参考资料:
https://github.com/amzn/selling-partner-api-docs/blob/main/guides/zh-CN/developer-guide/SellingPartnerApiDeveloperGuide(%E4%B8%AD%E6%96%87).md#step-1-create-an-aws-account
1、授权
$oauthUri = 端点地址;
// @oauthUri 根据市场区分
$applicationId = '';
// @applicationId 开发者资料(应用ID)
$uri = 'https://' . $oauthUri . '/apps/authorize/consent?application_id=' . $applicationId . '&state=' . uniqid();
header('Location: ' . $uri);
可选参数:redirect_uri 用于将浏览器重定向到应用程序的 URI。这必须是在注册应用程序时指定的 OAuth 重定向 URI。如果不包括 redirect_uri 参数,则默认值为注册应用程序时指定的第一个 OAuth 重定向 URI。
2、授权回调
$_REQUEST[‘selling_partner_id’] ----- 商家ID merchant_id 开发者资料
$_REQUEST[‘spapi_oauth_code’] ----- 授权CODE
$client_id ----- 开发者资料(LWA凭证)
$client_secret----- 开发者资料(LWA密钥)
$params = array(
'client_id' => $client_id,
'client_secret' => $client_secret,
'code' => $_REQUEST['spapi_oauth_code'],
'grant_type' => 'authorization_code',
);
$config = array(
'base_uri' => 'https://api.amazon.com/auth/o2/token',
'form_params' => $params,
'verify' => false,
'timeout' => 60
);
$client = new GuzzleHttp\Client($config);
$request = $client->request('POST');
$body = $request->getBody()->getContents();
$response = json_decode($body, true);
// 如果请求成功会有以下数据返回
```php
$response = array(
'access_token' => '', //令牌
'expires_in' => '', // 令牌有效时间
'refresh_token' => '', // 令牌过期后可用此码获取令牌,而非重新授权
);
3、以refresh_token获取access_token
$params = array(
'client_id' => $client_id,
'client_secret' => $client_secret,
'refresh_token' => $refresh_token,
'grant_type' => 'refresh_token',
);
$config = array(
'base_uri' => 'https://api.amazon.com/auth/o2/token',
'form_params' => $params,
'verify' => false,
'timeout' => 60
);
$client = new GuzzleHttp\Client($config);
$request = $client->request('POST');
$body = $request->getBody()->getContents();
$response = json_decode($body, true);
5、发起请求(Feed Price)
https://developer-docs.amazon.com/sp-api/docs/connecting-to-the-selling-partner-api#step-3-add-headers-to-the-uri
// 请求参数
$params = array(
'contentType' => 'text/xml; charset=UTF-8',
);
$path = '/feeds/2020-09-04/feeds'; // 路径
$method = 'GET';
$datetime = date('Ymd\THis\Z', time() - 3600 * 8);
$host = '市场端点';
$aws_secret // secret access key 开发者资料 (IMA密钥)
$aws_key // access key ID 开发者资料(IMA ID)
// 标头
$headers = array(
'x-amz-access-token' => $access_token,
'x-amz-date' => $datetime,
'user-agent' => 'sXstem/1.0 (Language=PHP/7.0; Platform=Linux)',
'host' => $host
);
// 签名 https://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html
1 创建规范请求
$sign1 = '';
// 1.1 从 HTTP 请求方法(GET、PUT、POST等)开始,后跟换行符。
$sign1 .= $method . "\n";
// 1.2 添加规范 URI 参数,后跟换行符。
$sign1 .= $path . "\n";
// 1.3 添加规范查询字符串,后跟换行符(一般用于URL后缀参数)
if($method == 'GET')
{
ksort($params);
foreach ($params as $key => $value)
{
$sign1 .= urlencode($key) . '=' . urlencode($value) . "&";
}
$sign1 = trim($canonicalRequest, '&');
}
$sign1 .= "\n";
// 1.4 添加规范标头,后跟换行符
$signHeaderString = 'host;x-amz-date';
$signedHeadersArray = explode(';', $signHeaderString);
foreach ($signedHeadersArray as $headerName)
{
$sign1 .= $headerName . ':' . $headers[$headerName] . "\n";
}
// 1.5 添加已签名的标头,后跟换行符
$sign1 .= "\n" . $signHeaderString . "\n";
// 1.6 使用哈希(摘要)函数(如 SHA256)从 HTTP 或 HTTPS 请求正文中的有效负载创建哈希值
if ($method == 'POST')
{
$hashString = hash('sha256', $json_encode($params));
$sign1 .= $hashString;
}
// **使用用于散列有效负载的相同算法创建规范请求的摘要(哈希)**
$sign1 .= hash('sha256', $sign1);
2.创建要为签名的字符串
$region = ''; // 目标区域 https://developer-docs.amazon.com/sp-api/docs/sp-api-endpoints
// 2.1 从算法指定开始,后跟换行符
$sign2 = "AWS4-HMAC-SHA256" . "\n";
// 2.2 追加请求日期值,后跟换行符
$sign2 .= $datetime . "\n";
// 2.3 追加凭据作用域值,后跟换行符。
$credential = substr($datetime, 0, 8) . "/" . $region . "/execute-api/aws4_request";
$sign2 .= $credential . "\n";
// 2.4 追加在1.1创建规范请求中创建的规范请求的哈希。
$sign2 .= $sign1;
3 计算签名
// 3.1 派生签名密钥
$kDate = hash_hmac('sha256', substr($datetime, 0, 8), "AWS4" . $aws_secret, true);
$kRegion = hash_hmac('sha256', $region, $kDate, true);
$kService = hash_hmac('sha256', 'execute-api', $kRegion, true);
$kSigning = hash_hmac('sha256', 'aws4_request', $kService, true);
// 3.2 计算签名
$signature = hash_hmac('sha256', $sign2, $kSigning);
4 将签名添加到 HTTP 请求
$headers['Authorization'] = 'AWS4-HMAC-SHA256 Credential=' . $aws_key . '/' . $credential . ',SignedHeaders=' . $signHeaderString . ',Signature=' . $signature;
5 发起请求
$client = new GuzzleHttp\Client($config);
$request = $client->request(strtoupper($method));
$body = $request->getBody()->getContents();
$response = json_decode($body, true);
// 请求失败
if ( ! empty($response['errors']))
{
$errorMessage = array();
foreach ($response['errors'] as $error)
{
$errorMessage[] = $error['code'] . ': ' . $error['message'] . ' ' . (isset($error['details']) ? json_encode($error['details']) : '');
}
}