アマゾンAPIの電子署名添付:日本語文字をURL-Encodeしておくことが必須
July 1, 2009 – 4:24 pm1週間ほど前、「Amazon APIのRequestへの電子署名添付(PHP版)」を書いた。ここで、アマゾンDBへのアクセスに必要になった電子署名を付け加えるためのphp関数と使用法について説明しておいた。ところが、以前に作成したコードの修正作業をするなかで、書名などの日本語文字が含まれるRequestに対しては、正しく動作しないことが分かった。原因は、日本語文字など2バイト文字をRequestに含める場合には、これらをurlencodeしておかねばならないということらしい。修正版のphpコードを示しておいた。
電子署名つきRequest作成用のphp関数: 前回の修正版のphp関数(署名作成用関数)は下記:
Signature.php
<?php function canonical_Str( $request ) { $req_split = array(); $req_split = split("&", $request); for( $i=0; $i<count($req_split); $i++) { $req_split[$i] = urlencode( $req_split[$i] ); $req_split[$i] = str_replace( '%3D', '=', $req_split[$i] ); } 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; } ?>
前回のコードとの違いは、Request用のパラメータセットのそれぞれをurlencodeしておくという点だ。今のところ、特段の問題なく正常に動作している。なお、前回のコードについても、日本語文字(文字コードUTF-8)があらかじめurlencodeされていれば動作する。
電子署名が要求されない従来のRequestについては、書名などの日本語文字(UTF-8コード)をurlencodeしない生のままで含めても問題なく処理されていた。そのあたり、アマゾンの説明では、何も言及されていない。少し、不親切ではないのかと思ってしまう。
参考のため、以前「アマゾンAPIを活用した蔵書管理システム(1)」で示した書籍検索用のphp関数BookSearch()の署名添付した形の修正版、並びに動作例を以下に示しておく。但し、コードは、上記したエントリー「アマゾンAPIを活用した蔵書管理システム(1)」に示したものを電子署名部のみ修正したものになっており、以前に書いたものと重複するが、このエントリに示したもののみで動作するよう関連コードを全て書いた。このコードの使用に際しては、Secret-ID、Key-ID、Associate-Tagなどを自らのものに書き換えて欲しい。使用に際して問題を見つけた場合には、コメントしていただければありがたい。
BookSearch.php
<?php function BookSearch($Title_Search, $Author_Search, $Page_AWS) { require_once("./TmpBook.php"); require_once("./Signature.php"); define('KEYID','Your Key-Id placed here'); define('AssocTag','Your Associate Tag placed here'); $aws_host = "ecs.amazonaws.jp"; $request='Service=AWSECommerceService' . '&AWSAccessKeyId='.KEYID.'&Operation=ItemSearch' . '&ResponseGroup=Medium&Version=2006-09-11&SearchIndex=Books' . '&Title=' . $Title_Search . '&Author=' . $Author_Search . '&ItemPage=' . $Page_AWS; $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); // Get AWS 判定 $IsValid = $parsed_xml->Items->Request->IsValid; if( $IsValid != 'True' ) return -1; // $No_of_Results = $parsed_xml->Items->TotalResults; $n_foreach = 0; $tmpbook_array = array(); foreach( $parsed_xml->Items->Item as $Item ) { // Get ASIN $Asin = $Item->ASIN; // Get Book_Data $Attributes = $Item->ItemAttributes; $Binding = $Attributes->Binding; $Isbn = $Attributes->ISBN; $EAN = $Attributes->EAN; $Pub_Date = $Attributes->PublicationDate; $Publisher = $Attributes->Publisher; $Title = $Attributes->Title; $author_name = array(); $ncr = 0; foreach( $Attributes->Author as $Author_name ) { $author_name[$ncr] = $Author_name; // echo "author = " . $author . "\n"; $ncr = $ncr + 1; } foreach( $Attributes->Creator as $Creator ) { $author_name[$ncr] = $Creator; $ncr = $ncr + 1; } $Author_name = $author_name[0]; $tmpbook = new TmpBook(); $tmpbook->setNoOfItems($No_of_Results); $tmpbook->setAsin($Asin); $tmpbook->setIsbn($Isbn); $tmpbook->setEan($EAN); $tmpbook->setPubdate($Pub_Date); $tmpbook->setPublisher($Publisher); $tmpbook->setTitle($Title); $tmpbook->setAuthor($Author_name); $tmpbook->setBinding($Binding); $tmpbook_array[] = $tmpbook; $n_foreach = $n_foreach + 1; if ( $n_foreach >=10 || $n_foreach == $No_of_Results ) break; } return $tmpbook_array; } ?>
TmpBook.php:
<?php class TmpBook { private $no_of_items = ""; private $asin = ""; private $isbn = ""; private $ean = ""; private $title = ""; private $pubdate = ""; private $page = ""; private $publisher = ""; private $binding = ""; private $author = ""; public function toString() { return (string) ($this->no_of_items . "\t" . $this->asin ."\t" . $this->isbn . "\t" . $this->ean . "\t" . $this->title . "\t" . $this->author . "\t" . $this->pubdate . "\t" . $this->publisher . "\t" . $this->binding . "\t" ); } public function getNoOfItems() { return $this->no_of_items; } public function setNoOfItems($no_of_items) { $this->no_of_items = $no_of_items; } public function getAsin() { return $this->asin; } public function setAsin($asin) { $this->asin = $asin; } public function getIsbn() { return $this->isbn; } public function setIsbn($isbn) { $this->isbn = $isbn; } public function getEan() { return $this->ean; } public function setEan($ean) { $this->ean = $ean; } public function getTitle() { return $this->title; } public function setTitle($title) { $this->title = $title; } public function getAuthor() { return $this->author; } public function setAuthor($author) { $this->author = $author; } public function getPubdate() { return $this->pubdate; } public function setPubdate($pubdate) { $this->pubdate = $pubdate; } public function getPages() { return $this->pages; } public function setPages($pages) { $this->pages = $pages; } public function getPublisher() { return $this->publisher; } public function setPublisher($publisher) { $this->publisher = $publisher; } public function getBinding() { return $this->binding; } public function setBinding($binding) { $this->binding = $binding; } } ?>
動作例:
Sample.php:
<?php require_once("BookSearch.php"); $title = urlencode('沈黙'); $title = '沈黙'; $author = urlencode('遠藤周作'); $author ='遠藤周作'; $page = '1'; $books = BookSearch($title,$author,$page); echo "No of Items : " . $books[0]->getNoOfItems() . "\n"; echo "size of tmp_array : " . sizeof($books) . "\n"; for( $i= 0; $i<sizeof($books); $i++ ) echo $books[$i]->getAsin() . ": " . $books[$i]->getAuthor() . ": " . $books[$i]->getTitle() . ": " . $books[$i]->getPublisher() . "\n"; $books=NULL; ?>
出力:
% php Sample.php No of Items : 12 size of tmp_array : 10 4101123152: 遠藤 周作: 沈黙 (新潮文庫): 新潮社 410303517X: 遠藤 周作: 沈黙: 新潮社 B000JABMF8: 遠藤 周作: 沈黙 (1966年): 新潮社 4833480018: 遠藤 周作: 沈黙の声 (カミユ文庫): プレジデント社 439344406X: 遠藤 周作: 遠藤周作とShusaku Endo―アメリカ「沈黙と声」遠藤文学研究学会報告: 春秋社 4770010141: 遠藤 周作: 沈黙―Silence (Japan’s modern writers): 講談社インターナショナル 4860551796: 遠藤 周作: 沈黙〈2〉 (大活字文庫): 大活字 B000J8GXTK: 遠藤 周作: 沈黙 (1979年): 新潮社 4860551788: 遠藤 周作: 沈黙〈1〉 (大活字文庫): 大活字 486055180X: 遠藤 周作: 沈黙〈3〉 (大活字文庫): 大活字
1 Trackback(s)