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