Проблемы расчета подписи для API Amazon Marketplace

Я пытаюсь вычислить подпись, чтобы делать вызовы API Amazon Marketplace, но я продолжаю получать следующую ошибку:

Подписанная нами подпись запроса не соответствует подписи, которую вы предоставили. Проверьте секретный ключ доступа 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 *.

EDIT: И вот как я использую класс 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())); } 

В стороне: я знаю, что учетные данные Marketplace верны, поскольку я вошел в учетную запись и получил ключи доступа, секретные и идентификаторы продавцов.

* Я не использую SDK, поскольку он не поддерживает вызов API, который мне нужен: SubmitFeed .

Solutions Collecting From Web of "Проблемы расчета подписи для API Amazon Marketplace"

Я не уверен, что я изменил, но мое поколение подписей работает сейчас. Ниже приведено содержание класса:

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

Попробуйте эту функцию после вызова функции знака:

  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.