signature - 亚马逊 sp-API aws 签名问题
问题描述
AMAZON SP-API AWS SIGNATURE 我们计算的请求签名与您提供的签名不匹配。检查您的 AWS 秘密访问密钥和签名方法。有关详细信息,请参阅服务文档
public function getOrdersFromApi(){
// Configuration values
$host = 'sellingpartnerapi-eu.amazon.com';
$accessKey = 'XXXXX';
$secretKey = 'XXXXXX';
$region = 'eu-west-1';
$service = 'execute-api';
/**
* You should modify the script
* for
* 1. full request url
* 2. uri for AWS signature
* 3. request method GET / POST / PUT
* 4. actual data of the request
* and call the above functions
*/
$requestUrl = 'https://sellingpartnerapi-eu.amazon.com/orders/v0/orders?MarketplaceIds=A21TJRUUN4KGV&CreatedAfter=2021-01-15T05:26:31.308992';
$uri = '?MarketplaceIds=A21TJRUUN4KGV&CreatedAfter=2021-01-15T05:26:31.308992';
$httpRequestMethod = 'GET';
$data = json_encode(array());
$headers = $this->calcualteAwsSignatureAndReturnHeaders($host, $uri, $requestUrl,
$accessKey, $secretKey, $region, $service,
$httpRequestMethod, $data, TRUE);
$result = $this->callToAPI($requestUrl, $httpRequestMethod, $headers, $data, TRUE);
print_r($result);
}
public function calcualteAwsSignatureAndReturnHeaders($host, $uri, $requestUrl,
$accessKey, $secretKey, $region, $service,
$httpRequestMethod, $data, $debug = TRUE){
$terminationString = 'aws4_request';
$algorithm = 'AWS4-HMAC-SHA256';
$phpAlgorithm = 'sha256';
$canonicalURI = $uri;
$canonicalQueryString = '';
$signedHeaders = 'content-type;host;x-amz-date'; $signedHeaders = "content-type;host;user-agent;x-amz-access-token;x-amz-date;x-amz-security-token";
$currentDateTime = new DateTime('UTC');
$reqDate = $currentDateTime->format('Ymd');
$reqDateTime = $currentDateTime->format('Ymd\THis\Z');
// 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 canonical headers
$canonicalHeaders = array();
$canonicalHeaders[] = 'content-type:application/json';
$canonicalHeaders[] = 'host:' . $host;
$canonicalHeaders[] = 'x-amz-date:' . $reqDateTime;
$canonicalHeadersStr = implode("\n", $canonicalHeaders);
// Create request payload
$requestHasedPayload = hash($phpAlgorithm, $data);
// Create canonical request
$canonicalRequest = array();
$canonicalRequest[] = $httpRequestMethod;
$canonicalRequest[] = $canonicalURI;
$canonicalRequest[] = $canonicalQueryString;
$canonicalRequest[] = $canonicalHeadersStr . "\n";
$canonicalRequest[] = $signedHeaders;
$canonicalRequest[] = $requestHasedPayload;
$requestCanonicalRequest = implode("\n", $canonicalRequest);
$requestHasedCanonicalRequest = hash($phpAlgorithm, utf8_encode($requestCanonicalRequest));
if($debug){
echo "<h5>Canonical to string</h5>";
echo "<pre>";
echo $requestCanonicalRequest;
echo "</pre>";
}
// Create scope
$credentialScope = array();
$credentialScope[] = $reqDate;
$credentialScope[] = $region;
$credentialScope[] = $service;
$credentialScope[] = $terminationString;
$credentialScopeStr = implode('/', $credentialScope);
// Create string to signing
$stringToSign = array();
$stringToSign[] = $algorithm;
$stringToSign[] = $reqDateTime;
$stringToSign[] = $credentialScopeStr;
$stringToSign[] = $requestHasedCanonicalRequest;
$stringToSignStr = implode("\n", $stringToSign);
if($debug){
echo "<h5>String to Sign</h5>";
echo "<pre>";
echo $stringToSignStr;
echo "</pre>";
}
// 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-length:'.strlen($data);
$headers[] = 'content-type: application/json';
$headers[] = 'user-agent:sellergeni/1.0 (Php=7.2)';
$headers[] = 'x-amz-access-token:Atza|IwEBII0yZlQvoo95puL9xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
$headers[] = 'host: ' . $host;
$headers[] = 'x-amz-date: ' . $reqDateTime;
return $headers;
}
public function callToAPI($requestUrl, $httpRequestMethod, $headers, $data, $debug=TRUE)
{
// Execute the call
$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_POSTFIELDS => $data,
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);
if($debug){
$headers = curl_getinfo($curl, CURLINFO_HEADER_OUT);
echo "<h5>Request</h5>";
echo "<pre>";
echo $headers;
echo "</pre>";
}
curl_close($curl);
if ($err) {
if($debug){
echo "<h5>Error:" . $responseCode . "</h5>";
echo "<pre>";
echo $err;
echo "</pre>";
}
} else {
if($debug){
echo "<h5>Response:" . $responseCode . "</h5>";
echo "<pre>";
echo $response;
echo "</pre>";
}
}
return array(
"responseCode" => $responseCode,
"response" => $response,
"error" => $err
);
}
此代码的响应如下 规范到字符串 得到 ?MarketplaceIds=A21TJRUUN4KGV&CreatedAfter=2021-01-15T05:26:31.308992 内容类型:应用程序/json 主持人:salespartnerapi-eu.amazon.com x-amz-日期:20210204T060039Z 内容类型;主机;用户代理;x-amz-access-token;x-amz-date;x-amz-security-token 4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945 要签名的字符串 AWS4-HMAC-SHA256 20210204T060039Z 20210204/eu-west-1/execute-api/aws4_request f11a59afb96cf62bbdd17e44405da8c5567178531f839826e89e9b1fcb77a24a 要求 GET /orders/v0/orders?MarketplaceIds=A21TJRUUN4KGV&CreatedAfter=2021-01-15T05:26:31.308992 HTTP/1.1 主持人:sellingpartnerapi-eu.amazon.com 接受: */* 授权:AWS4-HMAC-SHA256 Credential=xxxxxxxxxxxxxx/20210204/eu-west-1/execute-api/aws4_request, SignedHeaders=content-type;host;user-agent;x-amz-access-token;x-amz-date ;x-amz-security-token,签名=3ddc540c9a1e38ea0466e4d4570a5ea8a1bc7274cfbc2fffd50609c7f379c495 内容长度:2 内容类型:应用程序/json 用户代理:sellergeni/1.0 (Php=7.2) x-amz-access-token:Atza|xxxxxxxxxxxxxxxxxxxxxxxxxxx x-amz-日期:20210204T060039Z 回复:403 { “错误”:[ { "message": "我们计算的请求签名与您提供的签名不匹配。请检查您的 AWS Secret Access Key 和签名方法。有关详细信息,请参阅服务文档。 此请求的规范字符串应该是 '得到 /订单/v0/订单 CreatedAfter=2021-01-15T05%3A26%3A31.308992&MarketplaceIds=A21TJRUUN4KGV 内容类型:应用程序/json 主持人:salespartnerapi-eu.amazon.com 用户代理:sellergeni/1.0 (Php=7.2) x-amz-access-token:Atza|IwEBII0yZlQvoo95puL9xxxxxxxxxxxxxxxxxx x-amz-日期:20210204T060039Z x-amz-安全令牌: 内容类型;主机;用户代理;x-amz-access-token;x-amz-date;x-amz-security-token 4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945' 字符串签名应该是 'AWS4-HMAC-SHA256 20210204T060039Z 20210204/eu-west-1/execute-api/aws4_request e995c02098c1a2d5d775380f1fc49804b32af9534b5e330145ca125fe098f0af' ", “代码”:“无效签名” } ] }
解决方案
跑:
sign pathparam/resource
代替:
/messaging/v1/orders/{orderId}
和:
/messaging/v1/orders/xxx-xxxxxxx-xxxxxxx
推荐阅读
- c - 如何将 char 缓冲区作为代码传递给 exec?
- conv-neural-network - 预测不在训练数据集中的类
- javascript - PUT XMLHttpRequest 在控制台返回空
- python - paramiko-sftp如何限制流量
- mql - 如何结合 Mongo $in 和 $cond
- css - 使用百分比将线性渐变应用于边框
- html - 如何在图像顶部对齐文本并使其具有响应性?
- javascript - 如何获取 Firebase 存储的图像 URL 的访问令牌?
- python - Numpy 连接行为。如何正确连接示例
- node.js - 等待 WriteStream.drain 不会将缓冲区刷新到文件