node.js - El encabezado HTTP de Amazon MWS SubmitFeed Content-MD5 no coincide con el Content-MD5 calculado por Amazon
meteor amazon-mws (3)
Amazon requiere el hash md5 del archivo en la codificación base64.
Tu codigo:
var fileReadStream = fs.createReadStream(''/path/to/file.txt'');
var file = fileReadStream.toString(''base64''); //''[object Object]''
var contentMD5Value = crypto.createHash(''md5'').update(file).digest(''base64'');
asume erróneamente que un toString()
readStream
producirá el contenido del archivo, cuando, de hecho, este método se hereda de Object
y produce la cadena ''[object Object]''
.
La codificación de Base64 esa cadena siempre produce el ''FEGnkJwIfbvnzlmIG534uQ==''
que usted mencionó.
Si desea leer y codificar correctamente el hash, puede hacer lo siguiente:
var fileContents = fs.readFileSync(''/path/to/file.txt''); // produces a byte Buffer
var contentMD5Value = crypto.createHash(''md5'').update(fileContents).digest(''base64''); // properly encoded
que proporciona resultados equivalentes al siguiente fragmento de PHP:
$contentMD5Value = base64_encode(md5_file(''/path/to/file.txt'', true));
Sé que esta pregunta no es nueva, pero toda la solución que recibo para esto está en PHP o mi problema es diferente de ellos.
Estoy usando la API de feed MWS para enviar un archivo plano de actualizaciones de precio y cantidad y siempre aparece el siguiente error:
el encabezado HTTP Content-MD5 que aprobó para su feed no coincide con el Content-MD5 que calculamos para su feed
Me gustaría hacer 3 preguntas aquí:
El parámetro ContentMD5Value es opcional como se indica en el documento, pero si no lo aprobé entonces dirá que debe ingresar ContentMD5Value.
Como en doc the
ContentFeed
que se nos da a Amazon. Amazon creacontentMD5
para ese archivo y luego compara ese valor decontentMD5
con el valor decontentMD5
que enviamos a Amazon.
Si ambos coinciden, entonces OK, de lo contrario arrojará un error. Pero si supongo que no enviaré el archivo, también surgen los mismos errores que MD5 no coincide. ¿Cómo es eso posible? ¿Para qué archivo están calculando el MD5? Porque no he enviado el archivo enContentFeed
.Si envío el
contentMD5
en un encabezado, así como el parámetro y el envío deContentFeed
en el cuerpo, sigo recibiendo el error.
Nota: - Estoy enviando el contentMD5
en un encabezado, así como también en un formulario de parámetros usando el módulo de solicitud y también calculando la firma con eso y luego paso el contentFeed
la contentFeed
en el cuerpo.
Estoy usando JavaScript (Meteor), calculo el md5 usando el módulo crpyto
.
Primero, creo que mi md5 está mal, pero luego probé con un sitio web en línea que me daría el md5 para un archivo md5.
para mi archivo es:
Valor MD5: d90e9cfde58aeba7ea7385b6d77a1f1e
Base64Encodevalue: ZDkwZTljZmRlNThhZWJhN2VhNzM4NWI2ZDc3YTFmMWU =
El archivo plano que descargué de las Actualizaciones de precio y cantidad: -
https://sellercentral.amazon.in/gp/help/13461?ie=UTF8&Version=1&entries=0&
Calculé la firma también dando ContentMD5Value
mientras calculaba la firma.
FeedType: ''_ POST_FLAT_FILE_PRICEANDQUANTITYONLY_UPDATE_DATA_''
Como, leí documentación para eso pasé el encabezado MD5 en los encabezados y también lo envié como parámetro.
El documento de Amazon dice:
Anteriormente, Amazon MWS aceptaba el hash MD5 como un encabezado Content-MD5 en lugar de un parámetro. Pasarlo como un parámetro garantiza que el valor MD5 sea parte de la firma del método, lo que evita que cualquiera en la red altere el contenido del feed.
Amazon MWS seguirá aceptando un encabezado Content-MD5 independientemente de si se incluye un parámetro ContentMD5Value. Si se usan tanto un encabezado como un parámetro, y no coinciden, recibirá un error InvalidParameterValue.
Estoy usando el módulo de request
para solicitudes http.
Estoy pasando todas las claves requeridas, identificación del vendedor, etc. en forma de módulo de solicitud y pasando el FeedContent
la FeedContent
en el cuerpo.
Intenté enviar el archivo de la siguiente manera:
El método para submitFeed es:
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);
}
}))
El método que llama a Amazon submitFeedAPI es: -
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'');
La función mwsReqProcessor es la siguiente:
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''))
}
Método para la generación de 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;
};
También probé con los siguientes:
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''
},
}
También probé sin JSON y envié directamente la secuencia de lectura del archivo en el cuerpo, es decir:
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''
},
}
Pero el mismo error viene cada vez:
el encabezado HTTP Content-MD5 que aprobó para su feed no coincide con el Content-MD5 que calculamos para su feed
Quiero saber dónde estoy haciendo mal o cuál es la forma correcta de enviar API de feed y enviar el archivo utilizando el módulo de solicitud.
También probé con el código proporcionado en MWS para generar el MD5 pero el mismo error ocurrió cada vez.
Mi archivo .txt de la siguiente manera:
sku price quantity TP-T2-00-M 2
Cualquier ayuda es muy apreciada
Hola, lo siento por la respuesta tardía, pero ¿por qué no intenta enviar el archivo en varias partes en la solicitud de datos del formulario y otras cadenas de consulta en la propiedad ''qs'' del módulo de solicitud. Puede enviar la solicitud de la siguiente manera:
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){
})
finalmente obtuve la solución como dijo Ravi arriba. De hecho, hay algunos puntos que quiero aclarar aquí para todos ustedes que enfrentan el mismo problema:
1) El API API del mercado de Amazon no proporciona la información y el ejemplo adecuados . Incluso supongo que la documentación no está actualizada. Como en el documento, dijeron que el valor del parámetro ContentMD5Value es opcional, aquí está el enlace para el documento: -
http://docs.developer.amazonservices.com/en_US/feeds/Feeds_SubmitFeed.html
Puede verificar que mencionen claramente que el campo no es obligatorio, pero si no pasa, le dan el error de que debe pasar el contenido MD5.
Entonces eso está mal. ContentMD5 es un atributo obligatorio.
2) Dijeron en el mismo documento que necesita enviar los datos de los archivos es un xml o archivo plano en el nombre de la clave de campo, es decir, FeedContent .
Pero eso tampoco es necesario. Puede enviar el archivo con cualquier nombre. No es necesario que proporcione la clave de contenido de contenido para el archivo que solo necesita para enviar el archivo en flujo.
3) Te darán el mismo error de contenidoMD5 no coinciden con el clima en el que envías el archivo o no, porque si no encuentran el archivo que el contentMD5 que envías no coincidirá con eso. ENTONCES, si obtiene el error ContentMD5 no coincide, compruebe lo siguiente:
1) Verifique que está generando el código MD5 correcto para su archivo, puede verificar si está generando el código correcto o no con el código java que le dieron en el documento. Puedes obtenerlo del enlace:
http://docs.developer.amazonservices.com/en_US/dev_guide/DG_MD5.html
2) No confíe en los sitios web en línea para generar el hash MD5 y la codificación base64.
3) Si su MD5 coincide con el MD5 generado a partir del código de Java, dado que una cosa está clara es que su MD5 es correcto, por lo que no es necesario cambiar con eso.
4) Una vez que su MD5 es correcto y después de eso también si obtiene el mismo error que es: -
El encabezado HTTP de Amazon MWS SubmitFeed Content-MD5 no coincide con el Content-MD5 calculado por Amazon
ContentMD5 no coincide. Lo que necesita es verificar solo y solo el mecanismo de carga de archivos. Porque ahora el archivo que está enviando a Amazon no es correcto o no lo está enviando de la manera correcta.
Verifique la carga de archivos: -
Para verificar si está enviando el archivo correcto o no, debe verificar con los siguientes:
1) Debe enviar los parámetros requeridos, como sellerId, marketplaceId, AWSAccessKey, etc. como parámetros de consulta.
2) Debe enviar el archivo en los datos del formulario como multiparte, si está utilizando el módulo de solicitud de node.js de lo que puede ver el código anterior proporcionado por Ravi.
3) debe configurar el encabezado solo como: -
''Content-Type'': ''application / x-www-form-urlencoded''
No es necesario enviar el encabezado como separado o tabular, etc., porque no los necesito más, incluso me confunden porque en algún lugar alguien escribe usando este encabezado en otro lugar donde alguien escriba use este encabezado. Finalmente, como soy capaz de enviar esta API, no necesitaba el encabezado en lugar de application / x-www-form-urlencoded.
Ejemplo:-
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.
El código para crear el contentMD5 es:
var fileData= fs.readFileSync(''/home/parveen/Downloads/test/feed.txt'',''utf8'');
var contentMD5Value = crypto.createHash(''md5'').update(fileData).digest(''base64'');
Como me enfrento al problema, es porque estoy usando formulario y datos de formulario simultáneamente a través del módulo de solicitud, así que convierto los datos de mi formulario con qs (cadena de consulta) y el archivo en formulario-datos como multiparte.
De esta forma, puede enviar la API para enviar el feed.
Cualquier consulta es bienvenida