Webhook
shopify

Shopify の Webhook を試してみる

More than 1 year has passed since last update.

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 ストアにログインできること。

  1. Shopify の管理画面にログインし、画面左下の Settings をクリックする。
  2. Notifications メニュークリックする。
  3. 一番下までスクロールすると、Webhooks というセクションがある。
  4. Create webhook ボタンを押し、以下の情報を入力する。
    • Event : Webhook 送信タイミング。
    • Format : JSON or XML
    • URL : 送信先の URL
  5. 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 画面上に表示してくれるサービスです。このような外部リクエストの内容確認用のサービスなのです。

  1. RequestBinにアクセスします。
  2. private にチェックし、Create a RequestBin を押します。
  3. URL が発行されるので、この URL をコピーします。この画面はこのまま閉じずに置いておきます。リクエストが飛んできたらこの画面に内容が表示されるからです。
  4. Shopify の管理画面の Webhook の設定 (Settings > Notifications) に行き、URL にこの URL を設定します。
  5. 設定後、その設定の右の(ゴミ箱アイコンの左) send test notification をクリックします。これで、テストデータで RequestBin 宛にリクエストが送信されました。
  6. RequestBin の画面に戻り、画面をリフレッシュします。これでリクエストの内容を確認できたと思います。リクエストヘッダーやボディを確認してください。
  7. ストアの準備ができている場合は、Webhook のイベントに設定したタイミングで、実際にどんなデータが飛んで来るのか、確認してください。(例えば、購入完了のタイミングに設定しているのであれば、実際に購入完了をしてみてください。)

RequestBin は同じ URL で何回もリクエストを受けることができるので、送信したら画面をリフレッシュし、内容を確認してください。

ローカルで動作確認

上記までで、Shopify の Webhook を受けるエンドポイントを作成できる状態になったと思います。ここでは、必要な内容を実装し終わり、それが正常に動くのか、実際の Shopfiy の Webhook からのリクエストを受けて確認する方法を説明します。

そのサービスをインターネットに公開できていれば、ここで説明する内容は必要ありませんが、普通は先にローカルで確認したいかと思います。

実際に Shopify からの Webhook を受けるためには、サービスがインターネットに公開されていなくてはいけません。ここでは、ngrok というトンネルサービスを利用して、ローカルで立ち上げたサーバーを一時的に、インターネットからアクセスできるようにします。

ngrok の準備

  1. ngrok をダウンロード
  2. ダウンロードしたディレクトリに移動。
  3. OSX または、Linux の場合は、./ngrok http 4567 で起動。Windows の場合は、ngrok http 4567
  4. 起動すると、ngrok が立ち上がり、Forwarding ってとこに、外部からアクセス可能な URL が表示される。これが、Shopify 側に今回設定する URL となる。例: http://ac2a51a0.ngrok.io
  5. ブラウザで一旦、このアドレスにアクセスし、localhost の場合と同じ結果か確認する。

4567 というのは Sinatra のデフォルトポートなので、各自起動しているサーバーのポート番号に置き換えること

動作確認

ngrok が準備できたら、後は RequestBin のときと同じで、Shopify の管理画面の Webhook の設定の URL に ngrok で発行されている URL (https の方)を設定する。

後は、テスト送信で内容を動作を検証したり、実際にストアを動かして、正常にリクエストを処理できるか確認する。

備考

Shopify との連携という意味でいうと、Shopify アプリを作るという手段もある。それについては、Shopify 用のプライベートアプリを作ってみたで説明している。