Parveen yadav Parveen yadav - 25 days ago 10
Node.js Question

Amazon MWS SubmitFeed Content-MD5 HTTP header did not match the Content-MD5 calculated by Amazon

I know this question is not new but all the solution I get for this are in PHP or my issue is different from them.

I am using MWS feed API to submit flat file for Price and Quantity Updates and always 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





I would like to ask 3 questions here:-


  1. ContentMD5Value parameter is optional as given in doc, but if i not passed that than it will say that you must enter ContentMD5Value.

  2. As in doc the
    ContentFeed
    which we are given to Amazon. Amazon create
    contentMD5
    for that file and then compares that
    contentMD5
    value with the
    contentMD5
    value we send to Amazon.

    If both match then OK, otherwise it will throw an error. But if suppose I will not send the file then also the same errors come that MD5 does not match. How is that possible? Which file are they calculating the MD5 for? Because I haven't send the file in
    ContentFeed
    .

  3. If I send the
    contentMD5
    in a header as well as parameter and sending the
    ContentFeed
    in body, I still get the error.



Note:- I am sending the
contentMD5
in a header as well as in a parameters in form using request module and also calculating the signature with that and then pass the
contentFeed
in body.

I am using JavaScript (Meteor), I calculate the md5 using the
crpyto
module.

First, I think that my md5 is wrong but then I tried with an online website that will give me the md5 for a file the md5.

for my file is:


MD5 value: d90e9cfde58aeba7ea7385b6d77a1f1e

Base64Encodevalue: ZDkwZTljZmRlNThhZWJhN2VhNzM4NWI2ZDc3YTFmMWU=


The flat file I downloaded from for Price and Quantity Updates:-


https://sellercentral.amazon.in/gp/help/13461?ie=UTF8&Version=1&entries=0&


I calculated the signature also by giving
ContentMD5Value
while calculating the signature.


FeedType:'_POST_FLAT_FILE_PRICEANDQUANTITYONLY_UPDATE_DATA_'


As, I read documentation for that I passed the MD5-header in headers and also send as parameter.

Amazon doc says:


Previously, Amazon MWS accepted the MD5 hash as a Content-MD5 header
instead of a parameter. Passing it as a parameter ensures that the MD5
value is part of the method signature, which prevents anyone on the
network from tampering with the feed content.

Amazon MWS will still accept a Content-MD5 header whether or not a
ContentMD5Value parameter is included. If both a header and parameter
are used, and they do not match, you will receive an
InvalidParameterValue error.


I am using the
request
module for http requests.


I am passing all the required keys, seller id, etc. in form of request module and passing the
FeedContent
in body.

I tried sending the file as follows:

Method for submitFeed is:-

submitFeed : function(){
console.log("submitFeedAPI running..");
app = mwsReport({auth: {sellerId:'A4TUFSCXD64V3', accessKeyId:'AKIAJBU3FTBCJUIZWF', secretKey:'Eug7ZbaLljtrnGKGFT/DTH23HJ' }, marketplace: 'IN'});
app.submitFeedsAPI({FeedType:'_POST_FLAT_FILE_PRICEANDQUANTITYONLY_UPDATE_DATA_'},Meteor.bindEnvironment(function(err,response){
if(err){
console.log("error in submit feed...")
console.log(err)
}
else{
console.log("suuccess submit feed....")
console.log(response);
}
}))


Method that call Amazon submitFeedAPI is:-

var submitFeedsAPI = function(options, callback){
console.log("submitFeedsAPI running...");
var fileReadStream = fs.createReadStream('/home/parveen/Downloads/test/testting.txt');
var contentMD5Value = crypto.createHash('md5').update(file).digest('base64');

var reqForm = {query: {"Action": "SubmitFeed", "MarketplaceId": mpList[mpCur].id, "FeedType":options.FeedType,"PurgeAndReplace":false,"ContentMD5Value":contentMD5Value}};
mwsReqProcessor(reqForm, 'submitFeedsAPI', "submitFeedsAPIResponse", "submitFeedsAPIResult", "mwsprod-0000",false,file, callback);
}


also try

var fileReadStream = fs.createReadStream('/home/parveen/Downloads/test/testting.txt');
var base64Contents = fileReadStream.toString('base64');
var contentMD5Value = crypto.createHash('md5').update(base64Contents).digest('base64');


mwsReqProcessor function is as below:-

mwsReqProcessor = function mwsReqProcessor(reqForm, name, responseKey, resultKey, errorCode,reportFlag,file, callback) {

reqOpt = {
url: mwsReqUrl,
method: 'POST',
timeout: 40000,
body:{FeedContent: fs.readFileSync('/home/parveen/feedContentFile/Flat.File.PriceInventory.in.txt')},
json:true,
form: null,
headers: {
// 'Transfer-Encoding': 'chunked',
//'Content-Type': 'text/xml',
// 'Content-MD5':'ZDkwZTljZmRlNThhZWJhN2VhNzM4NWI2ZDc3YTFmMWU=',
// 'Content-Type': 'text/xml; charset=iso-8859-1'
'Content-Type':'text/tab-separated-values;charset=UTF-8'
},
}
reqOpt.form = mwsReqQryGen(reqForm);
var r = request(reqOpt, function (err, res, body){
console.log(err)
console.log(res)
})
// var form = r.form();
//form.append('FeedContent',fs.createReadStream('/home/parveen/feedContent//File/Flat.File.PriceInventory.in.txt'))
}


Method for mwsReqQryGen generation:-

mwsReqQryGen = function mwsReqQryGen(options) {
var method = (options && options.method) ? ('' + options.method) : 'POST',
host = (options && options.host) ? ('' + options.host) : mwsReqHost,
path = (options && options.path) ? ('' + options.path) : mwsReqPath,
query = (options && options.query) ? options.query : null,


returnData = {
"AWSAccessKeyId": authInfo.accessKeyId,
"SellerId": authInfo.sellerId,
"SignatureMethod": "HmacSHA256",
"SignatureVersion": "2",
"Timestamp": new Date().toISOString(),
"Version":"2009-01-01",
},
key;

if(query && typeof query === "object")
for(key in query)
if(query.hasOwnProperty(key)) returnData[key] = ('' + query[key]);

if(authInfo.secretKey && method && host && path) {

// Sort query parameters
var keys = [],
qry = {};

for(key in returnData)
if(returnData.hasOwnProperty(key)) keys.push(key);

keys = keys.sort();
for(key in keys)
if(keys.hasOwnProperty(key)) qry[keys[key]] = returnData[keys[key]];
var sign = [method, host, path, qs.stringify(qry)].join("\n");
console.log("..................................................")
returnData.Signature = mwsReqSignGen(sign);

}
//console.log(returnData); // for debug

return returnData;


};

I also tried with following:-

reqOpt = {
url: mwsReqUrl,
method: 'POST',
timeout: 40000,
json:true,
form: null,
body: {FeedContent: fs.createReadStream('/home/parveen/feedContentFile/Flat.File.PriceInventory.in.txt')},
headers: {
// 'Transfer-Encoding': 'chunked',
//'Content-Type': 'text/xml',
// 'Content-MD5':'ZDkwZTljZmRlNThhZWJhN2VhNzM4NWI2ZDc3YTFmMWU=',
// 'Content-Type': 'text/xml; charset=iso-8859-1'
},
}


I also tried without JSON and directly send the file read stream in the
body, i.e:

reqOpt = {
url: mwsReqUrl,
method: 'POST',
timeout: 40000,
form: null,
body: fs.createReadStream('/home/parveen/feedContentFile/Flat.File.PriceInventory.in.txt'),
headers: {
// 'Transfer-Encoding': 'chunked',
//'Content-Type': 'text/xml',
// 'Content-MD5':'ZDkwZTljZmRlNThhZWJhN2VhNzM4NWI2ZDc3YTFmMWU=',
// 'Content-Type': 'text/xml; charset=iso-8859-1'
},
}


But same error comes every time:


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


I want to know where I am doing wrong or what is the right way to submit feed API and sending the file using request module.

I also tried with the code given on MWS to generate the MD5 but same
error occurred each time.

My .txt file as follows:


sku price quantity
TP-T2-00-M 2


Any help is much appreciated

Answer

Hey sorry for late reply but why don't you try to send the file in multipart in the form-data request and other queryStrings in 'qs' property of request module. You can submit the request as follows:-

 reqOpt = {
   url: mwsReqUrl,
   method: 'POST',
   formData: {
      my_file: fs.createReadStream('file.txt')
  },
  headers: {
     'Content-Type': 'application/x-www-form-urlencoded'
  },
  qs: { 
     AWSAccessKeyId: '<your AWSAccessKeyId>',
     SellerId: '<your SellerId>',
     SignatureMethod: '<your SignatureMethod>',
     SignatureVersion: '<your SignatureVersion>',
     Timestamp: '<your Timestamp>',
     Version: '<your Version>',
     Action: 'SubmitFeed',
     MarketplaceId: '<your MarketplaceId>',
     FeedType: '_POST_FLAT_FILE_PRICEANDQUANTITYONLY_UPDATE_DATA_',
     PurgeAndReplace: 'false',
     ContentMD5Value: '<your file.txt ContentMD5Value>',
     Signature: '<your Signature>'
 }
}

request(reqOpt, function(err, res){

})