计算 Amazon Marketplace 签名的问题 API
Issues calculating signature for Amazon Marketplace API
我正在尝试计算签名以进行 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.
我已经将签名创建过程包装到 class:
<?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
class:
$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()));
}
顺便说一句:我 知道 Marketplace 凭据是正确的,因为我已经登录到帐户并检索了访问密钥、机密和卖家 ID。
* 我没有使用 SDK,因为它不支持我需要的 API 调用:SubmitFeed
.
调用你的符号函数后试试这个函数:
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;
}
After you've created the canonical string as described in Format the
Query Request, you calculate the signature by creating a hash-based
message authentication code (HMAC) using either the HMAC-SHA1 or
HMAC-SHA256 protocols. The HMAC-SHA256 protocol is preferred.
The resulting signature must be base-64 encoded and then URI encoded.
我不确定我更改了什么,但我的签名生成现在可以正常工作了。下面是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;
}
}
我正在尝试计算签名以进行 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.
我已经将签名创建过程包装到 class:
<?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
class:
$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()));
}
顺便说一句:我 知道 Marketplace 凭据是正确的,因为我已经登录到帐户并检索了访问密钥、机密和卖家 ID。
* 我没有使用 SDK,因为它不支持我需要的 API 调用:SubmitFeed
.
调用你的符号函数后试试这个函数:
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;
}
After you've created the canonical string as described in Format the Query Request, you calculate the signature by creating a hash-based message authentication code (HMAC) using either the HMAC-SHA1 or HMAC-SHA256 protocols. The HMAC-SHA256 protocol is preferred.
The resulting signature must be base-64 encoded and then URI encoded.
我不确定我更改了什么,但我的签名生成现在可以正常工作了。下面是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;
}
}