*当サイトのリンクにはAmazonアソシエイトやアフィリエイトリンクが含まれております。

Amazon SP-API のPHPコーディングメモ

サラリーのほうで、各ショッピングサイトの在庫連動システムをLaravelを用いて構築したのですが、
MWSが近々終了という事でSPAPIに移行しました。
すでに大半の移行が完了していたのですが、なぜかFBA在庫レポートのみ動作せずMWSを使っていました。
しかしながらMWS終了のメールが何度も来るので、重い腰を上げて再度向き合った時のメモ。

広告

Amazon SP-API の署名のメモ

上記のFBA在庫レポートに関してはどうしても動作しませんでした。
GET_AFN_INVENTORY_DATA を reportType に渡すとどうにもエラーです。

GIT上でもバグがあるってのが議論されてました。

日本では使えないのだろうか・・・

という事で別の方法で取得しました。

その時、署名の計算でハマったのでメモを残します。

GETの場合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
$spapi = new AmazonSpapiController;
 
$access_token = $spapi->get_actoken();
 
$host = $spapi::Api_set['host'];
$mid = $spapi::Api_set['MarketplaceId'];
$user_agent = $spapi::Api_set['user-agent'];
 
if ($queryString !== '') {
    $queryString .= '&MarketplaceIds=' . $mid;
    $request_url = 'https://' . $host . $request . '?' . $queryString;
} else {
    $request_url = 'https://' . $host . $request;
}
 
$gmtDate = gmdate("Ymd\THis\Z");
$ymdData = substr($gmtDate, 0, 8);
 
$headers = [
    'content-type:application/json;charset=UTF-8',
    'host:' . $host,
    'user-agent:' . $user_agent,
    'x-amz-access-token:' . $access_token, //事前取得アクセストークン
    'x-amz-date:' . $gmtDate
];
 
$canonicalRequest = [
    'method' => 'GET',
    'uri' => $request, //署名作成のまえに作ったリクエストURL
    'query' => $queryString, //署名作成のまえに作ったリクエストパラメーター
    'headers' => $headers,
    'signedheaders' => 'content-type;host;user-agent;x-amz-access-token;x-amz-date',
    'payload' => hash('sha256', ''),
];
 
//リクエスト生成 -1
$canonical_request = $spapi->CanonicalRequest($canonicalRequest);
 
//署名を計算 -2
$signing_key = $spapi->signatureKey($ymdData);
 
$algorithm = 'AWS4-HMAC-SHA256';
$param['amzdate'] = $gmtDate;
$param['datestamp'] = $ymdData;
$param['method'] = 'GET';
$signature = $spapi->signature($param, $canonical_request, $algorithm, $signing_key);
 
$auth = $spapi->createAuthorization($param, $canonicalRequest, $signature, $algorithm);
 
//これがバージョン4の署名で必要になる文字列
//ヘッダ情報に追加
$headers[] =  'Authorization: ' . $auth;
 
$json_response = $spapi->get_spapi_json($headers, $request_url, false);

こんな感じ。
他の関数とやり取りしてるので、コピペじゃ動きませんのであしからず・・・。

POSTの場合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
$spapi = new AmazonSpapiController;
$access_token = $spapi->get_actoken();
 
$host = $spapi::Api_set['host'];
$mid = $spapi::Api_set['MarketplaceId'];
$user_agent = $spapi::Api_set['user-agent'];
 
$request = "/reports/2021-06-30/reports";
$request_url = 'https://' . $host . $request;
 
/**
 * GET_FLAT_FILE_OPEN_LISTINGS_DATA -> 出品レポート
 */
$queryString = '{
   "reportType": "GET_FLAT_FILE_OPEN_LISTINGS_DATA",
   "marketplaceIds":["' . $mid . '"]
}';
 
$gmtDate = gmdate("Ymd\THis\Z"); //リクエストごとの先頭で予め取得しとくといいです。
$ymdData = substr($gmtDate, 0, 8);
 
$request_headers = [];
$request_headers['content-type'] = 'application/json';
$request_headers['host'] = $host;
$request_headers['x-amz-access-token'] = $access_token;
$request_headers['x-amz-content-sha256'] = hash('sha256', $queryString);
$request_headers['x-amz-date'] = $gmtDate;
 
//Canonical headers & Signed headers
$csheaders = $spapi->MakeheadInner($request_headers);
 
$canonicalRequest = [
    'method' => 'POST',
    'uri' => $request, //署名作成のまえに作ったリクエストURL
    'headers' => [$csheaders['ch']],
    'signedheaders' => $csheaders['sh'],
    'payload' => hash('sha256', $queryString),
];
 
//リクエスト生成 -1
$hashed_canonical = $spapi->CanonicalRequest($canonicalRequest);
 
//署名を計算 -2
$signature = $spapi->signatureKey($ymdData);
 
$algorithm = 'AWS4-HMAC-SHA256';
$param['amzdate'] = $gmtDate;
$param['datestamp'] = $ymdData;
$param['method'] = 'POST';
$signature = $spapi->signature($param, $hashed_canonical, $algorithm, $signature);
 
$auth = $spapi->createAuthorization($param, $canonicalRequest, $signature, $algorithm);
 
// Curl headers
$curl_headers = ['Authorization: ' . $auth];
foreach ($request_headers as $key => $value) {
    $curl_headers[] = $key . ": " . $value;
}
 
$json_response = $spapi->get_spapi_json($curl_headers, $request_url, $queryString);

GETとちょっとだけ違う。
たしかこれ作った時、どっちかを先に作って使いまわしたんで、無駄なコードがあると思います。

FBA在庫取得の解消方法

/fba/inventory/v1/summaries にリクエスト出すとFBAの在庫を取得できました。
こっちのがFBA在庫レポートを発行させるより効率良いようです。

だから GET_AFN_INVENTORY_DATA は動かないのかな??
分からんけど。

ちなみにバイト代くれればSPAPI対応のPHP作れなくもないです。
ではでは。


おすすめのコンテンツ

広告

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

This site uses Akismet to reduce spam. Learn how your comment data is processed.