1
votes

I am wondering if someone could help.

I am trying to list a product on Amazon through the API.

When using GetOrders it works perfectly but with similar code apart from the parameters I get the following error message when using SubmitFeed _POST_PRODUCT_DATA_

"Sender SignatureDoesNotMatch The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details."

All my details are correct, the secret key, aws access key etc. and I have compared the string to sign in my code to the one that is generated in the Amazon API test tool and they are exactly the same so I am not sure what the problem is.

Here is the code I am using -

$timestamp = date('c', strtotime($todays_date_time));
$timestamp = gmdate('Y-m-d\TH:i:s\Z', strtotime($timestamp));

$params = array(
    'AWSAccessKeyId' => "MY_AWS_KEY",
    'Action' => "SubmitFeed",
    'Merchant' => "MY_SELLER_ID",
    'FeedType' => "_POST_PRODUCT_DATA_",
    'SignatureMethod' => "HmacSHA256",
    'SignatureVersion' => "2",
    'Timestamp'=> $timestamp,
    'Version'=> "2009-01-01",
    'MarketplaceIdList.Id.1' => "MY_MARKETPLACE_ID",
    'PurgeAndReplace'=>'false'
);

$secret = 'MY_SECRET_KEY';

$url_parts = array();

foreach(array_keys($params) as $key) {

    $url_parts[] = $key . "=" . str_replace('%7E', '~', rawurlencode($params[$key]));

}

Then here I create the XML and store it in the variable $amazon_feed and then -

sort($url_parts);

$url_string = implode("&", $url_parts);
$string_to_sign = "POST\nmws.amazonservices.co.uk\n/\n" . $url_string;

$signature = hash_hmac("sha256", $string_to_sign, $secret, TRUE);

$http_header     =   array();
$http_header[]   =   'Transfer-Encoding: chunked';
$http_header[]   =   'Content-Type: application/xml';
$http_header[]   =   'Content-MD5: ' . base64_encode(md5($amazon_feed, true));
$http_header[]   =   'Expect:';
$http_header[]   =   'Accept:';

$signature = urlencode(base64_encode($signature));

$link = "https://mws.amazonservices.co.uk/Feeds/2009-01-01?".$url_string."&Signature=".$signature;

$ch = curl_init($link);
curl_setopt($ch, CURLOPT_HTTPHEADER, $http_header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); 
curl_setopt($ch, CURLOPT_POST, 1); 
curl_setopt($ch, CURLOPT_POSTFIELDS, $amazon_feed); 
$response = curl_exec($ch);

print_r($response);

$info = curl_getinfo($ch);
curl_close($ch);

Would anyone be able to help?

1
I had this issue not so long back. Have a look at this question (and answer) and see if it helps you: stackoverflow.com/questions/29679646/…Martin Bean

1 Answers

1
votes

You will have to ksort() your params before you pass them here:

foreach(array_keys($params) as $key) {

    $url_parts[] = $key . "=" . str_replace('%7E', '~', rawurlencode($params[$key]));

}

e.g.

$params = array(
    'AWSAccessKeyId' => "MY_AWS_KEY",
    'Action' => "SubmitFeed",
    'SellerId' => "MY_SELLER_ID",
    'FeedType' => "_POST_PRODUCT_DATA_",
    'SignatureMethod' => "HmacSHA256",
    'SignatureVersion' => "2",
    'Timestamp'=> $timestamp,
    'Version'=> "2009-01-01",
    'MarketplaceIdList.Id.1' => "MY_MARKETPLACE_ID",
    'PurgeAndReplace'=>'false'
);

$secret = 'MY_SECRET_KEY';
$url_parts = array();
ksort($params);
foreach(array_keys($params) as $key) {

    $url_parts[] = $key . "=" . str_replace('%7E', '~', rawurlencode($params[$key]));

}

I'm not entirely sure about the string you are signing, you should try it with this (adding /Feeds/2009-01-01 to it):

"POST\nmws-eu.amazonservices.com\n/Feeds/2009-01-01\n" . $url_string

Also, Amazon expects a SellerId for the _POST_PRODUCT_DATA_ operation, not Merchant.

I suggest you to use mws-eu-amazonservices.com instead of the co.uk one, you can use this for all the european marketplaces and don't need to change it for each. As a sidenote:

Amazon doesn't really report the correct error. The error you are getting can also occur if only SellerId is Merchant like above, or anything different that has nothing to do with what you are trying to do.