アマゾンAPIの電子署名添付:日本語文字をURL-Encodeしておくことが必須

July 1, 2009 – 4:24 pm

1週間ほど前、「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. 1 Trackback(s)

  2. Oct 13, 2009: 電子署名添付のAmazon APIを用いた書籍検索ツール | Yama's Memorandum

Post a Comment