Amazon Product Advertising API (認証対応)

 

Amazon Product Advertising APIの認証の件(zorioの日記)に、 シグネチャを計算するコードが載っていたので、 これを参考にしつつ本物のキーを使用してリクエストを発行してみました。

内容は、1回のリクエストで10個の ISBN-13 を送信して、 それぞれの書名を取得するというものです。

ソースコード

amazon-sig.rb
#!/usr/bin/ruby -Ku
# -*- coding: utf-8 -*-

require 'date'
require 'openssl'
require 'base64'
require 'cgi'
require 'net/http'
require 'rexml/document'

AccessKey = 'abracadabraabracadab'                      # 要変更
SecretKey = 'hirakegomahirakegomahirakegomahirakegoma'  # 要変更

Host = 'webservices.amazon.co.jp'
Path = '/onca/xml'

ISBN13 =
  [
   '9784894712850', '9784822234300', '9784797336610', '9784873113944',
   '9784873113678', '9784839927844', '9784777512928', '9784797340044',
   '9784274066429', '9784873113562'
  ]

def make_req(items, access_key, secret_key)
  gmt = DateTime.now.new_offset.strftime('%Y-%m-%dT%XZ')
  par =
    [
     'Service=AWSECommerceService',
     'Version=2009-01-06',
     'AWSAccessKeyId=' + access_key,
     'ContentType='    + CGI.escape('text/xml'),
     'Operation=ItemLookup',
     'SearchIndex=Books',
     'ResponseGroup='  + CGI.escape('Medium,Reviews,EditorialReview'),
     'IdType=ISBN',
     'ItemId='         + CGI.escape(items.join(',')),
     'Timestamp='      + CGI.escape(gmt)
    ].sort.join('&')
  msg = [ 'GET', Host, Path, par ].join("\n")
  dig = OpenSSL::HMAC::digest(OpenSSL::Digest::SHA256.new, secret_key, msg)
  sig = CGI.escape(Base64.encode64(dig).chomp)
  "#{Path}?#{par}&Signature=#{sig}"
end

begin
  Net::HTTP.start(Host, 80) { |http|
    req = make_req(ISBN13, AccessKey, SecretKey)
    doc = REXML::Document.new(http.get(req).body)
    doc.elements.each('ItemLookupResponse/Items/Item/ItemAttributes') { |item|
      puts '%s -> %s' % [item.text('EAN'), item.text('Title')]
    }
  }
end

実行結果

$ openssl version             ← SHA256 はサポートされているか?
OpenSSL 0.9.8g 19 Oct 2007    ← Yes!(0.9.8 以上)
$ /usr/bin/ruby -v 
ruby 1.8.6 (2008-08-11 patchlevel 287) [i386-linux]
$ chmod +x amazon-sig.rb
$ ./amazon-sig.rb
9784894712850 -> Rubyによるデザイン・パターン
9784822234300 -> Ruby技術者認定試験 公式ガイド (ITpro BOOKs)
9784797336610 -> たのしいRuby 第2版 Rubyではじめる気軽なプログラミング
9784873113944 -> プログラミング言語 Ruby
9784873113678 -> 初めてのRuby
9784839927844 -> Rubyで作る奇妙なプログラミング言語 ~Esoteric Language~
9784777512928 -> Rubyではじめるゲームプログラミング―人気の国産言語で、誰でも簡単にゲームが作れる! (I・O BOOKS)
9784797340044 -> Rubyレシピブック 第2版 268の技
9784274066429 -> プログラミングRuby 第2版 言語編
9784873113562 -> Rubyスクリプティングテクニック ―テスト駆動による日常業務処理術

CORESERVERの場合

CORESERVER の場合は、次のように openssl が古いため、 SHA256 が使えません(おそらく、XREA+ も同様です)。

foo@bar:~> openssl version    ← SHA256 はサポートされているか?
OpenSSL 0.9.7m 23 Feb 2007    ← No!(0.9.8 以上が必要)

従って代替手段を考える必要があるのですが、 アマゾンのProduct Advertising APIにRubyでアクセス に書かれている通り ruby-openid が使えます。

ライブラリを openssl から ruby-openid に変更するには、 上掲のソースコードを2ヶ所変更します。

■ 変更(1)

require 'openssl'
        ↓
require 'rubygems'
require 'hmac/sha2'           # gem install ruby-openid

■ 変更(2)

  dig = OpenSSL::HMAC::digest(OpenSSL::Digest::SHA256.new, secret_key, msg)
        ↓
  dig = HMAC::SHA256.digest(secret_key, msg)

CORESERVER に ruby-openid をインストールする方法については、 RubyGems, scrAPI インストール手順 - XREA+版 を参考にしてみてください。

結局のところ、ローカルで動作確認した後、ソースコードに手を加えずにそのまま CORESERVER で動かす、 といった場合には ruby-openid(hmac/sha2) を使った方が良いかも知れません。

もう1つの代替案として、zorioの日記 に掲載れている 「ちなみにopensslが古くてSHA256が使えない場合は、HMACの所だけ自前で書けばOK」 を検討してみてください。 その場合、ruby-openid(hmac/sha2) が不要になります。

2009-07-20

更新履歴

日付 内容
2009-05-22 追加 セクション「CORESERVERの場合」を追加
2009-05-13 初版