亚马逊销售合作伙伴 API 403 - 签名错误

问题描述

我正在尝试向亚马逊销售合作伙伴 API (node.js/Lambda) 发出请求,但我目前总是收到 403 错误。我已将相同的凭据和访问令牌插入 Postman,请求工作正常。我相信我在计算请求的签名时一定有错误,但我看不出任何错误

我正在计算签名如下:

function constructCanonicalRequest(accesstoken,dateTime) {
    let canonical = [];
    canonical.push('GET');
    canonical.push('/fba/outbound/2020-07-01/fulfillmentOrders/FBATestOrder-1');
    canonical.push('');
    canonical.push('host:' + 'sandBox.sellingpartnerapi-na.amazon.com');
    canonical.push('x-amz-access-token:' + accesstoken);
    canonical.push('x-amz-date:' + dateTime);
    canonical.push('');
    canonical.push('host;x-amz-access-token;x-amz-date');
    canonical.push(crypto.SHA256(''));

    let canonicalRequest = canonical.join('\n');
    let canonicalRequestHash = crypto.SHA256(canonicalRequest);

    return canonicalRequestHash
};

function constructStringToSign(dateTime,date,canonicalRequestHash) {
    let stringToSign = [];
    stringToSign.push('AWS4-HMAC-SHA256')
    stringToSign.push(dateTime);
    stringToSign.push(date + '/' + 'us-east-1' + '/' + 'execute-api' + '/aws4_request');
    stringToSign.push(canonicalRequestHash);
    
    return stringToSign.join('\n');
};

function constructSignature(date,iamSecret,stringToSign) {
    let kDate = crypto.HmacSHA256(date,'AWS4' + iamSecret);
    let kRegion = crypto.HmacSHA256('us-east-1',kDate);
    let kService = crypto.HmacSHA256('execute-api',kRegion);
    let kSigning = crypto.HmacSHA256('aws4_request',kService);

    let signature = crypto.HmacSHA256(stringToSign,kSigning).toString(crypto.enc.Hex);

    return signature
};

剩下的功能是:

        let dateTimeISO = new Date().toISOString();
        let dateTime = dateTimeISO.replace(/(\.\d{3})|\W/g,'');
        let date = dateTime.split('T')[0];

        let canonicalRequestHash = constructCanonicalRequest(accesstoken,dateTimeISO);
        let stringToSign = constructStringToSign(dateTime,canonicalRequestHash);
        let signature = constructSignature(date,stringToSign);

        let authHeader = 'AWS4-HMAC-SHA256 Credential=' + iamId + '/' + date + '/' + 'us-east-1' + '/execute-api/aws4_request,SignedHeaders=host;x-amz-access-token;x-amz-date,Signature=' + signature

        console.log(authHeader);

        let amazonUrl = "https://sandBox.sellingpartnerapi-na.amazon.com/fba/outbound/2020-07-01/fulfillmentOrders/FBATestOrder-1";
        const amazonResponse = await fetch(amazonUrl,{
            method: 'get',headers: {
                'Authorization':authHeader,'Content-Type':'application/json; charset=utf-8','host':'sandBox.sellingpartnerapi-na.amazon.com','x-amz-access-token':accesstoken,'user-agent': 'My Selling Tool/2.0 (Language=JS;Platform=Node)','x-amz-date':dateTime,}
        });

我还尝试使用多个不同的加密库来查看 HMAC 创建是否有问题,但这并没有解决任何问题。

解决方法

我可以使用 C# 工作。 GitHub 上有一个 Java 库: https://github.com/amzn/selling-partner-api-docs/blob/main/guides/en-US/developer-guide/SellingPartnerApiDeveloperGuide.md 我只是按照那里的说明进行操作,尽管 C# 库中存在关于承担角色的缺陷,即在 java 库中。