javascript - 使用 Google 脚本的 MWS 发布请求

标签 javascript post google-apps-script amazon-mws

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

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

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

一些我不确定的事情:

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

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

它是否必须在单独的行上,是否需要发布和其他内容。有点不清楚。?

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

请注意:

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

您的 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 ))

第三步,发送调用

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

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

第四步,处理结果

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

第 5 步,高级内容

如果您使用需要发送文档的调用,如 SendFeed,则需要执行以下额外步骤:

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

关于javascript - 使用 Google 脚本的 MWS 发布请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54295491/

相关文章:

javascript: HTML5 音频播放器

javascript - Aurelia 的带有对象的 computedFrom

C# MVC4 Jquery Ajax 发布部分 View 更新

google-apps-script - Google Apps脚本查找字符串并更改列背景颜色

javascript - 按名称查找列并删除列

javascript - Google 表格 - 表单提交时的格式日期

javascript - 如何将推特用户名与 Angular 用户界面路由器匹配

javascript - Mongoose - 查找(): object inside search options is not working

rest - HTTP 动词 - 何时使用 GET/POST/PUT/Delete

angular - HTTP post 405 方法不允许