如何使用php在aws中散列规范请求以匹配amazon aws sp api的期望?



我试图使用PHP向Amazon SP-API发出请求,但我一直得到请求签名不匹配的错误。尽管规范化请求中的所有值都与API所期望的值匹配,但是规范化请求的散列值是不同的。下面是我的代码:

<?php
$host = 'sellingpartnerapi-na.amazon.com';
$service = 'execute-api';
$region = 'us-east-1';
$accessKey = "aws access key id";
$secretKey = 'aws secret access key';
$accessToken = 'lwa access token';
$requestUrl = 'https://sellingpartnerapi-na.amazon.com';
$httpRequestMethod = 'GET';
$terminationString = 'aws4_request';
$algorithm = 'AWS4-HMAC-SHA256';
$phpAlgorithm = 'sha256';
$signedHeaders = 'content-type;host;x-amz-access-token;x-amz-date';
$canonicalURI = '/';
$canonicalQueryString   = '';
$requestHasedPayload = hash($phpAlgorithm, '');
$currentDateTime = new DateTime('UTC');
$reqDate = $currentDateTime->format('Ymd');
$reqDateTime = $currentDateTime->format('YmdTHisZ');

// Create canonical request
$canonicalRequest = array();
$canonicalRequest[] = $httpRequestMethod;
$canonicalRequest[] = $canonicalURI;
$canonicalRequest[] = 'content-type:application/json';
$canonicalRequest[] = 'host:sellingpartnerapi-na.amazon.com';
$canonicalRequest[] = 'x-amz-access-token:' . $accessToken;
$canonicalRequest[] = 'x-amz-date:' . $reqDateTime . "n";
$canonicalRequest[] = rawurlencode($signedHeaders);
$canonicalRequest[] = $canonicalQueryString;
$canonicalRequest[] = $requestHasedPayload;
$requestCanonicalRequest = implode("n", $canonicalRequest);
$requestHasedCanonicalRequest = hash($phpAlgorithm, utf8_encode($requestCanonicalRequest));
// Create signing key
$kSecret = $secretKey;
$kDate = hash_hmac($phpAlgorithm, $reqDate, 'AWS4' . $kSecret, true);
$kRegion = hash_hmac($phpAlgorithm, $region, $kDate, true);
$kService = hash_hmac($phpAlgorithm, $service, $kRegion, true);
$kSigning = hash_hmac($phpAlgorithm, $terminationString, $kService, true);

// Create scope
$credentialScope = array();
$credentialScope[] = $reqDate;
$credentialScope[] = $region;
$credentialScope[] = $service;
$credentialScope[] = $terminationString;
$credentialScopeStr = implode('/', $credentialScope);
// Create string to sign
$stringToSign = array();
$stringToSign[] = $algorithm;
$stringToSign[] = $reqDateTime;
$stringToSign[] = $credentialScopeStr;
$stringToSign[] = $requestHasedCanonicalRequest;
$stringToSignStr = implode("n", $stringToSign);

// Create signature
$signature = hash_hmac($phpAlgorithm, $stringToSignStr, $kSigning);
// Create authorization header
$authorizationHeader = array();
$authorizationHeader[] = 'Credential=' . $accessKey . '/' . $credentialScopeStr;
$authorizationHeader[] = 'SignedHeaders=' . $signedHeaders;
$authorizationHeader[] = 'Signature=' . ($signature);
$authorizationHeaderStr = $algorithm . ' ' . implode(', ', $authorizationHeader);

// Request headers
$headers = array();
$headers[] = 'authorization:'. $authorizationHeaderStr;
$headers[] = 'content-type: application/json';
$headers[] = 'host: ' . $host;
$headers[] = 'x-amz-date: ' . $reqDateTime;

$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $requestUrl,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_POST => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $httpRequestMethod, 
CURLOPT_VERBOSE => 0,
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_HEADER => false,
CURLINFO_HEADER_OUT=>true,
CURLOPT_HTTPHEADER => $headers,
));
$response = curl_exec($curl);
$err = curl_error($curl);
$responseCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);

curl_close($curl);
if ($err) {
echo "<h5>Error:" . $responseCode . "</h5>";
echo "<pre>";
echo $err;
echo "</pre>";
} else {
echo "<h5>Response:" . $responseCode . "</h5>";
echo "<pre>";
echo $response;
echo "</pre>";
}

如果你知道一个很好的资源,使用SP-API与php可以分享。文档非常模糊。

感谢

使用Signature Version 4签名AWS请求的文档有一步一步的方法以及用于GETPOST的定义良好的python示例完整的Signature Version 4签名过程示例(python)

这是另一个类似的问题,在PHP中签名版本4签名过程访问API网关端点。

请在你的问题中添加一些错误信息,以帮助这里的人回答你的问题。

最新更新