亚马逊 MWS SubmitFeed Content-MD5 HTTP header 与亚马逊计算的 Content-MD5 不匹配
Amazon MWS SubmitFeed Content-MD5 HTTP header did not match the Content-MD5 calculated by Amazon
我知道这个问题并不新鲜,但我得到的所有解决方案都在 PHP 中,或者我的问题与他们不同。
我正在使用 MWS 提要 API 提交价格和数量更新的平面文件,但总是收到以下错误:
the Content-MD5 HTTP header you passed for your feed did not match the
Content-MD5 we calculated for your feed
我想问3个问题:-
ContentMD5Value 参数在文档中是可选的,但如果我没有通过它,它会说您必须输入 ContentMD5Value。
如文档中所示 ContentFeed
我们提供给亚马逊的。亚马逊为该文件创建 contentMD5
,然后将该 contentMD5
值与我们发送给亚马逊的 contentMD5
值进行比较。
如果两者匹配则确定,否则将抛出错误。但是,如果假设我不会发送文件,那么同样的错误也会出现,即 MD5 不匹配。这怎么可能?他们在为哪个文件计算 MD5?因为我还没有在ContentFeed
.
发送文件
如果我在 header 中发送 contentMD5
以及参数并在 body 中发送 ContentFeed
,我仍然收到错误.
注意:- 我在 header 中发送 contentMD5
以及使用请求模块在表单中的参数中,还使用该模块计算签名,然后传递 contentFeed
在 body.
我正在使用 JavaScript (Meteor),我使用 crpyto
模块计算 md5。
首先,我认为我的 md5 是错误的,但后来我尝试了一个在线网站,该网站会为我提供 md5 文件的 md5。
我的文件是:
MD5 value: d90e9cfde58aeba7ea7385b6d77a1f1e
Base64Encodevalue: ZDkwZTljZmRlNThhZWJhN2VhNzM4NWI2ZDc3YTFmMWU=
我为价格和数量更新下载的平面文件:-
https://sellercentral.amazon.in/gp/help/13461?ie=UTF8&Version=1&entries=0&
我在计算签名的时候也给了ContentMD5Value
计算了签名
FeedType:'_POST_FLAT_FILE_PRICEANDQUANTITYONLY_UPDATE_DATA_'
因为,我阅读了我在 headers 中传递 MD5-header 并作为参数发送的文档。
亚马逊文档说:
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.
我正在使用 request
模块进行 http 请求。
我正在以请求模块的形式传递所有必需的密钥、卖家 ID 等,并在 body 中传递 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,直接在
body,即:
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'
},
}
但每次都会出现同样的错误:
the Content-MD5 HTTP header you passed for your feed did not match the
Content-MD5 we calculated for your feed
我想知道我哪里做错了或者提交提要 API 并使用请求模块发送文件的正确方法是什么。
我也尝试使用 MWS 上给出的代码来生成 MD5 但相同
每次都出错。
我的.txt文件如下:
sku price quantity
TP-T2-00-M 2
非常感谢任何帮助
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
并生成字符串 '[object Object]'
.
Base64 编码字符串 always 生成您提到的 '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));
嘿,很抱歉回复晚了,但您为什么不尝试在请求模块的 'qs' 属性 中的表单数据请求和其他查询字符串中发送多部分文件。
您可以通过以下方式提交请求:-
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){
})
最后我得到了拉维上面所说的解决方案。 实际上,我想在这里为面临同样问题的所有人澄清几点:-
亚马逊市场API文档没有提供正确的信息和示例。即使我猜文档没有更新。正如在文档中,他们说 ContentMD5Value 参数值是可选的 on this page
你可以在那里查看,他们清楚地提到该字段不是必需的,但如果你没有通过,他们会给出你必须传递内容 MD5 值的错误。
So that is wrong. ContentMD5 is required attribute.
他们在同一份文档中说,您需要在字段键名中的 xml 或 flat-file 中发送文件数据,即 FeedContent
.
But that is also not needed you can send the file with any name no
need to give FeedContent
key for the file you just need to send the
file in stream.
他们会给出相同的错误,contentMD5 与您发送文件的天气不匹配,因为如果他们找不到文件,那么您发送的 contentMD5 将不匹配。因此,如果您收到 ContentMD5 不匹配错误,请检查以下内容:-
检查您是否为文件生成了正确的 MD5 代码,您可以通过 java 他们在文档中提供的代码来检查您是否生成了正确的代码。你可以从 this link
不要相信生成 MD5 哈希和 base64 编码的在线网站。
如果您的 MD5 与他们给出的 Java 代码生成的 MD5 相匹配,那么很明显您的 MD5 是正确的,因此无需更改。
一旦您的 MD5 正确,之后如果您遇到同样的错误,那就是:-
Amazon MWS SubmitFeed Content-MD5 HTTP header did not match the
Content-MD5 calculated by Amazon
ContentMD5 不匹配。您只需要检查文件上传机制。
因为现在您发送到亚马逊的文件不正确或者您发送的方式不正确。
检查文件上传
为了检查您是否发送了正确的文件,您需要检查以下内容:-
您需要发送所需的参数,如 sellerId、marketplaceId、AWSAccessKey 等作为查询参数。
您需要将 form-data 中的文件作为 multipart 发送,如果您使用的是 node.js 的请求模块,那么您可以看到 Ravi 给出的上述代码。
您需要将 header 设置为仅:-
'Content-Type': 'application/x-www-form-urlencoded'
无需将 header 以分块或制表符分隔等方式发送,因为我不再需要它们,它们甚至让我感到困惑,因为有人写的某个地方在其他地方使用此 header写使用这个 header。
所以最后我可以提交这个 API 我不需要任何 header 而不是 application/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.
创建contentMD5的代码是:-
var fileData= fs.readFileSync('/home/parveen/Downloads/test/feed.txt','utf8');
var contentMD5Value = crypto.createHash('md5').update(fileData).digest('base64');
因为我面临的问题是因为我通过请求模块同时使用表单和 form-data 所以我用 qs(查询字符串)转换我的表单数据并在 form-data 中作为多部分文件.
因此您可以通过这种方式成功提交 API 供提交。
可能我来晚了,但这里是 C# 的关键点:
1) 多部分表单数据根本不起作用。完成以下(简化):
HttpContent content = new StringContent(xmlStr, Encoding.UTF8, "application/xml");
HttpClient client = new HttpClient();
client.PostAsync(query, content)
2) 关于 query
:
UriBuilder builder = new UriBuilder("https://mws.amazonservices.com/");
NameValueCollection query = HttpUtility.ParseQueryString(builder.Query);
query["AwsAccessKeyId"] = your_key_str;
query["FeedType"] = "_POST_ORDER_FULFILLMENT_DATA_";
... other required params
query["ContentMD5Value"] = Md5Base64(xmlStr);
builder.Query = query.ToString();
query = builder.ToString();
3) 关于Md5base64
public static string Md5Base64(string xmlStr)
{
byte[] plainTextBytes = Encoding.UTF8.GetBytes(xmlStr);
MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
byte[] hash = provider.ComputeHash(plainTextBytes);
return Convert.ToBase64String(hash);
}
我知道这个问题并不新鲜,但我得到的所有解决方案都在 PHP 中,或者我的问题与他们不同。
我正在使用 MWS 提要 API 提交价格和数量更新的平面文件,但总是收到以下错误:
the Content-MD5 HTTP header you passed for your feed did not match the Content-MD5 we calculated for your feed
我想问3个问题:-
ContentMD5Value 参数在文档中是可选的,但如果我没有通过它,它会说您必须输入 ContentMD5Value。
如文档中所示
ContentFeed
我们提供给亚马逊的。亚马逊为该文件创建contentMD5
,然后将该contentMD5
值与我们发送给亚马逊的contentMD5
值进行比较。
如果两者匹配则确定,否则将抛出错误。但是,如果假设我不会发送文件,那么同样的错误也会出现,即 MD5 不匹配。这怎么可能?他们在为哪个文件计算 MD5?因为我还没有在ContentFeed
. 发送文件
如果我在 header 中发送
contentMD5
以及参数并在 body 中发送ContentFeed
,我仍然收到错误.
注意:- 我在 header 中发送 contentMD5
以及使用请求模块在表单中的参数中,还使用该模块计算签名,然后传递 contentFeed
在 body.
我正在使用 JavaScript (Meteor),我使用 crpyto
模块计算 md5。
首先,我认为我的 md5 是错误的,但后来我尝试了一个在线网站,该网站会为我提供 md5 文件的 md5。
我的文件是:
MD5 value: d90e9cfde58aeba7ea7385b6d77a1f1e
Base64Encodevalue: ZDkwZTljZmRlNThhZWJhN2VhNzM4NWI2ZDc3YTFmMWU=
我为价格和数量更新下载的平面文件:-
https://sellercentral.amazon.in/gp/help/13461?ie=UTF8&Version=1&entries=0&
我在计算签名的时候也给了ContentMD5Value
计算了签名
FeedType:'_POST_FLAT_FILE_PRICEANDQUANTITYONLY_UPDATE_DATA_'
因为,我阅读了我在 headers 中传递 MD5-header 并作为参数发送的文档。
亚马逊文档说:
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.
我正在使用 request
模块进行 http 请求。
我正在以请求模块的形式传递所有必需的密钥、卖家 ID 等,并在 body 中传递 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,直接在 body,即:
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'
},
}
但每次都会出现同样的错误:
the Content-MD5 HTTP header you passed for your feed did not match the Content-MD5 we calculated for your feed
我想知道我哪里做错了或者提交提要 API 并使用请求模块发送文件的正确方法是什么。
我也尝试使用 MWS 上给出的代码来生成 MD5 但相同 每次都出错。
我的.txt文件如下:
sku price quantity TP-T2-00-M 2
非常感谢任何帮助
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
并生成字符串 '[object Object]'
.
Base64 编码字符串 always 生成您提到的 '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));
嘿,很抱歉回复晚了,但您为什么不尝试在请求模块的 'qs' 属性 中的表单数据请求和其他查询字符串中发送多部分文件。 您可以通过以下方式提交请求:-
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){
})
最后我得到了拉维上面所说的解决方案。 实际上,我想在这里为面临同样问题的所有人澄清几点:-
亚马逊市场API文档没有提供正确的信息和示例。即使我猜文档没有更新。正如在文档中,他们说 ContentMD5Value 参数值是可选的 on this page
你可以在那里查看,他们清楚地提到该字段不是必需的,但如果你没有通过,他们会给出你必须传递内容 MD5 值的错误。
So that is wrong. ContentMD5 is required attribute.
他们在同一份文档中说,您需要在字段键名中的 xml 或 flat-file 中发送文件数据,即
FeedContent
.But that is also not needed you can send the file with any name no need to give
FeedContent
key for the file you just need to send the file in stream.他们会给出相同的错误,contentMD5 与您发送文件的天气不匹配,因为如果他们找不到文件,那么您发送的 contentMD5 将不匹配。因此,如果您收到 ContentMD5 不匹配错误,请检查以下内容:-
检查您是否为文件生成了正确的 MD5 代码,您可以通过 java 他们在文档中提供的代码来检查您是否生成了正确的代码。你可以从 this link
不要相信生成 MD5 哈希和 base64 编码的在线网站。
如果您的 MD5 与他们给出的 Java 代码生成的 MD5 相匹配,那么很明显您的 MD5 是正确的,因此无需更改。
一旦您的 MD5 正确,之后如果您遇到同样的错误,那就是:-
Amazon MWS SubmitFeed Content-MD5 HTTP header did not match the Content-MD5 calculated by Amazon
ContentMD5 不匹配。您只需要检查文件上传机制。 因为现在您发送到亚马逊的文件不正确或者您发送的方式不正确。
检查文件上传
为了检查您是否发送了正确的文件,您需要检查以下内容:-
您需要发送所需的参数,如 sellerId、marketplaceId、AWSAccessKey 等作为查询参数。
您需要将 form-data 中的文件作为 multipart 发送,如果您使用的是 node.js 的请求模块,那么您可以看到 Ravi 给出的上述代码。
您需要将 header 设置为仅:-
'Content-Type': 'application/x-www-form-urlencoded'
无需将 header 以分块或制表符分隔等方式发送,因为我不再需要它们,它们甚至让我感到困惑,因为有人写的某个地方在其他地方使用此 header写使用这个 header。 所以最后我可以提交这个 API 我不需要任何 header 而不是 application/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.
创建contentMD5的代码是:-
var fileData= fs.readFileSync('/home/parveen/Downloads/test/feed.txt','utf8');
var contentMD5Value = crypto.createHash('md5').update(fileData).digest('base64');
因为我面临的问题是因为我通过请求模块同时使用表单和 form-data 所以我用 qs(查询字符串)转换我的表单数据并在 form-data 中作为多部分文件.
因此您可以通过这种方式成功提交 API 供提交。
可能我来晚了,但这里是 C# 的关键点:
1) 多部分表单数据根本不起作用。完成以下(简化):
HttpContent content = new StringContent(xmlStr, Encoding.UTF8, "application/xml");
HttpClient client = new HttpClient();
client.PostAsync(query, content)
2) 关于 query
:
UriBuilder builder = new UriBuilder("https://mws.amazonservices.com/");
NameValueCollection query = HttpUtility.ParseQueryString(builder.Query);
query["AwsAccessKeyId"] = your_key_str;
query["FeedType"] = "_POST_ORDER_FULFILLMENT_DATA_";
... other required params
query["ContentMD5Value"] = Md5Base64(xmlStr);
builder.Query = query.ToString();
query = builder.ToString();
3) 关于Md5base64
public static string Md5Base64(string xmlStr)
{
byte[] plainTextBytes = Encoding.UTF8.GetBytes(xmlStr);
MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
byte[] hash = provider.ComputeHash(plainTextBytes);
return Convert.ToBase64String(hash);
}