WordPressプラグイン Amazon Associates Link Builder 1.9.2 でタグ(トラッキングID)が異常なのと日本語が文字化けするのを直した

2019-03-07追記: 修正版を作ったのでこちらもどうぞ→ Amazon Associates Link Builder で商品リンクが表示されない不具合が直る気配がないので修正版を作った【WordPressプラグイン】 | けーのブログ

Amazonさん謹製のWordPressプラグイン「Amazon Associates Link Builder」で動作がおかしかったので調べて直したんだけど、どこに報告すべきかわからんかったのでメモっておく。というかissueでも上げようかと思ったら、WordPressのプラグインディレクトリのシステムが未だにSubversion使っててビビった。もう使い方忘れたし、バグレポート窓口も書いてなくてわからん。

タグ(トラッキングID)が異常になる件

文字列置換してるけど、そこが間違ってる。Amazon Associates Link Builderプラグインの目的からして、トラッキングIDが変わってしまったら致命的だと思うんだけど…

diff -urNZ amazon-associates-link-builder-1.9.2/rendering/xml_manipulator.php amazon-associates-link-builder/rendering/xml_manipulator.php
--- amazon-associates-link-builder-1.9.2/rendering/xml_manipulator.php  2019-02-08 15:58:32.000000000 +0000
+++ amazon-associates-link-builder/rendering/xml_manipulator.php        2019-02-18 08:16:59.851612155 +0000
@@ -199,7 +199,7 @@
         $response = preg_replace( "/linkCode(%3D|=)\w{1,3}/", "linkCode$1" . $link_code, $response );
 
         //replace store id
-        return preg_replace( "((tag=)[^&]+(&))", "$1" . $store_id . "$2", $response );
+        return preg_replace( "/tag=[^&]+&/", "tag=${store_id}&", $response );
     }

ちゃんとコードを追っていないので、そもそもここで何をしたいのかいまいち理解していないが、これで自分としては不都合ない感じになった。

日本語が文字化けする件

Amazon Associates Link Builder プラグインには、AmazonのProduct Advertising APIを使って商品情報を取得し、その結果をデータベースに保存してキャッシュする仕組みが備わっている。キャッシュは30分間有効で、同じ商品に対する問い合わせはこのキャッシュを利用するらしい。
Product Advertising API にはrate limitがあるので、適切にキャッシュするのは必要な仕組みだ(なんだけど、1.8では普通にエラーログを吐いてたのでキャッシュの仕組みが無かったのかも知れない…)。

で、キャッシュするのはいいけど、商品名などの日本語文字が文字化け(“?”になる)して困った。調べると、MySQL(MariaDB)でテーブルの文字エンコーディングが latin1 で作成されていたのが原因の模様。そこで、プラグインがテーブルを作成しているところを修正した。

diff -urNZ amazon-associates-link-builder-1.9.2/sql/sql_helper.php amazon-associates-link-builder/sql/sql_helper.php
--- amazon-associates-link-builder-1.9.2/sql/sql_helper.php     2019-02-08 15:58:32.000000000 +0000
+++ amazon-associates-link-builder/sql/sql_helper.php   2019-02-15 10:06:49.833054148 +0000
@@ -52,7 +52,7 @@
             $primary_key_param = ! empty( $primary_key ) ? ", PRIMARY KEY  $primary_key" : "";
 
             $parameters = $columns_param . $index_param . $primary_key_param;
-            $create_table_query = "CREATE TABLE {$this->table_name} ( $parameters )";
+            $create_table_query = "CREATE TABLE {$this->table_name} ( $parameters ) CHARACTER SET = utf8mb4";
 
             //To use dbDelta function
             require_once( ABSPATH . "/wp-admin/includes/upgrade.php" );

プラグインを無効化してから有効化すればテーブルを作成し直してくれるかなと思ったら、無効化しても DROP TABLE してくれないし、プラグイン設定画面でもテーブルを削除するボタンとかは無かった。うーん、めんどくせえと言いながら、プラグインを無効化し、手動で DROP TABLE wp_Aalb_Asin_Response;を実行、プラグインを有効化したら直った。

というわけで、この問題はMySQL(MariaDB)の設定によっては(デフォルトのエンコーディングがUTF-8なら)顕在化しないと思われる。

あとがき

誰かupstreamに報告しといて。

2019-03-05追記: PAAPI “You are submitting requests too quickly. Please retry your requests at a slower rate.” と WP-Cron

Amazon PAAPIのポリシーの更新により、売上が発生していないアカウントにおけるrate limitがきつくなっているのだが、少ないながらも30日以内の売上は一応発生しているのにAPIからエラーが返ってくる。どうやらキャッシュの仕組みがうまく動いていないようなので調査中。

とりあえずわかったこと:

  1. キャッシュ対象は商品情報のみと思いきや、商品情報に加えてHTMLレンダリング結果もキャッシュしているらしいので無用に複雑化している。
  2. 商品情報キャッシュはASIN単位ではなくAPIコール単位。APIのレスポンスがそのまま保存されるため、ASINが複数指定されているとそのグループ単位でキャッシュされる。保存先は専用のDBテーブル。
  3. HTMLレンダリング結果のキャッシュは、WordPressのTransients APIを使って保存している。ちなみにこれは wp_options テーブルに保存されているが、TTLどう管理してんのかと思ったら option_name (key) 列の値(文字列)にexpire timeの数字をsuffixとしてくっつけているらしい。雑wwwwwと思いつつ、さすがWordPressやな、となった。
  4. WP-Cronでキャッシュの更新ジョブがあるのだが、なんらかの理由で失敗すると、成功するまで数秒ごとにリトライするらしい。

なんかもうこのプラグイン捨てたほうがいい気もしてきた。

2019-03-07追記: 修正版を作った

冒頭にも書いたが、いくつかの問題を直したバージョンを作った→
Amazon Associates Link Builder で商品リンクが表示されない不具合が直る気配がないので修正版を作った【WordPressプラグイン】 | けーのブログ