Я без проблем перешёл с AWS на SP-API. У меня проблема только с загрузкой канала.
Я уже несколько недель пробую дюжину способов. С httpPutRequest и GuzzleHttp\Client, с JSON и XML, с разными заголовками, но я всегда получаю одну и ту же ошибку:
function amazonSendFeedRequest($method, $path, $post) {
// Get access token
$accessToken = getAccessToken();
// Two formats for date used throughout
$date = gmdate('Ymd\THis\Z');
$ymd = gmdate('Ymd');
// Build a canonical request. This is just a highly-structured and
// ordered version of the request you will be making. Each part is
// newline-separated. The number of headers is variable, but this
// uses four headers. Headers must be in alphabetical order.
$canonicalRequest = $method . "\n" // HTTP method
. $path . "\n" // Path component of the URL
. $qs . "\n" // Query string component of the URL (without '?')
. 'host:' . HOST . "\n" // Header
. 'user-agent:' . USER_AGENT . "\n" // Header
. 'x-amz-access-token:' . $accessToken . "\n" // Header
. 'x-amz-date:' . $date . "\n" // Header
. "\n" // A newline is needed here after the headers
. 'host;user-agent;x-amz-access-token;x-amz-date' . "\n" // Header names
. hash('sha256', $post); // Hash of the payload (empty string okay)
// Create signing key, which is hashed four times, each time adding
// more data to the key. Don't ask me why Amazon does it this way.
$signKey = hash_hmac('sha256', $ymd, 'AWS4' . IAM_USER_SECRET, true);
$signKey = hash_hmac('sha256', REGION, $signKey, true);
$signKey = hash_hmac('sha256', 'execute-api', $signKey, true);
$signKey = hash_hmac('sha256', 'aws4_request', $signKey, true);
// Create a String-to-Sign, which indicates the hash that is used and
// some data about the request, including the canonical request from above.
$stringToSign = 'AWS4-HMAC-SHA256' . "\n"
. $date . "\n"
. $ymd . '/' . REGION . '/execute-api/aws4_request' . "\n"
. hash('sha256', $canonicalRequest);
// Sign the string with the key, which will create the signature
// you'll need for the authorization header.
$signature = hash_hmac('sha256', $stringToSign, $signKey);
// Create Authorization header, which is the final step. It does NOT use
// newlines to separate the data; it is all one line, just broken up here
// for easier reading.
$authorization = 'AWS4-HMAC-SHA256 '
. 'Credential=' . IAM_USER_KEY . '/' . $ymd . '/'
. REGION . '/execute-api/aws4_request,'
. 'SignedHeaders=host;user-agent;x-amz-access-token;x-amz-date,'
. 'Signature=' . $signature;
$headers = [];
//$headers[] = 'authorization:' . $authorization;
$headers[] = 'contentType:text/xml; charset=UTF-8';
//$headers[] = 'host:' . HOST;
//$headers[] = 'user-agent:' . USER_AGENT;
//$headers[] = 'x-amz-access-token:' . $accessToken;
//$headers[] = 'x-amz-date:' . $date;
// Run the http request and capture the status code
$status = '';
$result = httpPutRequest($path, $post, $headers, $status);
// Validate the response
if (strpos($result, 'Error:') === 0) exit($result);
if (empty($result)) exit('Error: Empty response');
if ($status != 200 AND $status != 201) exit('Error: Status code ' . $status . ': ' . $result);
if (strpos($result, '{') !== 0) exit('Error: Invalid JSON: ' . $result);
// Decode json and return it
$json = json_decode($result, true);
if (!$json) exit('Error: Problem decoding JSON: ' . $result);
return $json;
}
Как это решить?
С помощью httpPutRequest и GuzzleHttp\Client, с JSON и XML, с разными заголовками
Я без проблем перешёл с AWS на SP-API. У меня проблема только с загрузкой канала. Я уже несколько недель пробую дюжину способов. С httpPutRequest и GuzzleHttp\Client, с JSON и XML, с разными заголовками, но я всегда получаю одну и ту же ошибку: [code]Header: SignatureDoesNotMatchThe request signature we calculated does not match the signature you provided. Check your key and signing method. [/code] Я читал, что проблема чаще всего связана с Content-Type, и я проверял и менял его снова и снова... Мой фактический код: [code]function sendFeed($feedURL) { $method = 'PUT'; //$url = '\SellingPartnerApi\Model\FeedsV20210630\CreateFeedResponse'; $url = $feedURL;
// Two formats for date used throughout $date = gmdate('Ymd\THis\Z'); $ymd = gmdate('Ymd');
// Build a canonical request. This is just a highly-structured and // ordered version of the request you will be making. Each part is // newline-separated. The number of headers is variable, but this // uses four headers. Headers must be in alphabetical order. $canonicalRequest = $method . "\n" // HTTP method . $path . "\n" // Path component of the URL . $qs . "\n" // Query string component of the URL (without '?') . 'host:' . HOST . "\n" // Header . 'user-agent:' . USER_AGENT . "\n" // Header . 'x-amz-access-token:' . $accessToken . "\n" // Header . 'x-amz-date:' . $date . "\n" // Header . "\n" // A newline is needed here after the headers . 'host;user-agent;x-amz-access-token;x-amz-date' . "\n" // Header names . hash('sha256', $post); // Hash of the payload (empty string okay)
// Create signing key, which is hashed four times, each time adding // more data to the key. Don't ask me why Amazon does it this way. $signKey = hash_hmac('sha256', $ymd, 'AWS4' . IAM_USER_SECRET, true); $signKey = hash_hmac('sha256', REGION, $signKey, true); $signKey = hash_hmac('sha256', 'execute-api', $signKey, true); $signKey = hash_hmac('sha256', 'aws4_request', $signKey, true);
// Create a String-to-Sign, which indicates the hash that is used and // some data about the request, including the canonical request from above. $stringToSign = 'AWS4-HMAC-SHA256' . "\n" . $date . "\n" . $ymd . '/' . REGION . '/execute-api/aws4_request' . "\n" . hash('sha256', $canonicalRequest);
// Sign the string with the key, which will create the signature // you'll need for the authorization header. $signature = hash_hmac('sha256', $stringToSign, $signKey);
// Create Authorization header, which is the final step. It does NOT use // newlines to separate the data; it is all one line, just broken up here // for easier reading. $authorization = 'AWS4-HMAC-SHA256 ' . 'Credential=' . IAM_USER_KEY . '/' . $ymd . '/' . REGION . '/execute-api/aws4_request,' . 'SignedHeaders=host;user-agent;x-amz-access-token;x-amz-date,' . 'Signature=' . $signature;
// Run the http request and capture the status code $status = ''; $result = httpPutRequest($path, $post, $headers, $status);
// Validate the response if (strpos($result, 'Error:') === 0) exit($result); if (empty($result)) exit('Error: Empty response'); if ($status != 200 AND $status != 201) exit('Error: Status code ' . $status . ': ' . $result); if (strpos($result, '{') !== 0) exit('Error: Invalid JSON: ' . $result);
// Decode json and return it $json = json_decode($result, true);
if (!$json) exit('Error: Problem decoding JSON: ' . $result); return $json; } [/code] Как это решить? С помощью httpPutRequest и GuzzleHttp\Client, с JSON и XML, с разными заголовками