MWS Post 请求 Google 脚本
MWS Post Request with Google Scripts
我正在尝试通过 google 脚本向亚马逊发出 post 请求以收集信息。
我们正在尝试将我们的订单发送到 MWS 并自动将它们转移到表格中。
我进行了签署请求的最后一步。
一些我不确定的事情:
- 他们说我们使用密钥进行散列,我只看到一个客户端密钥
和访问密钥 ID,我应该使用哪个?
- 我是否添加 URL 作为签名的一部分?在 MWS Scratch pad 上,他们添加如下所示:
POST
mws.amazonservices.com
/Orders/2013-09-01
是否必须在不同的行上,是否需要 post 和其他内容。有点看不懂?
- 我在网上看到 sha256 字节码得到 base64 编码,而不是字符串文字,是这样吗?
- 我尝试使用在线工具对亚马逊提供给我的字符串进行哈希处理,并将其与他们提供的哈希和 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
SignatureMethod
是 HmacSHA256
SignatureVersion
是 2
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
我正在尝试通过 google 脚本向亚马逊发出 post 请求以收集信息。
我们正在尝试将我们的订单发送到 MWS 并自动将它们转移到表格中。
我进行了签署请求的最后一步。
一些我不确定的事情:
- 他们说我们使用密钥进行散列,我只看到一个客户端密钥 和访问密钥 ID,我应该使用哪个?
- 我是否添加 URL 作为签名的一部分?在 MWS Scratch pad 上,他们添加如下所示:
POST
mws.amazonservices.com
/Orders/2013-09-01
是否必须在不同的行上,是否需要 post 和其他内容。有点看不懂?
- 我在网上看到 sha256 字节码得到 base64 编码,而不是字符串文字,是这样吗?
- 我尝试使用在线工具对亚马逊提供给我的字符串进行哈希处理,并将其与他们提供的哈希和 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 个字符的卖家 IDSignatureMethod
是HmacSHA256
SignatureVersion
是2
Timestamp
是像20181231T23:59:59Z
这样的日期,在新年前一秒 UTCVersion
是像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