php - descargar - clave de acceso secreta amazon
Problemas al calcular la firma para la API de Amazon Marketplace (2)
No estoy seguro de lo que he cambiado, pero mi generación de firmas está funcionando ahora. A continuación se muestra el contenido de la clase:
<?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;
}
}
Estoy tratando de calcular una firma para realizar llamadas a la API de Amazon Marketplace, pero sigo recibiendo el siguiente error:
La firma de solicitud que calculamos no coincide con la firma que proporcionó. Verifique su clave de acceso secreta de AWS y el método de firma. Consulte la documentación del servicio para más detalles.
He envuelto el proceso de creación de firma en una clase:
<?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;
}
}
Pero no puedo por mi vida ver a dónde me voy mal. He seguido la guía en la API y he examinado el ejemplo de Java y el antiguo SDK de PHP del mercado *.
EDITAR: Y aquí es cómo estoy usando la clase de 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()));
}
Además, sé que las credenciales de Marketplace son correctas, ya que inicié sesión en la cuenta y recuperé la clave de acceso, el secreto y los ID de los vendedores.
* No estoy usando el SDK porque no es compatible con la llamada a la API que necesito: SubmitFeed
.
Pruebe esta función después de llamar a su función de signo:
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;
}
Después de haber creado la cadena canónica como se describe en Formato de la solicitud de consulta, calcula la firma creando un código de autenticación de mensaje basado en hash (HMAC) utilizando los protocolos HMAC-SHA1 o HMAC-SHA256. Se prefiere el protocolo HMAC-SHA256.
La firma resultante debe estar codificada en base 64 y luego codificada en URI.