Amazon MWS SubmitFeed Content-MD5 HTTP标头与Amazon计算的Content-MD5不匹配
我知道这个问题不是新的,但我得到的所有解决scheme都是在PHP中,或者我的问题与他们不同。
我正在使用MWS提要API提交价格和数量更新的平面文件,并始终得到以下错误:
您为Feed提交的Content-MD5 HTTP标头与我们为您的Feed计算的Content-MD5不匹配
我想在这里问3个问题:
-
ContentMD5Value参数是doc中给出的可选参数,但是如果我没有通过,那么将会说您必须inputContentMD5Value。
-
正如在doc中我们给亚马逊的
ContentFeed
。 Amazon为该文件创buildcontentMD5
,然后将contentMD5
值与我们发送给Amazon的contentMD5
值进行比较。
如果两者匹配则OK,否则会抛出错误。 但是,如果假设我不会发送该文件,那么也会出现与MD5不匹配的错误。 这怎么可能? 他们计算MD5的文件是哪个? 因为我没有在ContentFeed
发送文件。 -
如果我发送
contentMD5
头和参数,并发送ContentFeed
的身体,我仍然得到错误。
注意: – 我使用请求模块将头文件中的contentMD5
以及表单中的参数发送contentFeed
,然后使用该模块计算签名,然后传入contentFeed
。
我正在使用JavaScript(Meteor),我使用crpyto
模块来计算md5。
首先,我认为我的md5是错误的,但后来我尝试了一个在线网站,它会给我一个md5文件的md5。
对于我的文件是:
MD5值:d90e9cfde58aeba7ea7385b6d77a1f1e
Base64Encodevalue:ZDkwZTljZmRlNThhZWJhN2VhNzM4NWI2ZDc3YTFmMWU =
我从价格和数量更新下载的平面文件: –
https://sellercentral.amazon.in/gp/help/13461?ie=UTF8&Version=1&entries=0&
我在计算签名时也通过给ContentMD5Value
计算签名。
的FeedType: '_ POST_FLAT_FILE_PRICEANDQUANTITYONLY_UPDATE_DATA_'
至于,我阅读文档,我在标题中传递的MD5头,也作为参数发送。
亚马逊文件说:
以前,亚马逊MWS接受MD5哈希作为Content-MD5头而不是参数。 将它作为parameter passing可确保MD5值是方法签名的一部分,从而防止networking上的任何人篡改提要内容。
无论是否包含ContentMD5Value参数,亚马逊MWS仍将接受Content-MD5头。 如果使用头和参数,并且它们不匹配,则会收到InvalidParameterValue错误。
我正在使用http请求的request
模块。
我以请求模块的forms传递所有必需的密钥,卖方id等,并将FeedContent
传递给主体。
我试着发送文件如下:
submitFeed的方法是: –
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); } }))
调用Amazon submitFeedAPI的方法是:
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函数如下: –
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')) }
mwsReqQryGen代的方法: –
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;
};
我也试过以下内容:
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' }, }
我也试过没有JSON,直接发送文件读取stream在身体,即:
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' }, }
但每次都出现同样的错误:
您为Feed提交的Content-MD5 HTTP头与我们为您的Feed计算的Content-MD5不匹配
我想知道我在哪里做错了什么是正确的方式来提交饲料API和使用请求模块发送文件。
我也尝试用MWS给出的代码生成MD5,但每次都发生相同的错误。
我的.txt文件如下:
sku价格数量 TP-T2-00-M 2
任何帮助深表感谢
嘿抱歉,迟到的答复,但你为什么不尝试在请求模块的'qs'属性中的表单数据请求和其他queryStrings多部分发送文件。 您可以按如下方式提交请求: –
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){ })
最后我得到了解决scheme,正如Ravi上面所说的。 其实,我想在这里为您清楚的expression同样的问题:
1)亚马逊marketplace API文件没有给出适当的信息和例子 。 即使我猜文档没有更新。 正如在文档中他们说,ContentMD5Value参数值是可选的, 这里是doc的链接: –
http://docs.developer.amazonservices.com/en_US/feeds/Feeds_SubmitFeed.html
你可以在那里查到他们明确提到这个字段不是必需的,但是如果你不通过,那么他们给出的错误是你必须通过内容MD5的值。
所以这是错的。 ContentMD5是必需的属性。
2)他们说,在同一个文档中,你需要发送文件数据天气的XML或平面文件的字段键名称,即FeedContent 。
但是这也不是必须的,你可以用任何名字发送文件,不需要给文件的FeedContent键,只需要发送文件。
3)他们会给内容相同的错误MD5不符合你发送文件的天气,因为如果他们没有发现文件比你发送的内容MD5不匹配。 所以如果你得到的ContentMD5不匹配的错误比检查以下内容: –
1)检查你是否为你的文件生成了正确的MD5代码,你可以通过它们在doc上给出的java代码来检查你是否生成了正确的代码。 你可以从链接中获得: –
http://docs.developer.amazonservices.com/en_US/dev_guide/DG_MD5.html
2)不要相信在线网站上生成MD5哈希和base64编码。
3)如果您的MD5与从Java代码生成的MD5相匹配,那么他们给出的一件事情很清楚,您的MD5是正确的,所以不需要改变。
4)一旦你的MD5是正确的,在此之后,如果你得到相同的错误是: –
Amazon MWS SubmitFeed Content-MD5 HTTP标头与Amazon计算的Content-MD5不匹配
ContentMD5不匹配。只需要检查file upload机制。 因为现在你发送给亚马逊的文件不正确,或者你不是以正确的方式发送的。
检查file upload: –
为了检查是否你正在发送正确的文件,你需要检查以下内容:
1)您需要发送所需的参数,如sellerId,marketplaceId,AWSAccessKey等作为查询参数。
2)如果使用node.js的请求模块,则需要将form-data中的文件作为multipart发送,而不是您可以看到Ravi给出的上述代码。
3)您只需将标题设置为: –
'Content-Type':'application / x-www-form-urlencoded'
没有必要发送头分块或制表符分隔等,因为我不再需要他们,他们甚至迷惑我,因为某个地方有人写在别的地方使用这个头在别人的地方使用这个头。 所以最后,因为我abel提交这个API我不需要任何头,而不是应用程序/ x-www-form-urlencoded。
例:-
reqOpt = { url: mwsReqUrl, method: 'POST', formData: { my_file: fs.createReadStream('file.txt') }, headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, qs: { }// all the parameters that you are using while creating signature.
创build内容MD5的代码是: –
var fileData= fs.readFileSync('/home/parveen/Downloads/test/feed.txt','utf8'); var contentMD5Value = crypto.createHash('md5').update(fileData).digest('base64');
由于我面临的问题,因为我通过请求模块同时使用窗体和表单数据,所以我转换我的表单数据与qs(查询string)和文件forms数据为多部分。
因此,您可以通过这种方式成功提交用于提交Feed的API。
任何疑问,非常欢迎谢谢
Amazon需要使用base64编码的文件的md5散列。
你的代码:
var fileReadStream = fs.createReadStream('/path/to/file.txt'); var file = fileReadStream.toString('base64'); //'[object Object]' var contentMD5Value = crypto.createHash('md5').update(file).digest('base64');
错误地假设一个readStream
的toString()
会产生文件内容,实际上,这个方法是从Object
inheritance而来的,并产生string'[object Object]'
。
Base64编码的string总是产生你提到的'FEGnkJwIfbvnzlmIG534uQ=='
。
如果您想正确读取和编码哈希,您可以执行以下操作:
var fileContents = fs.readFileSync('/path/to/file.txt'); // produces a byte Buffer var contentMD5Value = crypto.createHash('md5').update(fileContents).digest('base64'); // properly encoded
它提供的结果等同于以下PHP片段:
$contentMD5Value = base64_encode(md5_file('/path/to/file.txt', true));