1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Rubyで Amazon SP-API の初歩レベルの認証を突破するためのメモ

Last updated at Posted at 2023-06-09

Amazonが SP-APIを発表しましたが、連日以下のようなエラーに悩まされていませんか? 自分も同じような壁に悩まされたのでメモします。

{
    "errors": [
        {
            "message": "Access to requested resource is denied.",
            "code": "Unauthorized",
            "details": ""
        }
    ]
}

最初は以下のライブラリを試したのですが、どれを使っても認証エラーなので自分で書くことにしました。

アカウントを作成し、postmanで動作確認

神のようなドキュメントがあるので、以下の手順で環境を作ります。

postmanを使った、スクラッチパッドでの動作確認は必須です。時間をドブに捨てないためにも、必ずpostmanで動作確認しましょう。

postman でアクセストークンを取得しているところ

「アクセストークンを取得」がダメなら何をやってもダメです。
時間をドブに捨てないために、postmanでアクセストークンが取得できることを検証しましょう。

gettoken.png

トークンを元に、ASINから商品名を得るところ

authz.png

kojien.png

HTTPの何処に、何を入れるのか?

エラーになった場合、入れる場所が3か所あるので、そこを間違っておりませんか?

この場所に これを入れる
params
(別名 QUERY_STRING)
GETなAPIでつかうやつ
HTTP request header x-amz-access-token: Atzr●●●●●●
Content-Type : application/json
body (別名 POST DATA) これはJSON textになっている必要がある

あのパラメータはどこにあるの?

refresh_token は、Amazonデベロッパーセントラルにあります。
Clipboard01.jpg

client_id / client_secret は、デベロッパーセントラルで、各アプリの「LWA認証情報を表示」ボタンから見れます。
cb2.jpg

aws_access_key_id / aws_secret_access_key は、AWS IAMから参照します。
iam.jpg

Rubyでsp-apiを叩いてみる

ASINを指定すると、商品のタイトルを取得する初歩のAPIで実験してみます。

ヘッダに認証サインする箇所がものすごく面倒なので、公式のAWS SDKを使っています。

gem install aws-sigv4

require "aws-sigv4"
require "json"

require "faraday"
require "faraday_json"

#認証データ
CREDENTIALS = {
    # 以下の情報はデベロッパーセントラルから取得します
    refresh_token: "Atzr|IwE●●●●●●●●●●●●●●●●●●●●●●●●●●●●●Wo",
    client_id: "amzn1●●●●●●●●●●●●●●●●●●●●●●●●●●●●●c1",
    client_secret:  "amzn1.●●●●●●●●●●●●●●●●●●●●●●●●●●●●●3b",

    # 以下の情報はIAM画面から取得します
    aws_access_key_id:  "AKI●●●●●●●●●●●●●●●●●●●●●●●●●●●●●73",
    aws_secret_access_key: "0EOE●●●●●●●●●●●●●●●●●●●●●●●●●●●●●Ii",
}


##---------------
# 認証トークンを設定する
def login_with_amazon(cred)
	data = {
		:grant_type => "refresh_token", 
		:refresh_token => cred[ :refresh_token ],
		:client_id => cred[ :client_id ], 
		:client_secret => cred[ :client_secret ] }


	conn = Faraday.new("https://api.amazon.com")
	conn.response :json
	res =  conn.post("/auth/o2/token", data).body

	return res["access_token"]
end

#
# ASINを指定すると商品のタイトルを得る Catalog Items API v2020-12-01 
#  @see https://developer-docs.amazon.com/sp-api/docs/catalog-items-api-v2020-12-01-reference
#
def catalogitem(cred, token, asin)
	signer = Aws::Sigv4::Signer.new(
		service: 'execute-api',
		region: 'us-west-2',
		access_key_id: cred[:aws_access_key_id],
		secret_access_key: cred[:aws_secret_access_key]
	)
	url = "https://sellingpartnerapi-fe.amazon.com/catalog/2020-12-01/items/#{asin}?marketplaceIds=A1VC38T7YXB528"


	signature = signer.sign_request(
		http_method: 'GET',
		url: url,
		headers: {
			"host" => "sellingpartnerapi-fe.amazon.com",
			'User-Agent' => 'ruby/sp-api',
			"x-amz-access-token" => token,
			"x-amz-date" => Time.now.getutc.xmlschema.tr('-:',"")
		},
	  )

	pp sig_headers = signature.headers
	sig_headers["x-amz-access-token"] = token

	conn = Faraday.new()
	conn.headers = sig_headers
	res = conn.get(url).body

	return JSON.parse(res)

end

token = login_with_amazon(CREDENTIALS)

pp catalogitem(CREDENTIALS, token, "4000801317")		# 4000801317 は広辞苑のASIN

この例では広辞苑のASINを指定していて、以下のような結果が取得できます

{"asin"=>"4000801317", "summaries"=>[{"marketplaceId"=>"A1VC38T7YXB528", "browseNode"=>"500272", "itemName"=>"広辞苑 第七版(普通版)", "manufacturer"=>"岩波書店"}]}

おしまい。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?