web-dev-qa-db-ja.com

Amazon MWS SubmitFeed Content-MD5HTTPヘッダーがAmazonによって計算されたContent-MD5と一致しませんでした

私はこの質問が新しいものではないことを知っていますが、これに対して私が得るすべての解決策はPHPにあるか、私の問題はそれらとは異なります。

MWSフィードAPIを使用して、価格と数量の更新用のフラットファイルを送信していますが、常に次のエラーが発生します。

フィード用に渡したContent-MD5HTTPヘッダーが、フィード用に計算したContent-MD5と一致しませんでした


ここで3つの質問をしたいと思います:-

  1. ContentMD5Valueパラメーターは、ドキュメントに記載されているようにオプションですが、それを渡さなかった場合は、ContentMD5Valueを入力する必要があると表示されます。

  2. ドキュメントのように、Amazonに渡されるContentFeed。 Amazonは、そのファイルに対してcontentMD5を作成し、そのcontentMD5値をAmazonに送信するcontentMD5値と比較します。
    両方が一致する場合はOK、そうでない場合はエラーがスローされます。しかし、ファイルを送信しないとすると、MD5が一致しないという同じエラーが発生します。そんなことがあるものか?彼らはどのファイルのMD5を計算していますか? ContentFeedでファイルを送信していないためです。

  3. contentMD5をヘッダーとパラメーターで送信し、ContentFeedを本文で送信しても、エラーが発生します。

注:-リクエストモジュールを使用して、ヘッダーとパラメータでcontentMD5をフォームに送信し、それを使用して署名を計算してから、本文にcontentFeedを渡します。

JavaScript(Meteor)を使用していますが、crpytoモジュールを使用してmd5を計算しています。
最初に、私のmd5が間違っていると思いますが、次に、ファイルmd5のmd5を提供するオンラインWebサイトで試しました。

私のファイルは次のとおりです。

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ヘッダーを渡し、パラメーターとしても送信しました。

アマゾンドキュメントは言う:

以前は、AmazonMWSはMD5ハッシュをパラメーターではなくContent-MD5ヘッダーとして受け入れていました。これをパラメーターとして渡すと、MD5値がメソッドシグネチャの一部になり、ネットワーク上の誰もがフィードコンテンツを改ざんするのを防ぐことができます。

Amazon MWSは、ContentMD5Valueパラメーターが含まれているかどうかに関係なく、Content-MD5ヘッダーを引き続き受け入れます。ヘッダーとパラメーターの両方が使用されていて、それらが一致しない場合、InvalidParameterValueエラーが発生します。

httpリクエストにrequestモジュールを使用しています。

必要なすべてのキー、セラー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なしで試して、ファイル読み取りストリームを本文で直接送信しました。

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'
    },
}

しかし、毎回同じエラーが発生します。

フィード用に渡したContent-MD5HTTPヘッダーが、フィード用に計算したContent-MD5と一致しませんでした

どこで間違っているのか、フィードAPIを送信してリクエストモジュールを使用してファイルを送信する正しい方法を知りたいです。

また、MWSで提供されているコードを使用してMD5を生成しようとしましたが、毎回同じエラーが発生しました。

私の.txtファイルは次のとおりです:

 SKU価格数量
 TP-T2-00-M 2 

どんな助けでも大歓迎です

27
Parveen yadav

ついに私はラヴィが上で言ったように解決策を得ました。 実際、同じ問題に直面しているすべての人のために、ここでクリアしたい点がいくつかあります:-

1)AmazonマーケットプレイスAPIドキュメントは適切な情報と例を提供していません。私もドキュメントが更新されていないと思います。ドキュメントのように、ContentMD5Valueパラメータ値はオプションであると彼らは言いましたここにドキュメントのリンクがあります:-

http://docs.developer.amazonservices.com/en_US/feeds/Feeds_SubmitFeed.html

そこで確認できるのは、フィールドが必須ではないことを明確に示していることですが、合格しなかった場合は、コンテンツのMD5値を渡さなければならないというエラーが表示されます。

だからそれは間違っています。 ContentMD5は必須属性です。

2)同じドキュメントで、xmlまたはフラットファイルの天気予報でファイルデータを送信する必要があると言われましたフィールドキー名、つまりFeedContent

ただし、これも必要ありません。ファイルをストリームで送信するために必要なファイルのFeedContentキーを指定する必要はなく、任意の名前でファイルを送信できます。

3)送信したcontentMD5よりもファイルが見つからない場合、送信したcontentMD5がそれに一致しないため、ファイルを送信した天気と一致しない、または一致しないという同じエラーが発生します。 SO ContentMD5 not matchエラーが発生した場合は、以下を確認してください:-

1)ファイルに適切なMD5コードを生成していることを確認します。適切なコードを生成しているかどうかを確認できますJavaドキュメントに記載されているコード。できますリンクからそれを取得します:-

http://docs.developer.amazonservices.com/en_US/dev_guide/DG_MD5.html

2)MD5ハッシュとbase64エンコーディングを生成するためにオンラインWebサイトを信頼しないでください。

3)MD5がJavaコードから生成されたMD5と一致する場合、MD5が正しいことは明らかなので、変更する必要はありません。

4)MD5が正しければ、その後も同じエラーが発生した場合:-

Amazon MWS SubmitFeed Content-MD5HTTPヘッダーがAmazonによって計算されたContent-MD5と一致しませんでした

ContentMD5が一致しません。チェックする必要があるのはあなただけで、ファイルのアップロードメカニズムだけです。これは、Amazonに送信しているファイルが正しくないか、正しい方法で送信していないためです。

ファイルのアップロードを確認してください:-

正しいファイルを送信しているかどうかを確認するには、次のように確認する必要があります:-

1)sellerId、marketplaceId、AWSAccessKeyなどの必要なパラメーターをクエリパラメーターとして送信する必要があります。

2)node.jsのリクエストモジュールを使用している場合は、Raviによって提供された上記のコードを見ることができるよりも、フォームデータでファイルをマルチパートとして送信する必要があります。

3)ヘッダーを次のように設定する必要があります:-

'Content-Type': 'application/x-www-form-urlencoded'

ヘッダーをチャンクまたはタブ区切りなどで送信する必要はありません。これ以上必要ないため、誰かがこのヘッダーを使用している場所で誰かがこのヘッダーを使用しているため、混乱することさえあります。 最後に、このAPIを送信するのは難しいので、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');

リクエストモジュールを介してフォームとフォームデータを同時に使用しているため、問題に直面しているため、フォームデータをqs(クエリ文字列)で変換し、フォームデータ内のファイルをマルチパートとして変換します。

したがって、このようにして、フィード送信用のAPIを正常に送信できます。

どんな質問でも大歓迎ですありがとう

4
Parveen yadav

返信が遅れて申し訳ありませんが、フォームデータリクエストでファイルをマルチパートで送信し、リクエストモジュールの「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){

})
2
Ravi verma

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から継承され、文字列_'[object Object]'_を生成する場合、ObjecttoString()がファイルの内容を生成すると誤って想定します。

Base64-その文字列をエンコードする常にあなたが言及した_'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));
_
2
MasterAM

おそらく手遅れですが、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);
}
0
arudoy