【问题标题】:Issues calculating signature for Amazon Marketplace API为 Amazon Marketplace API 计算签名的问题
【发布时间】:2015-06-23 03:36:42
【问题描述】:

我正在尝试计算签名以进行 Amazon Marketplace API 调用,但我不断收到以下错误:

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

我已将签名创建过程封装到一个类中:

<?php
namespace App\Marketplace\Amazon;

class Signature
{
    protected $signedString;

    public function __construct($url, array $parameters, $secretAccessKey)
    {
        $stringToSign = $this->calculateStringToSign($url, $parameters);

        $this->signedString = $this->sign($stringToSign, $secretAccessKey);
    }

    protected function calculateStringToSign($url, array $parameters)
    {
        $url = parse_url($url);

        $string = "POST\n";
        $string .= $url['host'] . "\n";
        $string .= $url['path'] . "\n";
        $string .= $this->getParametersAsString($parameters);

        return $string;
    }

    protected function sign($data, $secretAccessKey)
    {
        return base64_encode(hash_hmac('sha256', $data, $secretAccessKey, true));
    }

    protected function getParametersAsString(array $parameters)
    {
        uksort($parameters, 'strcmp');

        $queryParameters = [];

        foreach ($parameters as $key => $value) {
            $queryParameters[$key] = $this->urlEncode($value);
        }

        return http_build_query($queryParameters);
    }

    protected function urlEncode($value)
    {
        return str_replace('%7E', '~', rawurlencode($value));
    }

    public function __toString()
    {
        return $this->signedString;
    }
}

但我这辈子都看不出哪里错了。我遵循 API 中的指南,查看了 Java 示例以及过时的 Marketplace PHP SDK*。

编辑:这是我使用Signature 类的方式:

$version = '2011-07-01';

$url = 'https://mws.amazonservices.com/Sellers/'.$version;

$timestamp = gmdate('c', time());

$parameters = [
    'AWSAccessKeyId' => $command->accessKeyId,
    'Action' => 'GetAuthToken',
    'SellerId' => $command->sellerId,
    'SignatureMethod' => 'HmacSHA256',
    'SignatureVersion' => 2,
    'Timestamp' => $timestamp,
    'Version' => $version,
];

$signature = new Signature($url, $parameters, $command->secretAccessKey);

$parameters['Signature'] = strval($signature);

try {
    $response = $this->client->post($url, [
        'headers' => [
            'User-Agent' => 'my-app-name',
        ],
        'body' => $parameters,
    ]);

    dd($response->getBody());
} catch (\Exception $e) {
    dd(strval($e->getResponse()));
}

顺便说一句:我知道市场凭据是正确的,因为我已登录帐户并检索了访问密钥、秘密和卖家 ID。

* 我没有使用 SDK,因为它不支持我需要的 API 调用:SubmitFeed

【问题讨论】:

    标签: php amazon-mws amazon-marketplace


    【解决方案1】:

    我不确定我做了什么更改,但我的签名生成功能现在可以正常工作了。以下是课程内容:

    <?php
    namespace App\Marketplace\Amazon;
    
    class Signature
    {
        /**
         * The signed string.
         *
         * @var string
         */
        protected $signedString;
    
        /**
         * Create a new signature instance.
         *
         * @param  string  $url
         * @param  array   $data
         * @param  string  $secretAccessKey
         */
        public function __construct($url, array $parameters, $secretAccessKey)
        {
            $stringToSign = $this->calculateStringToSign($url, $parameters);
    
            $this->signedString = $this->sign($stringToSign, $secretAccessKey);
        }
    
        /**
         * Calculate the string to sign.
         *
         * @param  string  $url
         * @param  array   $parameters
         * @return string
         */
        protected function calculateStringToSign($url, array $parameters)
        {
            $url = parse_url($url);
    
            $string = "POST\n";
            $string .= $url['host']."\n";
            $string .= $url['path']."\n";
            $string .= $this->getParametersAsString($parameters);
    
            return $string;
        }
    
        /**
         * Computes RFC 2104-compliant HMAC signature.
         *
         * @param  string  $data
         * @param  string  $secretAccessKey
         * @return string
         */
        protected function sign($data, $secretAccessKey)
        {
            return base64_encode(hash_hmac('sha256', $data, $secretAccessKey, true));
        }
    
        /**
         * Convert paremeters to URL-encoded query string.
         *
         * @param  array  $parameters
         * @return string
         */
        protected function getParametersAsString(array $parameters)
        {
            uksort($parameters, 'strcmp');
    
            $queryParameters = [];
    
            foreach ($parameters as $key => $value) {
                $key = rawurlencode($key);
                $value = rawurlencode($value);
    
                $queryParameters[] = sprintf('%s=%s', $key, $value);
            }
    
            return implode('&', $queryParameters);
        }
    
        /**
         * The string representation of this signature.
         *
         * @return string
         */
        public function __toString()
        {
            return $this->signedString;
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      调用你的sign函数后试试这个函数:

        function amazonEncode($text)
        {
          $encodedText = "";
          $j = strlen($text);
          for($i=0;$i<$j;$i++)
          {
            $c = substr($text,$i,1);
            if (!preg_match("/[A-Za-z0-9\-_.~]/",$c))
            {
              $encodedText .= sprintf("%%%02X",ord($c));
            }
            else
            {
              $encodedText .= $c;
            }
          }
          return $encodedText;
        }
      

      Reference

      按照格式化中所述创建规范字符串后 查询请求,您通过创建基于哈希的方法计算签名 使用 HMAC-SHA1 或 HMAC-SHA256 协议。首选 HMAC-SHA256 协议。

      生成的签名必须是 base-64 编码,然后是 URI 编码。

      【讨论】:

      • 我不确定您的 amazonEncode() 方法的主体在做什么,但我似乎正在按照文档在我的 sign() 方法中所说的那样做,但是使用 base64_encode 和 @ 987654326@ 功能。你能解释一下区别吗?此外,您提供的文档适用于 AWS,而不是 MWS。
      • 两者的签名生成类似。您需要对生成的 base64 进行 URI 编码,这几乎是我的 amazonEncode 所做的。
      • 我已将 sign() 方法的结果包装在您的 amazonEncode() 函数中,但我仍然收到 SignatureDoesNotMatch 错误。
      猜你喜欢
      • 2015-07-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-16
      • 2017-08-26
      • 1970-01-01
      • 1970-01-01
      • 2013-01-03
      • 2021-07-04
      相关资源
      最近更新 更多