1

I’m trying to submit a SubmitFeed request to Amazon Marketplace, but when I submit the request I get the following error:

the Content-MD5 HTTP header you passed for your feed did not match the Content-MD5 we calculated for your feed

So I tested the request on the Amazon Marketplace Scratchpad. I add my XML to the body, and the headers, and it generates the following MD5 hash:

1db3b177e743dc8c0df4dc9eb5c1cbcf

But there’s also a Content-MD5 (Base64) header, with this value:

HbOxd+dD3IwN9NyetcHLzw==

And it appears to be that value that’s actually sent to Amazon MWS as the Content-MD5 HTTP header, not the raw MD5 hash.

I’ve checked my PHP script and it’s generating the raw MD5 hash correctly, as when I wrap my XML string in the md5 function (md5($xml)) I get the same raw MD5 hash that Amazon generates. But if I then wrap that in the base64_encode function, I get a totally different value as to what Amazon lists for the Content-MD5 (Base64) value.

So far, I’ve tried wrapping the following in the base64_encode function:

  • The raw XML string
  • The MD5 hash of the raw XML string

But none yield the same value as Amazon’s Content-MD5 (Base64) value.

So what exactly is Amazon Base64-encoding to get that value? I’ve tried decoding the value, but just got a load of random characters that appears to be an encoding issue, so I can’t see the raw string that Amazon’s encoding to point me in the right direction.

Any guidance on this would be appreciated.

Martin Bean
  • 38,379
  • 25
  • 128
  • 201

1 Answers1

3

Found the solution. I decided to look at the documentation for the md5 function and found there was a second parameter to get the raw output of the function, which is false by default. So, I decided to set that flag to true instead and Base64-encode the result of that call.

Voilà! I got the same Base64 value as Amazon!

Using Guzzle, this is what I’m sending to Amazon and I’m now getting successful responses:

$xml = trim($xml);

// For some reason, the time my PHP script is sending is about 20 minutes out
// from my system time. This fixes that.
$timestamp = gmdate('c', time() + 1200);

$url = 'https://mws.amazonservices.co.uk/';

$parameters = [
    'Action' => 'SubmitFeed',
    'AWSAccessKeyId' => '#MY_ACCESS_KEY_ID#',
    'FeedType' => '_POST_PRODUCT_DATA_',
    'MarketplaceIdList.Id.1' => 'A1F83G8C2ARO7P', # UK marketplace ID
    'Merchant' => '#MY_SELLER_ID#',
    'PurgeAndReplace' => 'false',
    'SignatureMethod' => 'HmacSHA256',
    'SignatureVersion' => '2',
    'Timestamp' => $timestamp,
    'Version' => '2009-01-01',
];

/**
 * Custom class that generates signature for request.
 *
 * @see http://stackoverflow.com/a/29724063/102205
 */
$signature = new Signature($url, $parameters, '#MY_SECRET_ACCESS_KEY#');

$parameters['Signature'] = (string) $signature;

try {
    $response = $this->client->post($url, [
        'headers' => [
            'Content-MD5' => base64_encode(md5($xml, true)),
            'User-Agent' => '#MY_USER_AGENT_STRING#',
        ],
        'query' => $parameters,
        'body' => $xml,
    ]);
} catch (\GuzzleHttp\Exception\ClientException $e) {
    $response = $e->getResponse();
}

return $response->xml();

Hope this helps someone else!

Martin Bean
  • 38,379
  • 25
  • 128
  • 201
  • Thanks for this! Although I'm using java, your info regarding performing the base64 on the raw data, rather than the md5 string was very useful and solved my problem as well. – ganta Jun 27 '15 at 01:31
  • Hi Martin Bean, I am also facing the same issue but i am using request module of node.js , i am using Meteor (Javascript). I have passed the base64 encoded md5content but getting the same error. Even if i not send the file in FeddContent than also its given me the same error .Please help me regarding this i shall be thankful to you for this. Its take 3 days but i havn't found any solution yet. Link of my asked question is:- http://stackoverflow.com/questions/40180070/amazon-mws-submitfeed-content-md5-http-header-did-not-match-the-content-md5-calc – Parveen yadav Oct 24 '16 at 06:22