Shopify では、外部サービスと連携する仕組みの一環として、多くの Webhook イベントを用意している。カートに商品追加したとか、注文完了とか、支払い完了したとか。これを使って、Shopfiy だけではできない様々なことが行えるようになる。
ここでは、以下2点を紹介する。
- Shopify の Webhook の仕様
- Webhook リクエストをローカルのサービスで動作確認する方法
Shopify の Webhook について
Shopify がサポートしている Webhook タイミング
Shopify が提供している Wehook の一覧は、以下のページに書いてある。
https://help.shopify.com/api/reference/webhook
Shopify の Webhook の仕様
リクエストメソッド: POST
リクエストボディの形式: JSON か XML
タイムアウト: 5 秒
失敗時の繰り返しルール: 最初の失敗から、48時間で、19回繰り返す。(間隔についての記載はないので、不明)
レスポンス: Webhook を受けたら、200 を返す。
詳しくは、ドキュメントのここを参照。
ヘッダー
Shopify の Webhook へのリクエストヘッダーには以下の情報が含まれる。これは、サービス側でのリクエストの検証に使える。
-
X-Shopify-Topic : どの Webhook イベントか。例:
orders/create
-
X-Shopify-Hmac-Sha256 : Body を Hmac 化したもの。検証に使う。例:
XWmrwMey6OsLMeiZKwP4FppHH3cmAiiJJAweH5Jo4bM=
-
X-Shopify-Shop-Domain : どの Shopify ストアからのものか。例:
johns-apparel.myshopify.com
ボディ
ボディの内容は、Webhook の topic によって異なるので、各 Webhook の仕様を確認ください。
設定方法
Shopify の Webhook を利用する手順は以下の通り。
事前条件: Shopify ストアにログインできること。
- Shopify の管理画面にログインし、画面左下の Settings をクリックする。
- Notifications メニュークリックする。
- 一番下までスクロールすると、Webhooks というセクションがある。
-
Create webhook ボタンを押し、以下の情報を入力する。
- Event : Webhook 送信タイミング。
- Format : JSON or XML
- URL : 送信先の URL
- Save webhook をクリックする。
以上。これで、設定したタイミングになったときに、設定した宛先に POST リクエストが飛んで行く。
注: みての通り、Shopify の Webhook では設定で、API キーや認証情報は指定できない作りになっている。そのため、送られてきたリクエストが、本当に Shopify からのものか、途中で改竄されていないかは、サービス側で検証する必要がある。
次に、その検証方法を説明する。
Webhook リクエストの検証方法
Shopify ドキュメントにあるまんまを書く。ここでは、Ruby (というか Sinatra) を使った場合の例を示す。ドキュメントには、PHP の場合の例も載っている。
検証ロジック
検証は、リクエストヘッダーにある Shopify からの HAMC (X-Shopify-Hmac-SHA256
) とリクエストボディとシークレットキーを使って、算出した HMAC が同じ値になるかを比較する。
検証に使うデータ
- リクエストヘッダーにある
X-Shopify-Hmac-SHA256
- シークレットキー: シークレットキーは、Shopify 管理画面の Webhook の設定の一番下に以下のメッセージがあるので、そこにある文字列。
All your webhooks will be signed with dfdfdfadsfadf2332ad3da09un3krjfdjflsafadfoj32lfadfcfdauf2a1ca4 so you can verify their integrity.
コード
require 'rubygems'
require 'base64'
require 'openssl'
require 'sinatra'
# The Shopify app's shared secret, viewable from the Partner dashboard
SHARED_SECRET = 'my_shared_secret'
helpers do
# Compare the computed HMAC digest based on the shared secret and the request contents
# to the reported HMAC in the headers
def verify_webhook(data, hmac_header)
digest = OpenSSL::Digest::Digest.new('sha256')
calculated_hmac = Base64.encode64(OpenSSL::HMAC.digest(digest, SHARED_SECRET, data)).strip
ActiveSupport::SecurityUtils.secure_compare(calculated_hmac, hmac_header)
end
end
# Respond to HTTP POST requests sent to this web service
post '/' do
request.body.rewind
data = request.body.read
verified = verify_webhook(data, env["HTTP_X_SHOPIFY_HMAC_SHA256"])
# Output 'true' or 'false'
puts "Webhook verified: #{verified}"
end
※: my_shared_secret
は上記に書いたシークレットキーで置き換える
Webhook リクエストの内容の確認
上記までで、リクエストを検証できる段階になったかと思います。ただ、実際にどんなデータが飛んで来るのか、事前に確認したいかと思います。ここではそれを確認します。
確認するためのツールとして、RequestBinという外部サービスを利用します。これは一時的に有効は URL を発行していくれて、そこで受けたリクエストを Web 画面上に表示してくれるサービスです。このような外部リクエストの内容確認用のサービスなのです。
- RequestBinにアクセスします。
-
private
にチェックし、Create a RequestBin
を押します。 - URL が発行されるので、この URL をコピーします。この画面はこのまま閉じずに置いておきます。リクエストが飛んできたらこの画面に内容が表示されるからです。
- Shopify の管理画面の Webhook の設定 (Settings > Notifications) に行き、URL にこの URL を設定します。
- 設定後、その設定の右の(ゴミ箱アイコンの左)
send test notification
をクリックします。これで、テストデータで RequestBin 宛にリクエストが送信されました。 - RequestBin の画面に戻り、画面をリフレッシュします。これでリクエストの内容を確認できたと思います。リクエストヘッダーやボディを確認してください。
- ストアの準備ができている場合は、Webhook のイベントに設定したタイミングで、実際にどんなデータが飛んで来るのか、確認してください。(例えば、購入完了のタイミングに設定しているのであれば、実際に購入完了をしてみてください。)
RequestBin は同じ URL で何回もリクエストを受けることができるので、送信したら画面をリフレッシュし、内容を確認してください。
ローカルで動作確認
上記までで、Shopify の Webhook を受けるエンドポイントを作成できる状態になったと思います。ここでは、必要な内容を実装し終わり、それが正常に動くのか、実際の Shopfiy の Webhook からのリクエストを受けて確認する方法を説明します。
そのサービスをインターネットに公開できていれば、ここで説明する内容は必要ありませんが、普通は先にローカルで確認したいかと思います。
実際に Shopify からの Webhook を受けるためには、サービスがインターネットに公開されていなくてはいけません。ここでは、ngrok というトンネルサービスを利用して、ローカルで立ち上げたサーバーを一時的に、インターネットからアクセスできるようにします。
ngrok の準備
- ngrok をダウンロード
- ダウンロードしたディレクトリに移動。
- OSX または、Linux の場合は、
./ngrok http 4567
で起動。Windows の場合は、ngrok http 4567
。 - 起動すると、ngrok が立ち上がり、
Forwarding
ってとこに、外部からアクセス可能な URL が表示される。これが、Shopify 側に今回設定する URL となる。例: http://ac2a51a0.ngrok.io - ブラウザで一旦、このアドレスにアクセスし、localhost の場合と同じ結果か確認する。
※ 4567
というのは Sinatra のデフォルトポートなので、各自起動しているサーバーのポート番号に置き換えること
動作確認
ngrok
が準備できたら、後は RequestBin のときと同じで、Shopify の管理画面の Webhook の設定の URL に ngrok で発行されている URL (https の方)を設定する。
後は、テスト送信で内容を動作を検証したり、実際にストアを動かして、正常にリクエストを処理できるか確認する。
備考
Shopify との連携という意味でいうと、Shopify アプリを作るという手段もある。それについては、Shopify 用のプライベートアプリを作ってみたで説明している。