首页 > 解决方案 > 亚马逊 sp-API aws 签名问题

问题描述

AMAZON SP-API AWS SIGNATURE 我们计算的请求签名与您提供的签名不匹配。检查您的 AWS 秘密访问密钥和签名方法。有关详细信息,请参阅服务文档

    public function getOrdersFromApi(){
                // Configuration values
                $host                   = 'sellingpartnerapi-eu.amazon.com';
                $accessKey              = 'XXXXX';
                $secretKey              = 'XXXXXX';
                $region                 = 'eu-west-1';
                $service                = 'execute-api';
    
                /**
                * You should modify the script
                * for
                *   1. full request url
                *   2. uri for AWS signature
                *   3. request method GET / POST / PUT
                *   4. actual data of the request
                * and call the above functions
                */
                $requestUrl = 'https://sellingpartnerapi-eu.amazon.com/orders/v0/orders?MarketplaceIds=A21TJRUUN4KGV&CreatedAfter=2021-01-15T05:26:31.308992';
                $uri = '?MarketplaceIds=A21TJRUUN4KGV&CreatedAfter=2021-01-15T05:26:31.308992';
                $httpRequestMethod = 'GET';
    
                $data = json_encode(array());
    
                $headers = $this->calcualteAwsSignatureAndReturnHeaders($host, $uri, $requestUrl, 
                            $accessKey, $secretKey, $region, $service, 
                            $httpRequestMethod, $data, TRUE);
    
                $result = $this->callToAPI($requestUrl, $httpRequestMethod, $headers, $data, TRUE);
    
                print_r($result);
    
        }


    public function calcualteAwsSignatureAndReturnHeaders($host, $uri, $requestUrl, 
                $accessKey, $secretKey, $region, $service, 
                $httpRequestMethod, $data, $debug = TRUE){
    
        $terminationString  = 'aws4_request';
        $algorithm      = 'AWS4-HMAC-SHA256';
        $phpAlgorithm       = 'sha256';
        $canonicalURI       = $uri;
        $canonicalQueryString   = '';
        $signedHeaders      = 'content-type;host;x-amz-date'; $signedHeaders = "content-type;host;user-agent;x-amz-access-token;x-amz-date;x-amz-security-token";
    
        $currentDateTime = new DateTime('UTC');
        $reqDate = $currentDateTime->format('Ymd');
        $reqDateTime = $currentDateTime->format('Ymd\THis\Z');
    
        // Create signing key
        $kSecret = $secretKey;
        $kDate = hash_hmac($phpAlgorithm, $reqDate, 'AWS4' . $kSecret, true);
        $kRegion = hash_hmac($phpAlgorithm, $region, $kDate, true);
        $kService = hash_hmac($phpAlgorithm, $service, $kRegion, true);
        $kSigning = hash_hmac($phpAlgorithm, $terminationString, $kService, true);
    
        // Create canonical headers
        $canonicalHeaders = array();
        $canonicalHeaders[] = 'content-type:application/json';
        $canonicalHeaders[] = 'host:' . $host;
        $canonicalHeaders[] = 'x-amz-date:' . $reqDateTime;
        $canonicalHeadersStr = implode("\n", $canonicalHeaders);
    
        // Create request payload
        $requestHasedPayload = hash($phpAlgorithm, $data);
    
        // Create canonical request
        $canonicalRequest = array();
        $canonicalRequest[] = $httpRequestMethod;
        $canonicalRequest[] = $canonicalURI;
        $canonicalRequest[] = $canonicalQueryString;
        $canonicalRequest[] = $canonicalHeadersStr . "\n";
        $canonicalRequest[] = $signedHeaders;
        $canonicalRequest[] = $requestHasedPayload;
        $requestCanonicalRequest = implode("\n", $canonicalRequest);
        $requestHasedCanonicalRequest = hash($phpAlgorithm, utf8_encode($requestCanonicalRequest));
        if($debug){
            echo "<h5>Canonical to string</h5>";
            echo "<pre>";
            echo $requestCanonicalRequest;
            echo "</pre>";
        }
    
        // Create scope
        $credentialScope = array();
        $credentialScope[] = $reqDate;
        $credentialScope[] = $region;
        $credentialScope[] = $service;
        $credentialScope[] = $terminationString;
        $credentialScopeStr = implode('/', $credentialScope);
    
        // Create string to signing
        $stringToSign = array();
        $stringToSign[] = $algorithm;
        $stringToSign[] = $reqDateTime;
        $stringToSign[] = $credentialScopeStr;
        $stringToSign[] = $requestHasedCanonicalRequest;
        $stringToSignStr = implode("\n", $stringToSign);
        if($debug){
            echo "<h5>String to Sign</h5>";
            echo "<pre>";
            echo $stringToSignStr;
            echo "</pre>";
        }
    
        // Create signature
        $signature = hash_hmac($phpAlgorithm, $stringToSignStr, $kSigning);
    
        // Create authorization header
        $authorizationHeader = array();
        $authorizationHeader[] = 'Credential=' . $accessKey . '/' . $credentialScopeStr;
        $authorizationHeader[] = 'SignedHeaders=' . $signedHeaders;
        $authorizationHeader[] = 'Signature=' . ($signature);
        $authorizationHeaderStr = $algorithm . ' ' . implode(', ', $authorizationHeader);
    
    
        // Request headers
        $headers = array();
        $headers[] = 'authorization:'.$authorizationHeaderStr;
        $headers[] = 'content-length:'.strlen($data);
        $headers[] = 'content-type: application/json';
        $headers[] = 'user-agent:sellergeni/1.0 (Php=7.2)';
        $headers[] = 'x-amz-access-token:Atza|IwEBII0yZlQvoo95puL9xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
        $headers[] = 'host: ' . $host;
        $headers[] = 'x-amz-date: ' . $reqDateTime;
    
        return $headers;
    }
    
    public  function callToAPI($requestUrl, $httpRequestMethod, $headers, $data, $debug=TRUE)
    {
        // Execute the call
        $curl = curl_init();
        curl_setopt_array($curl, array(
          CURLOPT_URL => $requestUrl,
          CURLOPT_RETURNTRANSFER => true,
          CURLOPT_FOLLOWLOCATION => true,
          CURLOPT_TIMEOUT => 30,
          CURLOPT_POST => true,
          CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
          CURLOPT_CUSTOMREQUEST => $httpRequestMethod,
          CURLOPT_POSTFIELDS => $data,
          CURLOPT_VERBOSE => 0,
          CURLOPT_SSL_VERIFYHOST => 0,
          CURLOPT_SSL_VERIFYPEER => 0,
          CURLOPT_HEADER => false,
          CURLINFO_HEADER_OUT=>true,
          CURLOPT_HTTPHEADER => $headers,
        ));
    
        $response = curl_exec($curl);
        $err = curl_error($curl);
        $responseCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    
        if($debug){
            $headers = curl_getinfo($curl, CURLINFO_HEADER_OUT);
            echo "<h5>Request</h5>";
            echo "<pre>";
            echo $headers;
            echo "</pre>";
        }
    
        curl_close($curl);
    
        if ($err) {
            if($debug){
                echo "<h5>Error:" . $responseCode . "</h5>";
                echo "<pre>";
                echo $err;
                echo "</pre>";
            }
        } else {
            if($debug){
                echo "<h5>Response:" . $responseCode . "</h5>";
                echo "<pre>";
                echo $response;
                echo "</pre>";
            }
        }
        
        return array(
            "responseCode" => $responseCode,
            "response" => $response,
            "error" => $err
        );
    }
此代码的响应如下
    
    规范到字符串
    得到
    ?MarketplaceIds=A21TJRUUN4KGV&CreatedAfter=2021-01-15T05:26:31.308992
    
    内容类型:应用程序/json
    主持人:salespartnerapi-eu.amazon.com
    x-amz-日期:20210204T060039Z
    
    内容类型;主机;用户代理;x-amz-access-token;x-amz-date;x-amz-security-token
    4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945
    要签名的字符串
    AWS4-HMAC-SHA256
    20210204T060039Z
    20210204/eu-west-1/execute-api/aws4_request
    f11a59afb96cf62bbdd17e44405da8c5567178531f839826e89e9b1fcb77a24a
    要求
    GET /orders/v0/orders?MarketplaceIds=A21TJRUUN4KGV&CreatedAfter=2021-01-15T05:26:31.308992 HTTP/1.1
    主持人:sellingpartnerapi-eu.amazon.com
    接受: */*
    授权:AWS4-HMAC-SHA256 Credential=xxxxxxxxxxxxxx/20210204/eu-west-1/execute-api/aws4_request, SignedHeaders=content-type;host;user-agent;x-amz-access-token;x-amz-date ;x-amz-security-token,签名=3ddc540c9a1e38ea0466e4d4570a5ea8a1bc7274cfbc2fffd50609c7f379c495
    内容长度:2
    内容类型:应用程序/json
    用户代理:sellergeni/1.0 (Php=7.2)
    x-amz-access-token:Atza|xxxxxxxxxxxxxxxxxxxxxxxxxxx
    x-amz-日期:20210204T060039Z
    
    回复:403
    {
      “错误”:[
        {
          "message": "我们计算的请求签名与您提供的签名不匹配。请检查您的 AWS Secret Access Key 和签名方法。有关详细信息,请参阅服务文档。
    
    此请求的规范字符串应该是
    '得到
    /订单/v0/订单
    CreatedAfter=2021-01-15T05%3A26%3A31.308992&MarketplaceIds=A21TJRUUN4KGV
    内容类型:应用程序/json
    主持人:salespartnerapi-eu.amazon.com
    用户代理:sellergeni/1.0 (Php=7.2)
    x-amz-access-token:Atza|IwEBII0yZlQvoo95puL9xxxxxxxxxxxxxxxxxx
    x-amz-日期:20210204T060039Z
    x-amz-安全令牌:
    
    内容类型;主机;用户代理;x-amz-access-token;x-amz-date;x-amz-security-token
    4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945'
    
    字符串签名应该是
    'AWS4-HMAC-SHA256
    20210204T060039Z
    20210204/eu-west-1/execute-api/aws4_request
    e995c02098c1a2d5d775380f1fc49804b32af9534b5e330145ca125fe098f0af'
    ",
         “代码”:“无效签名”
        }
      ]
    }
   

标签: signatureamazon-product-api

解决方案


跑:

sign pathparam/resource

代替:

/messaging/v1/orders/{orderId}

和:

/messaging/v1/orders/xxx-xxxxxxx-xxxxxxx

推荐阅读