MWS Post 请求 Google 脚本

MWS Post Request with Google Scripts

我正在尝试通过 google 脚本向亚马逊发出 post 请求以收集信息。

我们正在尝试将我们的订单发送到 MWS 并自动将它们转移到表格中。

我进行了签署请求的最后一步。

一些我不确定的事情:

  1. 他们说我们使用密钥进行散列,我只看到一个客户端密钥 和访问密钥 ID,我应该使用哪个?
  2. 我是否添加 URL 作为签名的一部分?在 MWS Scratch pad 上,他们添加如下所示:

POST mws.amazonservices.com /Orders/2013-09-01

是否必须在不同的行上,是否需要 post 和其他内容。有点看不懂?

  1. 我在网上看到 sha256 字节码得到 base64 编码,而不是字符串文字,是这样吗?
  2. 我尝试使用在线工具对亚马逊提供给我的字符串进行哈希处理,并将其与他们提供的哈希和 base64 编码进行比较,结果匹配。我也试过解码,没有匹配的

谁能给我一个有效的例子,这样我就能理解发生了什么以及它是如何工作的?

谢谢!

以下是我目前所拥有的:

function POSTRequest() {

  var url = 'https:mws.amazonservices.com/Orders/2013-09-01?';

  var today = new Date();
  var todayTime = ISODateString(today);

  var yesterday = new Date();
  yesterday.setDate(today.getDate() - 1);
  yesterday.setHours(0,0,0,0);
  var yesterdayTime = ISODateString(yesterday); 

  var dayBeforeYesterday = new Date();
  dayBeforeYesterday.setDate(today.getDate() - 2);
  dayBeforeYesterday.setHours(0,0,0,0);
  var dayBeforeYesterdayTime = ISODateString(dayBeforeYesterday); 

  var unsignedURL = 
  'POST\r\nhttps:mws.amazonservices.com\r\n/Orders/2013-09-01\r\n'+
  'AWSAccessKeyId=xxxxxxxxxxx' +
  '&Action=ListOrders'+
  '&CreatedAfter=' + dayBeforeYesterdayTime +
  '&CreatedBefore' + yesterdayTime +
  '&FulfillmentChannel.Channel.1=AFN' +
  '&MWSAuthToken=xxxxxxxxxxxx'+
  '&MarketplaceId.Id.1=ATVPDKIKX0DER' +
  '&SellerId=xxxxxxxxxxx'+
  '&SignatureMethod=HmacSHA256'+
  '&SignatureVersion=2'+
  '&Timestamp='+ ISODateString(new Date) + 
  '&Version=2013-09-0';

  var formData = {
        'AWSAccessKeyId' : 'xxxxxxxxx',
        'Action' : "ListOrders",
        'CreatedAfter' : dayBeforeYesterdayTime,
        'CreatedBefore' : yesterdayTime,
        'FulfillmentChannel.Channel.1' : 'AFN',
        'MWSAuthToken' : 'xxxxxxxxxxxx',
        'MarketplaceId.Id.1' : 'ATVPDKIKX0DER',
        'SellerId' : 'xxxxxxxxxx',
        'SignatureMethod' : 'HmacSHA256',
        'SignatureVersion' : '2',
        'Timestamp' : ISODateString(new Date),
        'Version' : '2013-09-01',
        'Signature' : calculatedSignature(unsignedURL)

      };

   var options = {
     "method" : "post",
     "muteHttpExceptions" : true,
     "payload" : formData
   };


  var result = UrlFetchApp.fetch(url, options);
  writeDataToXML(result);
  Logger.log(result);


  if (result.getResponseCode() == 200) {
  writeDataToXML(result);
  }
}




function calculatedSignature(url) {
var urlToSign = url;
var secret = "xxxxxxxxxxxxxxxxxxx";
var accesskeyid = 'xxxxxxxxxxxxxxx';

  var byteSignature = Utilities.computeHmacSha256Signature(urlToSign, secret);
// convert byte array to hex string
var signature = byteSignature.reduce(function(str,chr){
  chr = (chr < 0 ? chr + 256 : chr).toString(16);
  return str + (chr.length==1?'0':'') + chr;
},'');


  Logger.log("URL to sign: " + urlToSign);
  Logger.log("");
  Logger.log("byte " + byteSignature);
  Logger.log("");
  Logger.log("reg " + signature);

var byte64 =  Utilities.base64Encode(byteSignature)
Logger.log("base64 byte " + Utilities.base64Encode(byteSignature));
  Logger.log("");
Logger.log("base64 reg " + Utilities.base64Encode(signature)); 

 return byte64;
}

第一步,创建待签名字符串

string_to_sign是以下组合:

  • 字符串 POST 后跟一个 NEWLINE 字符
  • 主机名,mws.amazonservices.com,后跟 NEWLINE
  • API URL,通常只是 /,或 /Orders/2013-09-01 之类的东西,后跟 NEWLINE
  • URL 编码中除 Signature 之外的所有参数的字母顺序列表,如 a=1&b=2,后面没有任何内容

最小的参数好像是:

  • AWSAccessKeyId是亚马逊提供的20个字符的代码
  • Action 是您的 API 电话的名称,例如 GetReport
  • SellerId 是您的 14 个字符的卖家 ID
  • SignatureMethodHmacSHA256
  • SignatureVersion2
  • Timestamp 是像 20181231T23:59:59Z 这样的日期,在新年前一秒 UTC
  • Version 是像 2013-09-01
  • 这样的 API 版本
  • 根据 Action
  • 的值,您的调用可能需要 其他参数

请注意:

  • NEWLINE字符只是“\n”,而不是“\r\n”
  • 主机名称应包括"https://"或"http://"
  • Signature 参数对于稍后的实际调用是必需的(参见第 3 步),但 不是 string_to_sign.[=111 的一部分=]

您的 string_to_sign 现在应该看起来像这样:

POST
mws.amazonservices.com
/Orders/2013-09-01
AWSAccessKeyId=12345678901234567890&Action=ListOrders&CreatedAfter .... &Version=2013-09-01

第 2 步,对该字符串签名

  • 使用 40 个字符 Secret Key
  • 计算上述字符串的 SHA256 散列
  • 使用 Base64 编码此散列
  • 在伪代码中:signature = Base64encode( SHA256( string_to_sign, secret_key ))

第3步,发送呼叫

发送 HTTPS POST 请求,使用参数的完整字母顺序列表,现在 包括 上面的签名作为 Signature 在中间的某个地方,因为你需要保持升序字母顺序。

https://mws.amazonservices.com/Orders/2013-09-01?AWSAccessKeyId....Version=2013-09-01

第四步,处理结果

您应该得到两样东西:回复 header 和 XML 文档。请务必评估 header 中的 HTTP 状态以及 XML 文档的所有内容。一些错误消息隐藏在 XML 中,而 HTTP returns "200 OK".

第 5 步,高级内容

如果您使用需要发送文件的电话,例如 SendFeed,您需要执行以下附加步骤:

  • 计算文档的 MD5 哈希值
  • 使用 Base64 编码此散列
  • 在伪代码中:contentmd5= Base64encode( MD5( document ))
  • 添加 Content-Type: text/xml(或任何适合您文档的内容)作为 HTTP header
  • 添加 Content-MD5: 加上 base64 编码的哈希作为 HTTP header

这段代码对构建类似的应用程序很有帮助。我纠正了一些小问题以使其正常工作:

在签署 ISODate 之前需要计算出替换“:”字符

  var todayTime = ISODateString(today);
  var todayISO = todayTime;


  var todayTime_ = todayTime.replace(":", "%3A");
  todayTime = todayTime_.replace(":","%3A");

计算出的签名也一样(快速和肮脏的解决方案,只替换 3 次出现,需要更新更多字符)


  Logger.log(unsignedURL);

  var tmpsignature = calculatedSignature(unsignedURL);

  var orsignature = tmpsignature;


// encode special chars
tmpsignature = encodeURIComponent(orsignature);
  }

我加了一个header,去掉了表格,把所有的参数都放在了url

var header = {
     "x-amazon-user-agent": "GoogleSheets/1.0 (Language=Javascript)",
    "Content-Type": "application/x-www-form-urlencoded"
     //  "Content-Type": "text/xml"
}; 


   var options = {
     "method" : "post",
     "muteHttpExceptions" : true,
   //  "payload" : formData,
     "header":header
   };

并将调用更改为 url 编码(表单无法正常工作,不知道为什么)


var url = 'https:mws-eu.amazonservices.com/Orders/2013-09-01?'+
'AWSAccessKeyId=<your stuff>'+
'&Action=GetOrder'+
  '&SellerId=<your stuff>+
  '&MWSAuthToken=<your token>'+
  '&SignatureVersion=2'+
  '&Timestamp='+todayTime'+ // remember to replace the ":" thru hex
  '&Version=2013-09-01'+
  '&Signature='+ tmpsignature+
  '&SignatureMethod=HmacSHA256'+
  '&AmazonOrderId.Id.1='+<your order;

解析响应:



 var result = UrlFetchApp.fetch(url, options);

  //writeDataToXML(result);
  Logger.log(result);

    var xml = result.getContentText();

  var document = XmlService.parse(xml);

这成功了! :-)

我也检查了签名 https://mws-eu.amazonservices.com/scratchpad/index.html