1

I am trying to GET Walmart Seller API using CURL PHP to acknowledge. Can any one suggest which RSA PHP library i need to use ? So that Authentication Signature is verify while making calls to walmart.

Any one experience with this ?

$headers = array(
    'WM_SVC.NAME: Walmart Marketplace',
    'WM_QOS.CORRELATION_ID: 14730688612',
    'WM_SEC.TIMESTAMP:14730688612',
    'WM_SEC.AUTH_SIGNATURE: XXXXXXXXXXX'
    'WM_CONSUMER.ID: XXXXXXXXXXX',
    'Content-Type: application/xml',
    'Accept: application/xml',
 );


$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_URL,$requestUrl);
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$result = curl_exec( $ch );
if(curl_errno($ch)):
    echo 'Curl error: '.curl_error($ch);
endif;

I have used reference that found while googling.

 - https://github.com/fillup/walmart-auth-signature-php
Good Lux
  • 896
  • 9
  • 19
Zeolr
  • 11
  • 1
  • 4

4 Answers4

2

The hardest part about this is generating the signature and getting that to work properly.

I pulled a lot of these pieces from various spots to give a straight forward example so hopefully it will work.

Let say we want to make a GET call to get all of our feeds statuses.

// Your walmart info from walmart admin
$walmart_consuer_id = XXXXXXXXXXXXX;
$walmart_channel_type = XXXXXXXXXXXX;

$request_type = "GET";

$url = "https://marketplace.walmartapis.com/v2/feeds";

// We need a timestamp to generate the signature and to send as part of the header
$timestamp = round(microtime(true) * 1000);

$signature = getClientSignature($url, $request_type, $timestamp);

$headers = array();
$headers[] = "Accept: application/xml";
$headers[] = "WM_SVC.NAME: Walmart Marketplace";
$headers[] = "WM_CONSUMER.ID: ".$walmart_consuer_id;
$headers[] = "WM_SEC.TIMESTAMP: ".$timestamp;
$headers[] = "WM_SEC.AUTH_SIGNATURE: ".$signature;
$headers[] = "WM_QOS.CORRELATION_ID: ".mt_rand();
$headers[] = "WM_CONSUMER.CHANNEL.TYPE: " .$walmart_channel_type;

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_FAILONERROR, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $request_type);
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);

function getClientSignature($url, $request_type, $timestamp) {
  // Your walmart info from walmart admin
  $walmart_secret = XXXXXXXXXXXXXXXX;
  $walmart_consuer_id = XXXXXXXXXXXXX;

  // Get an openssl usable private key from the walmart supplied secret
  $pem = pkcs8_to_pem(base64_decode($walmart_secret));
  $private_key = openssl_pkey_get_private($pem);

  // Construct the data we want to sign
  $data = $walmart_consuer_id."\n";
  $data .= $url."\n";
  $data .= $request_type."\n";
  $data .= $timestamp."\n";

  // Sign the data
  $hash = defined("OPENSSL_ALGO_SHA256") ? OPENSSL_ALGO_SHA256 : "sha256";
  if (!openssl_sign($data, $signature, $private_key, $hash)) {
    // ERROR
    return null;
  }

  return base64_encode($signature);
}

function pkcs8_to_pem($der) {

  static $BEGIN_MARKER = "-----BEGIN PRIVATE KEY-----";
  static $END_MARKER = "-----END PRIVATE KEY-----";

  $value = base64_encode($der);

  $pem = $BEGIN_MARKER . "\n";
  $pem .= chunk_split($value, 64, "\n");
  $pem .= $END_MARKER . "\n";

  return $pem;
}
fr0x
  • 196
  • 1
  • 5
2

In the new API after August of 2018, you have to generate an access token AND then use a completely separate authentication header to pull anything from their API. It took a couple of hours just to figure this out, so I hope this helps someone in the future.

(This is for the Marketplace API, but should work for any Walmart API)

To generate the access token, you have to pass these headers:

Array(
[0] => Authorization: Basic BASE64_ENCODED_VARIABLE (see below)
[1] => Content-Type: application/x-www-form-urlencoded
[2] => Accept: application/json
[3] => WM_SVC.NAME: Walmart Marketplace
[4] => WM_QOS.CORRELATION_ID: 10_DIGIT_RANDOM_GENERATED_ALPHANUMERIC_ID
[5] => WM_SVC.VERSION: 1.0.0
[6] => WM_CONSUMER.CHANNEL.TYPE: PROVIDED_WHEN_GENERATING_CLIENT_ID_AND_SECRET
)

To generate BASE64_ENCODED_VARIABLE, create a variable using base64_encode as such:

$auth = base64_encode($clientId . ":" . $clientSecret);

...where Client ID and Client Secret are generated from Wal-Mart's Developer Portal API area.

===========================================

After you successfully POST that data to Walmart and receive an Access Token in return, you want to pass the following headers in ANY API CALL you make with Wal-Mart:

Array(
[0] => Authorization: Basic BASE64_ENCODED_VARIABLE (as described above)
[1] => WM_SVC.NAME: Walmart Marketplace
[2] => WM_QOS.CORRELATION_ID: 10_DIGIT_RANDOM_GENERATED_ALPHANUMERIC_ID
[3] => WM_CONSUMER.CHANNEL.TYPE: PROVIDED_WHEN_GENERATING_CLIENT_ID_AND_SECRET
[4] => WM_SEC.ACCESS_TOKEN: GENERATED_FROM_PREVIOUS_STEP (returned as [access_token])
[5] => Content-Type: application/json
[6] => Accept: application/json
)

...then make your calls.

This is what FINALLY worked for me after continuously receiving UNAUTHORIZED.GMP_GATEWAY_API errors across the board.

Passing "Authorization: Bearer TOKENTOKENTOKEN" instead of the way I've listed above WILL NOT WORK as the authentication header. Trust me :-)

TTUGoldFOX
  • 151
  • 9
0
<?php
$consumer_id='xxxxxxxxxx';
$private_key='xxxxxxxxxx';
$timestamp='xxxxxxxx';
$correlation_id='xxxxxxxxxxx';
$channel_id='xxxxxxxxxx';

$endPoint = "v3/feeds?feedType=item";
$requestUrl = "https://marketplace.walmartapis.com/$endPoint";
$requestMethod = 'POST';
$signature = new Signature($consumer_id, $private_key, $requestUrl,       $requestMethod);
$actual_signature = $signature->getSignature($timestamp);

$file = '..../walmart_product.xml';

$headers = [];
$headers[] = "WM_SVC.NAME: Walmart Marketplace";
$headers[] = "WM_QOS.CORRELATION_ID: ".$correlation_id;
$headers[] = "WM_SEC.TIMESTAMP: ".$timestamp;
$headers[] = "WM_SEC.AUTH_SIGNATURE: ".$actual_signature;
$headers[] = "WM_CONSUMER.ID: " .$consumer_id;
$headers[] = "Content-Type: multipart/form-data";
$headers[] = "Accept: application/xml";
$headers[] = "WM_CONSUMER.CHANNEL.TYPE: ".$channel_id;
$headers[] = "HOST: marketplace.walmartapis.com";


$body ['file'] = new \CurlFile ( $file, 'application/xml' );

$ch = curl_init ();
curl_setopt ( $ch, CURLOPT_URL, $requestUrl );
curl_setopt ( $ch, CURLOPT_HTTPHEADER, $headers );
curl_setopt ( $ch, CURLOPT_HEADER, 1 );
curl_setopt ( $ch, CURLOPT_POST, 1 );
curl_setopt ( $ch, CURLOPT_POSTFIELDS, $body );
curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, 0 );
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );
$server_output = curl_exec ( $ch );
?>
CedCommerce
  • 1
  • 4
  • 11
-1
$ch = curl_init();

$headers = $actual;

$qos = uniqid();

$url='https://api-gateway.walmart.com/v3/items';

$options = 
array (
    CURLOPT_URL => $url,

    CURLOPT_RETURNTRANSFER => true,

    CURLOPT_TIMEOUT => 60,

    CURLOPT_HEADER => false,

    CURLOPT_POST => 1,

    CURLOPT_HTTPHEADER => array(
    'WM_SVC.NAME: Drop Ship Vendor Services',

    'WM_QOS.CORRELATION_ID:'.$qos,

    'WM_SEC.TIMESTAMP:1451606400',

    'WM_SEC.AUTH_SIGNATURE: '.$headers,

    'WM_CONSUMER.ID:'.$WalmartConsumerID
,
    'WM_CONSUMER.CHANNEL.TYPE:**********',

    'Accept: application/xml'
        ),

    CURLOPT_HTTPGET => true
);

curl_setopt_array($ch, $options);

$response = curl_exec ($ch);

print_r($response);
S.I.
  • 3,250
  • 12
  • 48
  • 77