アマゾン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)