我正在尝试计算签名以进行亚马逊商城API调用,但我不断收到以下错误:
我们计算的请求签名与您提供的签名不符。检查您的AWS Secret Access Key和签名方法。有关详细信息,请参阅服务文档。
我已将签名创建过程包装到一个类中:
<?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
。
答案 0 :(得分:7)
我不确定我改变了什么,但我的签名一代现在正在运作。以下是该课程的内容:
<?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;
}
}
答案 1 :(得分:2)
调用您的签名功能后尝试此功能:
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;
}
在您创建规范字符串后,如格式化 查询请求,您可以通过创建基于哈希的方法来计算签名 消息认证码(HMAC)使用HMAC-SHA1或 HMAC-SHA256协议。 HMAC-SHA256协议是首选。
生成的签名必须是base-64编码,然后进行URI编码。