Product Advertising API の SOAPリクエスト aws:Client.RequiresSSL エラーについて - 日報 #121
さて金曜日になりました。
RoomClipは曜日変動が微妙にあるサービスなのですが、
想像しやすい事象とはいえ、中々この曜日変動というのは不思議なものだと感じます。
1週間というループが仮に10日だったら、10日なりの変動周期になっていただろうと考えると、
それと7日ループとを比べてみたいものです。
相似形になるのでしょうかね。
さて、前回に引き続いて、
突発案件について少し。
直近でいうと、Amazon Product Advertising のAPI応答エラーについて。
早い話が、Amazon商品情報APIに対して何らかクエリを投げて、
検索結果一覧を得るというシステムが、ある日突然動かなくなりました。という事件です。
AmazonECS.class.phpというここで手に入る
ライブラリを使ってSOAP接続をして結果をパースしていたのですが、
ある日こんなエラーが吐出されるように。
Fatal error: Uncaught SoapFault exception: [aws:Client.RequiresSSL] SSL connection required for SOAP authentication
このエラー文で検索すればワンサカ出てきますが、
大体取りまとめるとこんな助言が得られます。
乱暴ですが、こんな感じです。まぁ結論「よく分からん!」という感じでした。
そもそもSOAPとはプロトコルの1つで、HTTPとかと同じようなジャンルのものです。
一般的に、ブラウザでページアクセスをする時というのは、
ブラウザソフトがサーバソフトに対して「決まった書式と段取り」に従ってリクエスト情報を投げたり、
レスポンスを受けたりするわけです。
この「決まった書式と段取り」のことをプロトコルと呼び、いまスタンダードなのはHTTPプロトコルなわけですね。
簡単に言うと。
SOAPはその「決まった書式や段取り」、プロトコルの1つです。
特にXMLでリクエスト文やレスポンスを受けるルールになっているため、
HTTPよりしっかりと構造化されているプロトコルで一時期は「凄いかも」と目されていたはずです。
今はどうか、、、知らないですけど、、、
とにかく、AmazonはそのSOAPで商品情報APIを取得することができるわけなんです。
その細かなやり取りを担ってくれるのがAmazonECS.class.phpだったはずなのですが、、、
上記のエラーなわけです。
最初からエラーだったらいいのですが、いきなりなるってことは気味が悪いですね。
で、色々なドキュメントを見ると、
驚くことにSOAPのエンドポイントがドキュメントごとで結構違います。
https://images-na.ssl-images-amazon.com/images/G/09/associates/paapi/dg/index.html?SOAPEndpoints.html
ここと、
http://docs.aws.amazon.com/ja_jp/AWSECommerceService/latest/DG/SOAPEndpoints.html
ここで、異なります。
なんだかこんがらがってきてよく分からんので、
この辺は目をつぶって「きっと何らかの仕様が変更されたんだろう」という予測のもと、
ライブラリの方をアップデートしてみました。
AmazonECS.class.phpはレガシーとなり、今はApaiというライブラリになっております。
ここがgithubリポジトリです。
かなりナウい構造になっているので、面くらいますが、大人しくcomposerでインストールします。
composerでインストールしたらautoload.phpをインクルードして、さっそく使ってみます。
が、
やはりSOAPでつなぐと同じエラーが!
もーーやだ!
SOAPなんて使わないぞ!
ということで、別の方法としてRESTを使います。
コードはこんな感じ。
<?php require_once(LIB_PATH.'/libraries/ApaiIO/vendor/autoload.php'); use ApaiIO\ApaiIO; use ApaiIO\Configuration\GenericConfiguration; use ApaiIO\Operations\Search; use ApaiIO\Operations\Lookup; $devId = "AMAZON_ACCESS_KEY"; // アマゾンキー $secret = "AMAZON_ACCESS_SECRET_KEY"; // シークレットキー $aflId = "AFIL_ID"; // アフィリエイトID $conf = new GenericConfiguration(); try { $conf ->setCountry('co.jp') // 日本 ->setAccessKey($devId) ->setSecretKey($secret) ->setAssociateTag($aflId) ->setResponseTransformer('\ApaiIO\ResponseTransformer\XmlToSimpleXmlObject'); // レスポンスをXmlObjectに変更するトランスフォーマークラス /* ApaiIO/vendor/exeu/apai-o/lib/ApaiIO/ResponseTransformer/ 配下にいっぱい変換クラスがありますので、 目的のを選ぶといいです */ } catch (\Exception $e) { echo $e->getMessage(); } $apaiIO = new ApaiIO($conf); // Keywordで検索 $search = new Search(); $search->setCategory('All'); $search->setKeywords($keyword); $search->setPage(1); $search->setResponseGroup(array('ItemAttributes', 'Offers', 'Images', 'EditorialReview')); $search_response = $apaiIO->runOperation($search); $search_response = json_decode(json_encode($response), TRUE); // ItemIDで検索 $lookup = new Lookup(); $lookup->setItemId($this->params['item_id']); $lookup->setResponseGroup(array('ItemAttributes','Offers','Images','EditorialReview')); $lookup_response = $apaiIO->runOperation($lookup); $lookup_response = json_decode(json_encode($response), TRUE); ?>
RESTはとても順調光速で機能しました。
ありがたいことです。
ちなみに、Xmlをそのままオブジェクトにするのがだるかったので、
$lookup_response = json_decode(json_encode($response), TRUE);
このように1回jsonにしてから引き戻してArray化するという手法をとっています。
Xmlの属性値が使えなくなりますが、、まぁ一応機能は果たしましたのでよしとします。
以上でした。
でも結局原因が分からず、非常に消化不良です。
どなたか何か情報ございましたら教えて頂けると嬉しいです。
それでは!