我正在尝试在此之后创建对亚马逊销售合作伙伴 API 的请求guide https://github.com/amzn/selling-partner-api-docs/blob/main/guides/developer-guide/SellingPartnerApiDeveloperGuide.md#step-2-construct-a-selling-partner-api-uri.
第一部分:创建访问权限已经完成here https://stackoverflow.com/questions/66450176/google-apps-script-connecting-to-amazon-selling-partner-api-access-token/.
订单 API 的文档可以找到here https://github.com/amzn/selling-partner-api-docs/blob/main/references/orders-api/ordersV0.md.
我正在尝试调用GET /orders/v0/orders
手术。
连接到 API
此操作的唯一强制参数是MarketplaceIds
根据文档。
为了获得订单,我们需要签署我们的请求。到目前为止,这是我的代码:
function GetOrders(){
var access_token = AccessToken();
//Time variables
var currentDate = new Date();
var isoDate = currentDate.toISOString();
var yearMonthDay= Utilities.formatDate(currentDate, 'GTM-5', 'yyyyMMdd');
//API variables
var end_point = 'https://sellingpartnerapi-eu.amazon.com';
//Credential variables
var aws_region = "eu-west-1";
var service = "execute-api";
var termination_string = "aws4_request";
//CanonicalRequest = httpRequestMethod + '\n' + CanonicalURI + '\n' + CanonicalQueryString + '\n' + CanonicalHeaders + '\n' + SignedHeaders + '\n' + HexEncode(Hash(RequestPayload));
//CanonicalRequest components:
var httpRequestMethod = 'GET';
var canonicalURI = '/orders/v0/orders';
var canonicalQueryString = '?marketplaceId=A1PA6795UKMFR9';
var canonicalheaders = 'host:' + canonicalURI + '\n' + 'x-amz-access-token:' + access_token + '\n' + 'x-amz-date:' + isoDate;
var signedheaders = 'host;user-agent;x-amz-access-token;x-amz-date';
var requestPayloadHashed = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, "");//NEW
requestPayloadHashed = requestPayloadHashed.map(function(e) {return ("0" + (e < 0 ? e + 256 : e).toString(16)).slice(-2)}).join("");//NEW
//Building the canonical request
var canonical_string = httpRequestMethod + '\n' + canonicalURI + '\n' + canonicalQueryString + '\n' + canonicalheaders + '\n' + signedheaders + '\n' + requestPayloadHashed;//UPDATED
var canonical_signature = Utilities.computeHmacSha256Signature(canonical_string, ACCESS_KEY);
var canonical_request = canonical_string + '\n' + canonical_signature;
canonical_request = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, canonical_request);//NEW
//CredentialScope = Date + AWS region + Service + Termination string;
//StringToSign = Algorithm + \n + RequestDateTime + \n + CredentialScope + \n + HashedCanonicalRequest;
var credential_scope = yearMonthDay + '/' + aws_region + '/' + service + '/' + termination_string;
var string_to_sign = "AWS4-HMAC-SHA256" + '\n' + isoDate + '\n' + credential_scope + '\n' + canonical_request;
var kSecret = ACCESS_KEY;
var kDate = Utilities.computeHmacSha256Signature(yearMonthDay, "AWS4" + kSecret);
var kRegion = Utilities.computeHmacSha256Signature(Utilities.newBlob(aws_region).getBytes(), kDate);
var kService = Utilities.computeHmacSha256Signature(Utilities.newBlob(service).getBytes(), kRegion);
var kSigning = Utilities.computeHmacSha256Signature(Utilities.newBlob(termination_string).getBytes(), kService);
kSigning = kSigning.map(function(e) {return ("0" + (e < 0 ? e + 256 : e).toString(16)).slice(-2)}).join("");
Logger.log('kSigning: ' + kSigning);
var signature = Utilities.computeHmacSha256Signature(kSigning, string_to_sign);
signature = signature.map(function(e) {return ("0" + (e < 0 ? e + 256 : e).toString(16)).slice(-2)}).join("");
var options = {
'method': 'GET',
'payload': {
'end_point': end_point,
'path': canonicalURI,
'query_string': canonicalQueryString
//Path parameter not needed
},
'headers': {
//'host': end_point,
'x-amz-access-token': access_token,
'x-amz-date': isoDate,
'user-agent': 'GAS Script 1.0 (Javascript)',
'Authorization': 'AWS4-HMAC-SHA256 Credential=' + ACCESS_ID + '/' + credential_scope + ', SignedHeaders=' + signedheaders + ', Signature=' + signature,
},
}
var getOrders = UrlFetchApp.fetch(end_point, options);
Logger.log(getOrders);
}
PROBLEMS
运行脚本时,我收到以下错误:
Exception: Request failed for https://sellingpartnerapi-eu.amazon.com returned code 403. Truncated server response: {
{
"errors": [
{
"message": "The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.
The Canonical String for this request should have been
'POST
/
host:sellingpartnerapi-eu.amazon.com
user-agent:Mozilla/5.0 (compatible; Google-Apps-Script; beanserver; +https://script.google.com; id: UAEmdDd-KyWEWcR137UzUzWb1fu3rUgNviHA)
x-amz-access-token:Atza|IwEBSomeAccessToken
x-amz-date:2021-03-10T02:44:01.727Z
host;user-agent;x-amz-access-token;x-amz-date
cf22942946358a7530d8b72df6333e859644aaebb08a1cd825a6af65a8561111'
The String-to-Sign should have been
'AWS4-HMAC-SHA256
20210310T024401Z
20210310/eu-west-1/execute-api/aws4_request
c4c1dcea7026765f52c5265296f9e1cb91b6618928debbc04a393bac89ce8493'
",
"code": "InvalidSignature"
}
]
}
问题
我对什么是“有效负载”有很大疑问
对于这部分代码:
var canonical_string = httpRequestMethod + '\n' + canonicalURI + '\n' + canonicalQueryString + '\n' + canonicalheaders + '\n' + signedheaders + '\n' + requestPayloadHashed;
我们必须合并有效负载请求的哈希版本requestPayloadHashed
.
它还提到:
如果有效负载为空,则使用空字符串作为哈希的输入
功能。
现在我刚刚创建了具有空白值的变量
var requestPayloadHashed = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, "");//NEW
requestPayloadHashed = requestPayloadHashed.map(function(e) {return ("0" + (e < 0 ? e + 256 : e).toString(16)).slice(-2)}).join("");//NEW
但我不确定我是否遗漏了一些重要的东西。
更新#1
应用田池建议后,我收到以下消息:
{
"errors": [
{
"message": "The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.
The Canonical String for this request should have been
'GET
/orders/v0/orders
marketplaceId=A1PA6795UKMFR9
host:sellingpartnerapi-eu.amazon.com
user-agent:Mozilla/5.0 (compatible; Google-Apps-Script; beanserver; +https://script.google.com; id: UAEmdDd-KyWEWcR137UzUzWb1fu3rUgNviHA)
x-amz-access-token:Atza|IwEBISomeAccessToken
x-amz-date:2021-03-10T03:00:14.411Z
host;user-agent;x-amz-access-token;x-amz-date
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
The String-to-Sign should have been
'AWS4-HMAC-SHA256
20210310T030014Z
20210310/eu-west-1/execute-api/aws4_request
f1bbc99190ca5a9e9e068ad6a0b2ef6a7aed4a1232095ef8f3d77ad62d0e66ac'
",
"code": "InvalidSignature"
}
]
}
更新#2有一个网站可以帮助我们对这些连接进行一些测试:
https://mws.amazonservices.de/scratchpad/index.html https://mws.amazonservices.de/scratchpad/index.html
通过使用它,我相信我已经验证了Access Key ID
and Secret Key
,但是,它要求提供一个 SellerId,这对我来说是新的,并且在API docs https://github.com/amzn/selling-partner-api-docs/blob/main/references/orders-api/ordersV0.md.
我想知道它可以去哪里。
更新#3
我实施了大部分 Tanaike 建议,并尝试将发送到 API 的内容与收到的错误消息保持一致:
这是该脚本的最后一个版本:
function GetOrders(){
var access_token = AccessToken();
//Time variables
var currentDate = new Date();
var isoDate = currentDate.toISOString();
var isoString = isoDate.replace(/-/g, "").replace(/:/g, "").replace(/(\.\d{3})/, "");
var yearMonthDay= Utilities.formatDate(currentDate, 'GTM-5', 'yyyyMMdd');
Logger.log('isoDate: ' + isoDate)
//API variables
var end_point = 'https://sellingpartnerapi-eu.amazon.com';
//Credential variables
var aws_region = "eu-west-1";
var service = "execute-api";
var termination_string = "aws4_request";
//CanonicalRequest = httpRequestMethod + '\n' + CanonicalURI + '\n' + CanonicalQueryString + '\n' + CanonicalHeaders + '\n' + SignedHeaders + '\n' + HexEncode(Hash(RequestPayload));
//CanonicalRequest components:
var httpRequestMethod = 'GET';
var canonicalURI = '/orders/v0/orders';
var canonicalQueryString = '?marketplaceId=A1PA6795UKMFR9';
var canonicalheaders = 'host:' + "sellingpartnerapi-eu.amazon.com" + '\n' + 'x-amz-access-token:' + access_token + '\n' + 'x-amz-date:' + isoDate;
var signedheaders = 'host;x-amz-access-token;x-amz-date';//;user-agent
var requestPayloadHashed = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, "");//NEW
requestPayloadHashed = requestPayloadHashed.map(function(e) {return ("0" + (e < 0 ? e + 256 : e).toString(16)).slice(-2)}).join("");//NEW
//Building the canonical request
var canonical_string = httpRequestMethod + '\n' + canonicalURI + '\n' + "marketplaceId=A1PA6795UKMFR9" + '\n' + canonicalheaders + '\n\n' + signedheaders + '\n' + requestPayloadHashed;//UPDATED
Logger.log('canonical_string: ' + canonical_string)
var canonical_signature = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, canonical_string);
canonical_request = canonical_signature.map(function(e) {return ("0" + (e < 0 ? e + 256 : e).toString(16)).slice(-2)}).join("");
Logger.log("canonical_request: " + canonical_request)
//CredentialScope = Date + AWS region + Service + Termination string;
//StringToSign = Algorithm + \n + RequestDateTime + \n + CredentialScope + \n + HashedCanonicalRequest;
var credential_scope = yearMonthDay + '/' + aws_region + '/' + service + '/' + termination_string;
var string_to_sign = "AWS4-HMAC-SHA256" + '\n' + isoString + '\n' + credential_scope + '\n' + canonical_request;
Logger.log("string_to_sign: " + string_to_sign);
var kSecret = ACCESS_KEY;
var kDate = Utilities.computeHmacSha256Signature(yearMonthDay, "AWS4" + kSecret);
var kRegion = Utilities.computeHmacSha256Signature(toBytes(aws_region), kDate);
var kService = Utilities.computeHmacSha256Signature(toBytes(service), kRegion);
var kSigning = Utilities.computeHmacSha256Signature(toBytes(termination_string), kService);
Logger.log('kSigning: ' + kSigning);
var signature = hex(Utilities.computeHmacSha256Signature(toBytes(string_to_sign), kSigning));
Logger.log('signature: ' + signature)
var options = {
'method': 'GET',
'headers': {
//'host': end_point,
'x-amz-access-token': access_token,
'x-amz-date': isoDate,
//'user-agent': 'Mozilla/5.0 (compatible; Google-Apps-Script; beanserver; +https://script.google.com; id: UAEmdDd-KyWEWcR137UzUzWb1fu3rUgNviHA)',
'Authorization': 'AWS4-HMAC-SHA256 Credential=' + ACCESS_ID + '/' + credential_scope + ', SignedHeaders=' + signedheaders + ', Signature=' + signature,
},
'muteHttpExceptions': true
}
var getOrders = UrlFetchApp.fetch(end_point + canonicalURI + canonicalQueryString, options);
Logger.log(getOrders);
}
我现在收到完全与我的访问相关的错误:
{
"errors": [
{
"message": "Access to requested resource is denied.",
"code": "Unauthorized",
"details": ""
}
]
}
然而,这可能是因为当我注册应用程序时(指南here https://github.com/amzn/selling-partner-api-docs/blob/main/guides/developer-guide/SellingPartnerApiDeveloperGuide.md#step-6-register-your-application)我使用 IAM 用户而不是 IAM 角色。
指南中说:
重要的。注册您的应用程序时,您注册的 IAM ARN
必须为您附加 IAM 的 IAM 实体提供
步骤 3. 创建 IAM 策略中的策略。在此工作流程中,IAM
实体是步骤 4. 创建 IAM 角色中的 IAM 角色。如果你
使用您的 IAM 用户注册您的应用程序,请确保 IAM
政策附在其上。否则您致电销售合作伙伴
API 将失败。我们建议使用 IAM 注册您的应用程序
角色,如此工作流程中所示,可帮助您更好地控制对
您的 AWS 资源。
因此,我将继续解决该问题,看看是否获得了所需的授权。