Amazon APIのRequestへの電子署名添付(PHP版)
June 24, 2009 – 4:16 pmこの5月から「AmazonアソシエイトWebサービス」が「Product Advertising API」に変更されること、そして来る8月からはAPIを用いた商品データベースにアクセスする際には電子署名が必要になるとの案内が届いた。我が方も、これに対応するため、簡単なPHP関数を作成した。このエントリーでは、今回作成したPHP関数と、これを用いた従来のコードの修正方法についてメモした。
電子署名添付の手続きその他は、
http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/
に記述されている。このうち、RESTを用いたRequestについては、このなかのExample REST Requestsにおいて、電子署名を付加するための手順がステップ・バイ・ステップでしめされている。今回、私が作成したコードは、この手順に、できる限り忠実に従ったつもりである。
PHP関数の作成: 今回作成したPHP関数は、canonical_Str()とget_Signature()の二つだ。Canonical_Str()では、認証用Signatureを得るためにRequestの前処理を行う。get_Signature()では、処理済のRequest等を用いて、Signatureを求めている。
なお、今回用いたphpのバージョンは、5.2.9である。
この二つの関数は、以下の通り:
function canonical_Str( $request ) { $request = str_replace( ',', '%2C', $request ); $request = str_replace( ':', '%3A', $request ); $request = str_replace( '%7E', '~', $request ); $req_split = array(); $req_split = split("&", $request); sort( $req_split ); $str_join = implode('&', $req_split ); return $str_join; } function get_Signature( $request, $aws_host ) { $key = "Your Secret Key is placed here"; $prep01 = 'GET'; $prep02 = $aws_host; $prep03 = '/onca/xml'; $str_to_sign = $prep01 . "\n" . $prep02 . "\n" . $prep03 . "\n". $request; $algo = "sha256"; $hash_out = hash_hmac( $algo, $str_to_sign, $key, true ); $signature = urlencode(base64_encode($hash_out)); return $signature; }
従来コード修正の具体例: 昨年9月に、「アマゾンの書籍データにphpでアクセスしてみた」を書いた。ここでアマゾンの書籍データを取得するために用いた「Request」に対し、上記のPHP関数を使用すると電子署名がどのように付加されるかを示す。
従来方式に対応するRequest(URLストリング)の指定部分:
$request="http://ecs.amazonaws.jp/onca/xml?Service=AWSECommerceService&AWSAcce ssKeyId=xxxxxxxxxxxxxxxxxxxx&AssociateTag=yyyyyyyyyyyyyyyy&Version=2006-09-11& Operation=ItemLookup&ResponseGroup=Large,Offers&SearchIndex=Books&IdType=ISBN& ItemId=4152085576&ItemPage=1";
を、以下に置き換える:
$aws_host ="ecs.amazonaws.jp"; $request ="Service=AWSECommerceService&AWSAccessKeyId=xxxxxxxxxxxxxxx&Associa teTag=yyyyyyyyyyyy&Version=2006-09-11&Operation=ItemLookup&ResponseGroup=Large, Offers&SearchIndex=Books&IdType=ISBN&ItemId=4152085576&ItemPage=1"; $request .="&Timestamp=".str_replace('GMT','T',gmdate("Y-m-dTH:i:s"))."Z"; $request = canonical_Str( $request ); $signature = get_Signature( $request, $aws_host ); $request = "http://".$aws_host."/onca/xml?".$request."&Signature=".$signature;
参考のため、以下に書籍データ取得に際して用いたコードの全体、ならびに出力を示しておく:
sample.php:
<?php function canonical_Str( $request ) { $request = str_replace( ',', '%2C', $request ); $request = str_replace( ':', '%3A', $request ); $request = str_replace( '%7E', '~', $request ); $req_split = array(); $req_split = split("&", $request); sort( $req_split ); $str_join = implode('&', $req_split ); return $str_join; } function get_Signature( $request, $aws_host ) { $key = "Your Secret Key is placed here"; $prep01 = 'GET'; $prep02 = $aws_host; $prep03 = '/onca/xml'; $str_to_sign = $prep01 . "\n" . $prep02 . "\n" . $prep03 . "\n". $request; $algo = "sha256"; $hash_out = hash_hmac( $algo, $str_to_sign, $key, true ); $signature = urlencode(base64_encode($hash_out)); return $signature; } $aws_host ="ecs.amazonaws.jp"; $request ="Service=AWSECommerceService&AWSAccessKeyId=xxxxxxxxxxxxxxxxxxxx&Assoc iateTag=yyyyyyyyyyyyyyyy&Version=2006-09-11&Operation=ItemLookup&ResponseGroup=Large ,Offers&SearchIndex=Books&IdType=ISBN&ItemId=4152085576&ItemPage=1"; $request .= "&Timestamp=" . str_replace('GMT','T',gmdate("Y-m-dTH:i:s")) . "Z"; $request = canonical_Str( $request ); $signature = get_Signature( $request, $aws_host ); $request = "http://".$aws_host."/onca/xml?".$request."&Signature=". $signature; $response = file_get_contents($request); $parsed_xml = simplexml_load_string($response); $Image_URL = $parsed_xml->Items->Item->MediumImage->URL; $Title = $parsed_xml->Items->Item->ItemAttributes->Title; $Author = $parsed_xml->Items->Item->ItemAttributes->Author; $Creator = $parsed_xml->Items->Item->ItemAttributes->Creator; $Creator_Role = $parsed_xml->Items->Item->ItemAttributes->Creator['Role']; $Publ_date = $parsed_xml->Items->Item->ItemAttributes->PublicationDate; echo $Title . "written by " . $Author . "\n"; echo " translated by " . $Creator . "/" . $Creator['Role'] . "\n"; echo " publised on " . $Publ_date . "\n"; ?>
実行例:
$ php sample.php 盲目の時計職人written by リチャード・ドーキンス translated by 日高 敏隆/翻訳 publised on 2004-03-24
2 Responses to “Amazon APIのRequestへの電子署名添付(PHP版)”
OperationのパラメータをItemSearchとし、商品名などを日本語(文字コード:UTF-8)で指定した場合、Signatureが正しく導出されないという問題が発生している。
原因を検討中。
なお、英文(アルファベット)のみの場合は、問題なく動作する。
検討の結果: 日本語文字がクエリに含まれる場合には、これをurlencodeしておかなければならない。このあたりを満足するためのコードは別エントリーにて説明予定。
By yama on Jun 29, 2009