2009年5月10日日曜日

Amazon Product Advertising APIの署名認証をPythonでやってみる

AmazonアソシエイトWebサービスの名称が新しくProduct Advertising APIに変わるみたいです。

それだけなら、ふぅんという話なのですが、合わせて署名認証のお知らせがありました。

Amazon アソシエイト Web サービスの名称変更および署名認証についてのお知らせ

署名認証というのは正直初めて耳にしましたが、要するに自分とamazonだけが知っているパスワード(Secret Key)を利用して他人が不正利用できないようにすること、と理解しました。
あぁ、そういえばAmazonWebサービスに登録した時にSecret Keyというのがあったなと思い出しました。


Product Advertising APIを利用しているWebアプリはいくつかあるので、とりあえずPythonで作ったものから手をつけることに。


import urllib, urllib2, hmac, hashlib, base64
from datetime import datetime

class ProductAdvertising:

def __init__(self, access_key_id, secret_key, associate_tag=None, version='2008-08-19'):
self.access_key_id = access_key_id
self.secret_key = secret_key
self.associate_tag = associate_tag
self.version = version
self.uri = 'webservices.amazon.co.jp'
self.end_point = '/onca/xml'

def item_lookup(self, asin, options={}):
options['Operation'] = 'ItemLookup'
options['ItemId'] = asin
return self.send_request(options)

def send_request(self, options):
options['Service'] = 'AWSECommerceService'
options['AWSAccessKeyId'] = self.access_key_id
options['Version'] = self.version

# Timestampをセットしないとエラーになる。
# タイムスタンプはGMT(≒UTC)
options['Timestamp'] = datetime.utcnow().isoformat()

if self.associate_tag:
options['AssociateTag'] = self.associate_tag

# パラメーターをソートしてURLエンコード
# (修正 2009/05/17) payload = urllib.urlencode(sorted(options.items()))
payload = ""
for v in sorted(options.items()):
payload += '&%s=%s' % (v[0], urllib.quote(str(v[1])))
payload = payload[1:]

# 署名用の文字列
strings = ['GET', self.uri, self.end_point, payload]

# 署名の作成
digest = hmac.new(self.secret_key, '\n'.join(strings), hashlib.sha256).digest()
signature = base64.b64encode(digest)

url = "http://%s%s?%s&Signature=%s" % (self.uri, self.end_point, payload, urllib.quote_plus(signature))
return urllib2.urlopen(url).read()


使い方はこんな感じ
pa = ProductAdvertising(access_key_id='your_access_key_id', secret_key='your_secret_key')
item = pa.item_lookup('ASIN')


基本的には Product Advertising API: Example REST Requests ←こちらの例を参考にすれば問題ないはず。


ちなみに自分のSecret KeyはAmazon Web ServicesのYour AccountのAccess Identifiersで確認することができます。

PHPでもやってみました
Amazon Product Advertising APIの署名認証をPHPでやってみる


2009/05/17 修正

URLエンコード部分を下記のようにやっていましたが
payload = urllib.urlencode(sorted(options.items()))

urllib.urlencodeは内部でquote_plus使用しているようです。
quote_plusは空白文字をプラス(+)に変換します。
hmacの文字列にプラスが含まれているとアマゾンから
The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.

という、署名が間違っているぞというエラーが返ってきますのでurllib.quoteでURLエンコードをおこなうように修正しました。

payload = ""
for v in sorted(options.items()):
payload += '&%s=%s' % (v[0], urllib.quote(str(v[1])))
payload = payload[1:]

2 コメント:

Keiya さんのコメント...

はじめまして!

Product Advertising APIで認証が必要になったと聞いて途方に暮れ、Googleで検索したところ、トップにでていたので、参考にさせていただきました。ちょうど、開発していたのが、Pythonのアプリケーションだったので、大変参考になりました。というか、Pythonだったことに大変驚きました。

ありがとうございました。

Youthhr さんのコメント...

コメントありがとうございます!

日本語でPythonを語ってくれるブログは少ないので大変ですよね。
お役に立ててなによりです。

読者