php - 为 Amazon Marketplace API 计算签名的问题

标签 php amazon-mws amazon-marketplace

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

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.

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

<?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()));
}

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

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

最佳答案

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

<?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;
    }

}

关于php - 为 Amazon Marketplace API 计算签名的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29679646/

相关文章:

api - 亚马逊 MWS API(产品和实时订单更新)

python - 获取给定 ASIN 的最低 4 个价格

C# 亚马逊上传提要,将产品与现有产品匹配?

amazon-web-services - Restcomm登录页面错误: webpage not available

php - 使用 php/mysql 创建最近的提要

php - 检测哪个 webkit/moz/etc.要显示的前缀

php - 无法弄清楚如何将 &lt;input type ="checkbox"> 转换为 PHP bool 值

java - 亚马逊 MWS - getOrders

php - 将亚马逊 MWS 暂存器查询转换为 API 调用

PHP非法字符串偏移错误