2022.9.30でMWSが廃止となり、SP-APIへの移行が避けられないため、
アプリを修正しています。phpでの実装例が少ないので参考になれば。
例えば、情報をうまく使えば、こんなの作れます^^
フロー
大まかな処理の流れは下記の通り。
事前にAWS IAMユーザの作成とAmazon Seller Centralの開発者情報を取得しておく。
詳細版)
ソース公開
動作確認用の暫定コードです。2022-04-01版で動作確認済@2022.7.4
※php7.4、php8.0環境で動作済み
※php7.2、php5.4環境では、jsonのデータ引き渡しでNG
- <?php
- //出品者毎に固有のパラメータ
- $AWS_CLIENT_ID = 'am--------------------';
- $AWS_CLIENT_SECRET_KEY = 'cf-------------------------';
- $AWS_REFRESH_TOKEN = 'At-----------------------------------------------------------------';
-
- $DEV_ACCESS_KEY = 'A-----------------';
- $DEV_SECRET_ACCESS_KEY = 'yV----------------------------------';
-
- ////////////////////////////////////////////////////////////
- //0.初期化処理
- // 固定値と変数枠を準備する。
- //
- ////////////////////////////////////////////////////////////
-
- $DEBUG_MODE=0; //0:通常モード 1:デバッグモード
- $GMT_DATE = gmdate("Ymd\THis\Z");
- $DATE = substr($GMT_DATE, 0, 8);
-
- $ASIN_CODE = "B007BFMY3I"; //サンプル商品
- $REQUEST_SUB_URL = "/catalog/2022-04-01/items/".$ASIN_CODE;
-
- $F_CANONICALREQUEST_QUERY = "marketplaceIds=A1VC38T7YXB528"; //日本のマーケットプレイス
- $F_REQUEST_URL = "https://sellingpartnerapi-fe.amazon.com" .$REQUEST_SUB_URL ."?" . $F_CANONICALREQUEST_QUERY;
-
-
- $F_CURLOPT_HTTPHEADER_ARRAY = array(
- 'CONTENT-TYPE' => 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8',
- 'HOST' => 'Host: api.amazon.com',
- 'ACT' => 'POST /auth/o2/token HTTP/l.l'
- );
- $F_CURLOPT_POSTFIELDS_ARRAY = array(
- 'grant_type' => 'refresh_token',
- 'refresh_token' => $AWS_REFRESH_TOKEN,
- 'client_id' => $AWS_CLIENT_ID,
- 'client_secret' => $AWS_CLIENT_SECRET_KEY
- );
- $F_ACC_CURLOPT_ARRAY = array(
- 'CUSTOMREQUEST' => 'POST',
- 'HTTPHEADER_ARRAY' => $F_CURLOPT_HTTPHEADER_ARRAY,
- 'TOKEN_URL' => 'https://api.amazon.com/auth/o2/token',
- 'RETURNTRANSFER' => 'TRUE',
- 'POST' => 'TRUE',
- 'VERIFYPEER' => 'FALSE',
- 'VERIFYHOST' => 'FALSE',
- 'POSTFIELDS_ARRAY' => $F_CURLOPT_POSTFIELDS_ARRAY
- );
- $F_CANONICALREQUEST_HEADERS = array(
- 'HOST' => 'host:sellingpartnerapi-fe.amazon.com',
- 'USER_AGENT' => 'user-agent:test_pg',
- 'ACCESS_TOKEN' => '', //アクセストークン取得後に代入する。
- 'DATE' => 'x-amz-date:' . $GMT_DATE
- );
- $F_CANONICALREQUEST_ARRAY = array(
- 'METHOD' => 'GET',
- 'URL' => $REQUEST_SUB_URL,
- 'QUERY' => $F_CANONICALREQUEST_QUERY,
- 'HEADERS' => '', //アクセストークン取得後に代入する。
- 'SIGNED_HEADERS'=> 'host;user-agent;x-amz-access-token;x-amz-date',
- 'PAYLOAD' => hash('sha256','')
- );
- $F_SIGNATURE_ARRAY_0 = array(
- 'DATE' => $DATE,
- 'DEV_SECRET_ACCESS_KEY' => $DEV_SECRET_ACCESS_KEY,
- 'HEAD' => 'AWS4',
- 'HASH' => 'sha256',
- 'AWS_REGION' => 'us-west-2',
- 'AWS_SERVICE' => 'execute-api',
- 'AWS_TERMINATION' => 'aws4_request',
- );
- $F_SIGNATURE_ARRAY_1 = array(
- 'GMT_DATE' => $GMT_DATE,
- 'DATE' => $F_SIGNATURE_ARRAY_0['DATE'],
- 'CANONICAL_REQUEST' => '', //正規リクエスと作成後に代入する。
- 'SIGNATURE_ALGORITHM' => 'AWS4-HMAC-SHA256',
- 'SIGNING_KEY' => '', //署名キー作成後に代入する。
- 'AWS_REGION' => $F_SIGNATURE_ARRAY_0['AWS_REGION'],
- 'AWS_SERVICE' => $F_SIGNATURE_ARRAY_0['AWS_SERVICE'],
- 'AWS_TERMINATION' => $F_SIGNATURE_ARRAY_0['AWS_TERMINATION']
- );
- $F_SIGNATURE_ARRAY_2 = array(
- 'DATE' => $F_SIGNATURE_ARRAY_0['DATE'],
- 'CANONICAL_REQUEST_ARRAY' => '', //アクセストークン取得後に代入する。
- 'SIGNATURE' => '', //署名作成後に代入する。
- 'SIGNATURE_ALGORITHM' => $F_SIGNATURE_ARRAY_1['SIGNATURE_ALGORITHM'],
- 'DEV_ACCESS_KEY' => $DEV_ACCESS_KEY,
- 'AWS_REGION' => $F_SIGNATURE_ARRAY_0['AWS_REGION'],
- 'AWS_SERVICE' => $F_SIGNATURE_ARRAY_0['AWS_SERVICE'],
- 'AWS_TERMINATION' => $F_SIGNATURE_ARRAY_0['AWS_TERMINATION']
- );
- $F_GET_CURLOPT_HTTPHEADER_ARRAY = array(
- 'AUTH_HEADER' => '', //認証ヘッダを作成後に代入する。
- 'HOST' => 'host:sellingpartnerapi-fe.amazon.com',
- 'USER-AGENT' => 'user-agent:test_pg',
- 'ACCESS_TOKEN' => '', //アクセストークン取得後に代入する。
- 'GMT_DATE' => 'x-amz-date:' . $GMT_DATE
- );
- $F_GET_CURLOPT_ARRAY = array(
- 'CUSTOMREQUEST' => 'GET',
- 'HTTPHEADER_ARRAY' => '', //認証ヘッダを作成後に代入する。
- 'REQUEST_URL' => $F_REQUEST_URL,
- 'RETURNTRANSFER' => 'TRUE',
- 'POST' => 'FALSE',
- 'VERIFYPEER' => 'FALSE',
- 'VERIFYHOST' => 'FALSE',
- 'HEADER' => 'TRUE'
- );
-
- ////////////////////////////////////////////////////////////
- //1.アクセストークンの取得
- //
- // input :固定値、AWS情報、開発者キーなど
- // output :アクセストークン
- //
- ////////////////////////////////////////////////////////////
-
- //Processing
- // initialize curl header
- $CURL_HEADER = curl_init();
-
- // set curl options
- curl_setopt($CURL_HEADER, CURLOPT_CUSTOMREQUEST, $F_ACC_CURLOPT_ARRAY['CUSTOMREQUEST']);
- curl_setopt($CURL_HEADER, CURLOPT_HTTPHEADER, $F_ACC_CURLOPT_ARRAY['HTTPHEADER_ARRAY']);
- curl_setopt($CURL_HEADER, CURLOPT_URL, $F_ACC_CURLOPT_ARRAY['TOKEN_URL']);
- curl_setopt($CURL_HEADER, CURLOPT_RETURNTRANSFER, $F_ACC_CURLOPT_ARRAY['RETURNTRANSFER']);
- curl_setopt($CURL_HEADER, CURLOPT_POST, $F_ACC_CURLOPT_ARRAY['POST']);
- curl_setopt($CURL_HEADER, CURLOPT_SSL_VERIFYPEER, $F_ACC_CURLOPT_ARRAY['VERIFYPEER']);
- curl_setopt($CURL_HEADER, CURLOPT_SSL_VERIFYHOST, $F_ACC_CURLOPT_ARRAY['VERIFYHOST']);
- curl_setopt($CURL_HEADER, CURLOPT_POSTFIELDS, http_build_query($F_ACC_CURLOPT_ARRAY['POSTFIELDS_ARRAY']));
-
- // running curl
- $CUR_RES = curl_exec($CURL_HEADER);
- curl_close($CURL_HEADER);
-
- // formatting
- $json_response = json_decode($CUR_RES);
- // get access_token(output)
- $ACCESS_TOCKEN = $json_response->access_token;
-
-
- $F_CANONICALREQUEST_HEADERS['ACCESS_TOKEN'] = 'x-amz-access-token:'.$ACCESS_TOCKEN;
- $F_CANONICALREQUEST_ARRAY['HEADERS'] = $F_CANONICALREQUEST_HEADERS;
- $F_SIGNATURE_ARRAY_2['CANONICAL_REQUEST_ARRAY'] = $F_CANONICALREQUEST_ARRAY;
- $F_GET_CURLOPT_HTTPHEADER_ARRAY['ACCESS_TOKEN'] = 'x-amz-access-token:' . $ACCESS_TOCKEN;
-
-
- if( $DEBUG_MODE == 1){
- echo $ACCESS_TOCKEN . "\n";
- }
-
- ////////////////////////////////////////////////////////////
- //2.署名
- //
- // input :固定値、AWS情報、開発者キー、アクセストークンなど
- // output :認証ヘッダー
- //
- ////////////////////////////////////////////////////////////
-
- //リクエスト生成
- $F_SIGNATURE_ARRAY_1['CANONICAL_REQUEST']=CanonicalRequest($F_CANONICALREQUEST_ARRAY);
-
- //署名を計算
- $F_SIGNATURE_ARRAY_1['SIGNING_KEY']=SignatureKey($F_SIGNATURE_ARRAY_0);
-
- if( $DEBUG_MODE == 1){
- echo "-----signature array-------------------\n";
- echo "GMT_DATE:" . $F_SIGNATURE_ARRAY_1['GMT_DATE'] . "\n";
- echo "DATE:" . $F_SIGNATURE_ARRAY_1['DATE'] . "\n";
- echo "CANONICAL_REQUEST:" . bin2hex($F_SIGNATURE_ARRAY_1['CANONICAL_REQUEST']) . "\n";
- echo "SIGNATURE_ALGORITHM:" . $F_SIGNATURE_ARRAY_1['SIGNATURE_ALGORITHM'] . "\n";
- echo "SIGNING_KEY:" . bin2hex($F_SIGNATURE_ARRAY_1['SIGNING_KEY']) . "\n";
- echo "AWS_REGION:" . $F_SIGNATURE_ARRAY_1['AWS_REGION'] . "\n";
- echo "AWS_SERVICE:" . $F_SIGNATURE_ARRAY_1['AWS_SERVICE'] . "\n";
- echo "AWS_TERMINATION:" . $F_SIGNATURE_ARRAY_1['AWS_TERMINATION'] . "\n";
- echo "---------------------------------------\n";
- }
-
- $F_SIGNATURE_ARRAY_2['SIGNATURE'] = SignatureByAlgo($F_SIGNATURE_ARRAY_1);
-
- if( $DEBUG_MODE == 1){
- echo "signature:" . bin2hex($F_SIGNATURE_ARRAY_2['SIGNATURE']) . "\n";
- }
-
- //認証ヘッダ作成
- $AuthorizationHeader = CreateAuthorization($F_SIGNATURE_ARRAY_2);
-
- if( $DEBUG_MODE == 1){
- echo "AuthorizationHeader :" . $AuthorizationHeader . "\n";
- }
-
- ////////////////////////////////////////////////////////////
- //3.データ取得
- //
- // input :認証ヘッダー
- // output :クエリ結果
- //
- ////////////////////////////////////////////////////////////
-
- $F_GET_CURLOPT_HTTPHEADER_ARRAY['AUTH_HEADER']=$AuthorizationHeader; //認証ヘッダ
- $F_GET_CURLOPT_ARRAY['HTTPHEADER_ARRAY']= $F_GET_CURLOPT_HTTPHEADER_ARRAY;
-
- // 必要に応じてオプションを追加。
- $CURL_HEADER = curl_init();
- curl_setopt($CURL_HEADER, CURLOPT_CUSTOMREQUEST, $F_GET_CURLOPT_ARRAY['CUSTOMREQUEST']);
- curl_setopt($CURL_HEADER, CURLOPT_HTTPHEADER, $F_GET_CURLOPT_ARRAY['HTTPHEADER_ARRAY']);
- curl_setopt($CURL_HEADER, CURLOPT_URL, $F_GET_CURLOPT_ARRAY['REQUEST_URL']);
- curl_setopt($CURL_HEADER, CURLOPT_RETURNTRANSFER, $F_GET_CURLOPT_ARRAY['RETURNTRANSFER']);
- curl_setopt($CURL_HEADER, CURLOPT_POST, $F_GET_CURLOPT_ARRAY['POST']);
- curl_setopt($CURL_HEADER, CURLOPT_SSL_VERIFYPEER, $F_GET_CURLOPT_ARRAY['VERIFYPEER']);
- curl_setopt($CURL_HEADER, CURLOPT_SSL_VERIFYHOST, $F_GET_CURLOPT_ARRAY['VERIFYHOST']);
- curl_setopt($CURL_HEADER, CURLOPT_HEADER, $F_GET_CURLOPT_ARRAY['HEADER']);
-
- $CUR_RES = curl_exec($CURL_HEADER);
- curl_close($CURL_HEADER);
- $json_response = json_decode($CUR_RES);
-
- echo count( $json_response -> summaries ) . "\n";
-
- echo "ASIN:" . $json_response -> asin . "\n";
- echo "brand :" . $json_response -> summaries['0'] -> brand . "\n";
- echo "browseClassification(classificationId):" . $json_response -> summaries['0'] -> browseClassification -> classificationId . "\n";
- echo "browseClassification(displayName):" . $json_response -> summaries['0'] -> browseClassification -> displayName . "\n";
- echo "itemClassification:" . $json_response -> summaries['0'] -> itemClassification . "\n";
- echo "itemName:" . $json_response -> summaries['0'] -> itemName . "\n";
- echo "manufacturer:" . $json_response -> summaries['0'] -> manufacturer . "\n";
- echo "marketplaceId:" . $json_response -> summaries['0'] -> marketplaceId . "\n";
- echo "websiteDisplayGroup:" . $json_response -> summaries['0'] -> websiteDisplayGroup . "\n";
- echo "websiteDisplayGroupName:" . $json_response -> summaries['0'] -> websiteDisplayGroupName . "\n";
-
- //以降、関数--------------------------------------
- function CanonicalRequest($IN_CR_ARRAY) {
- $STR = $IN_CR_ARRAY['METHOD'] . "\n"
- . $IN_CR_ARRAY['URL'] . "\n"
- . $IN_CR_ARRAY['QUERY'] . "\n";
-
- if (count($IN_CR_ARRAY['HEADERS']) > 0) {
- foreach ($IN_CR_ARRAY['HEADERS'] as $HEAD) {
- $STR .= $HEAD . "\n";
- }
- } else {
- $STR .= "\n";
- }
-
- $STR .= "" . "\n"
- . $IN_CR_ARRAY['SIGNED_HEADERS'] . "\n"
- . $IN_CR_ARRAY['PAYLOAD'];
-
- return hash('sha256', $STR, true);
- }
-
- function SignatureKey($IN_SIG_ARR) {
- $S_Key =hash_hmac($IN_SIG_ARR['HASH'], $IN_SIG_ARR['AWS_TERMINATION'],
- hash_hmac($IN_SIG_ARR['HASH'], $IN_SIG_ARR['AWS_SERVICE'],
- hash_hmac($IN_SIG_ARR['HASH'], $IN_SIG_ARR['AWS_REGION'],
- hash_hmac($IN_SIG_ARR['HASH'], $IN_SIG_ARR['DATE'], $IN_SIG_ARR['HEAD'] . $IN_SIG_ARR['DEV_SECRET_ACCESS_KEY'], true), true), true), true);
- return $S_Key;
- }
-
- function SignatureByAlgo($IN_SIG_ARR) {
- //認証情報スコープ(日付/リージョン/サービス/終端文字)
- $TAEGET_STR = $IN_SIG_ARR['SIGNATURE_ALGORITHM'] . "\n"
- . $IN_SIG_ARR['GMT_DATE'] . "\n"
- . $IN_SIG_ARR['DATE'] . "/"
- . $IN_SIG_ARR['AWS_REGION'] . "/"
- . $IN_SIG_ARR['AWS_SERVICE'] . "/"
- . $IN_SIG_ARR['AWS_TERMINATION'] . "\n"
- . bin2hex($IN_SIG_ARR['CANONICAL_REQUEST']);
-
- // echo "-----sign_func-------------------\n";
- // echo $TAEGET_STR . "\n";
- // echo "-----sign_func-------------------\n";
- return hash_hmac('sha256', $TAEGET_STR, $IN_SIG_ARR['SIGNING_KEY'], true);
- }
-
- function CreateAuthorization($IN_SIG_ARR) {
- //Authorizationヘッダー(アルゴ Credential=AWSアクセスID/認証スコープ,SignedHeaders=host;user-agent;x-amz-accesstoken;xamz-date, )
- $STR = 'Authorization: '
- . $IN_SIG_ARR['SIGNATURE_ALGORITHM']
- . ' Credential=' . $IN_SIG_ARR['DEV_ACCESS_KEY'] . "/". $IN_SIG_ARR['DATE'] . "/". $IN_SIG_ARR['AWS_REGION'] . "/". $IN_SIG_ARR['AWS_SERVICE'] . "/". $IN_SIG_ARR['AWS_TERMINATION']
- . ', SignedHeaders=' . $IN_SIG_ARR['CANONICAL_REQUEST_ARRAY']['SIGNED_HEADERS']
- . ', Signature=' . bin2hex($IN_SIG_ARR['SIGNATURE']);
-
- return $STR;
- }
- ?>
関連記事
・SP-APIリクエストをPostmanで確認する方法
・SP-APIリクエスト(アクセストークン取得)
・SP-APIリクエスト(商品情報取得)
・SP-APIリクエスト(商品情報取得JAN)
・SP-APIリクエスト(価格取得)
参考サイト
SP-API関連)
・Amazon MWS から SP-API への移行 [準備編]
・【解決済】2022年10月以降、MWSで全ての商品情報が、SP-APIで…
・Amazon SP-APIをPHP ノンフレームワークで実装してみたので使い方を説明します
ブログ記載関連)
・マージナルソフト:ソースをHTML化
コメント
ソース参考にさせていただきました。
クエリに「includedData」を追加した場合にデータ取得がうまくいきませんでした。
・OK
https://sellingpartnerapi-fe.amazon.com/catalog/2022-04-01/items/B00K85QDQM?marketplaceIds=A1VC38T7YXB528&i
・NG
https://sellingpartnerapi-fe.amazon.com/catalog/2022-04-01/items/B00K85QDQM?marketplaceIds=A1VC38T7YXB528&includedData=attributes%2CsalesRanks
何か追加の処理が必要でしょうか??
解決しまいた。
クエリのパラメータの順番がアルファベット順でないとエラーになるようです。
https://sellingpartnerapi-fe.amazon.com/catalog/2022-04-01/items/B0BQHHNV9V?includedData=attributes%2Csummaries&marketplaceIds=A1VC38T7YXB528
このURLでデータ取得できました。
コメントありがとうございます。
※スパムが多すぎて返信できておらず、すんません。
確かに、「アルファベット順でないとエラーが出る」ということもありましたね。
マニュアルにも記載があったように記憶していますが、そんな仕様いる?と疑問ですね。
なにはともあれ、自己解決されて何よりです^^
ただ、逆に言えば、微妙な仕様がありすぎて理解するのが大変なので、
ソースのたたき台を丸々公開させていただいている次第です。
[…] ・phpでSP-APIを利用する方法(認証編) […]