Shopify運用設計研究所 > Shopify Webhookの実装設計|外部連携を止めない受信基盤
2026年7月3日
•約14分で読めます
Shopify Webhookで注文、顧客、商品、在庫、GDPRイベントを外部DB、kintone、ERP、会計へ安全に同期するためのtopic選定、HMAC検証、raw body、重複排除、キュー、DLQ、監視、再同期ジョブ、復旧手順を整理します。
Shopify Webhookを受ければ、注文や在庫を外部DBやkintoneへリアルタイム同期できますか?
できます。ただし、Webhookは「イベント通知」です。受信したらすぐ外部システムを更新すればよい、という設計にすると、タイムアウト、再送、重複、欠損、順序ズレで運用が止まります。
Shopifyで受注や商品数が増えてくると、注文をWMSへ渡す、顧客更新をkintoneへ反映する、商品・在庫・返金をERPや会計へ送る、といった外部連携の起点としてWebhookを使いたくなります。方向性は正しいです。ただし、Webhookを「ShopifyからPOSTが来る便利な仕組み」とだけ捉えると危険です。
Shopify公式のWebhooks referenceでは、topic、購読方法、mandatory compliance topicsを確認できます。Verify webhook deliveriesでは、HMAC署名、raw body、X-Shopify-Webhook-Id、X-Shopify-Event-Id、200応答、タイムアウト、キュー処理、reconciliation job、再送仕様が説明されています。この記事では2026年7月3日時点で確認した内容を前提にしますが、実装時は必ず公式を再確認してください。
外部サービス側の実務ガイドとしては、HookdeckのShopify Webhooks over HTTPS guideも参考になります。即時ACK、永続キュー、DLQ相当の失敗管理、監視、手動リトライの観点を補えます。
Shopify Webhookの実装で最初に作るべきものは、受信用エンドポイントではなく、topic、重複排除、キュー、外部同期、再実行、欠損復旧を含む受信基盤の設計です。
ShopifyからPOSTを受けた瞬間に、kintone登録、ERP送信、会計明細作成、在庫DB更新まで終わらせる設計は避けます。どこか1つが遅いだけでShopify側のタイムアウトや再送を招き、外部側では処理済みなのに同じ注文がもう一度届くことがあります。
| 層 | 役割 | 設計で決めること |
|---|---|---|
| 受信エンドポイント | ShopifyからのHTTPS POSTを受ける | HMAC検証、raw body保持、topic/shop/header保存、即時200応答 |
| 受信ログ | 届いたWebhookを証跡として保存する | webhook ID、event ID、payload hash、受信時刻 |
| キュー | 外部同期を非同期化する | topic別優先度、再試行回数、処理中ロック、バックプレッシャー |
| ワーカー | 注文・顧客・商品・在庫の処理を実行する | 最新状態の再取得、外部DB、kintone、ERP/API更新 |
| 同期台帳 | Shopifyと外部システムの対応を持つ | Shopify ID、外部ID、処理状態、エラー、再実行キー |
| DLQ・再同期・監視 | 失敗や欠損を復旧する | 原因分類、担当者、reconciliation job、topic別アラート |
Webhookは、変化が起きたことを早く知るために向いています。一方で、過去分の全件同期、欠損確認、月次照合、複雑な検索にはAPI pollingやBulk処理が必要です。注文作成、顧客更新、商品・SKU変更はWebhookが向きますが、過去注文の会計投入やWebhook欠損確認は、GraphQL Admin API、Bulk Operations、reconciliation jobで補います。API連携全体の正本や同期イベントは、Shopify API連携の設計方法でも整理しています。
Shopify Webhookのtopicは、増やせば安心というものではありません。購読topicが多いほど受信量、重複、順序ズレ、監視対象が増えます。業務イベント、外部同期先、再取得方法を一緒に決めます。
| 領域 | topic候補 | 外部連携の例 | 設計上の注意 |
|---|---|---|---|
| 注文作成 | orders/create |
WMS出荷指示、kintone注文台帳、CRM購入履歴 | 支払未確定や不正疑いをすぐ出荷対象にしない |
| キャンセル・返金 | orders/cancelled、返金関連topic |
会計補正、CS確認、在庫復帰候補 | 自動で会計仕訳まで進めず、確認点を残す |
| 顧客 | customers/create、customers/update、customers/delete |
CRM、kintone顧客台帳、メール配信同意 | メールアドレスだけを一意キーにしない |
| 商品 | products/create、products/update、products/delete |
PIM、外部商品DB、ERP商品マスタ | 販売文言と社内管理属性を分ける |
| 在庫 | 在庫関連topic | WMS、発注候補、低在庫通知 | Shopify在庫が正本か、WMS在庫が正本かを決める |
| GDPR・compliance | 顧客データ要求、顧客削除、ショップ削除系topic | 個人情報削除、監査ログ、対応期限管理 | App Store配布アプリでは必須topicを公式で確認する |
orders/updatedは便利ですが、更新頻度が高くなりやすいtopicです。全イベントを外部DBに流すのではなく、「出荷指示を更新する」「ログだけ残す」「会計確認へ回す」を分けます。読み書き責任は、Shopify Admin API実装計画と合わせて整理します。
Shopify公式ドキュメントでは、X-Shopify-Hmac-SHA256とclient secret、raw request bodyを使ってHMAC-SHA256を検証すると説明されています。JSON parse後のオブジェクトや、整形し直した文字列で検証すると一致しないことがあります。
| 項目 | 実装方針 | 失敗すると起きること |
|---|---|---|
| raw body | body parserより前に取得し、HMAC検証に使う | 正しいShopify配送なのに署名不一致になる |
X-Shopify-Hmac-SHA256 |
base64のHMACとして検証する | 偽装リクエストや誤配送を処理してしまう |
| secret管理 | client secretを安全に保管し、ローテーション時の影響を確認する | secret更新直後に検証失敗が増える |
| 検証失敗 | 401/400系で拒否し、処理キューへ入れない | 不正payloadが同期台帳に混ざる |
実装では、HMAC検証前にpayloadを信用しない、raw bodyを失わない、外部DB更新はこの場でやらない、という流れを崩さないことが重要です。
ShopifyのHTTPS配送では、受信側が速く応答する必要があります。公式ドキュメントでは、200番台以外や3XXはエラー扱い、接続タイムアウトは1秒、リクエスト全体のタイムアウトは5秒と説明されています。応答なしやエラーの場合は次の4時間で8回再送し、Admin APIで作成したsubscriptionでは連続失敗後に自動削除される可能性があります。
| 設計項目 | 推奨方針 | 見るべきリスク |
|---|---|---|
| 即時ACK | HMAC検証、ID保存、キュー投入だけ行い、5秒以内に200を返す | 外部API処理でShopify応答が遅れる |
| topic別キュー | 注文、顧客、商品、在庫、complianceを分ける | 商品更新の大量イベントで注文処理が詰まる |
| リトライ | 一時障害は自動再試行、上限後はDLQへ送る | 外部API停止中に無限再試行する |
| ロック | 同じ注文や顧客への同時処理を避ける | 状態更新が前後して外部DBが戻る |
| rate limit | kintone、ERP、会計APIの上限に合わせる | 外部API側で429やタイムアウトが増える |
| payload保存 | raw body、headers、処理結果を分ける | 後から検証できない、個人情報を過剰保持する |
Shopify Webhookは5秒以内に業務処理を終わらせる仕組みではなく、5秒以内に安全に受け付け、後段で確実に処理する仕組みとして設計します。
Webhookは重複して届くことがあります。公式ドキュメントでは、X-Shopify-Webhook-Idを個別配送の重複排除に使い、同じmerchant action由来の配送の相関にはX-Shopify-Event-Idを使う、と説明されています。
| ID | 使い道 | 保存場所 | 注意点 |
|---|---|---|---|
X-Shopify-Webhook-Id |
1配送の重複排除 | webhook_deliveriesテーブルの一意キー | 同じtopic複数subscriptionでは別IDになる |
X-Shopify-Event-Id |
同じmerchant action由来の相関 | event_correlation_idとして保存 | 重複排除の主キーにするかは購読設計次第 |
| 外部ID | kintone record ID、ERP伝票ID、会計仕訳ID | external_syncsテーブル | 再実行時に新規作成ではなく更新に使う |
| idempotency key | 処理単位の一意キー | topic + shop + resource + actionなど | 外部APIに渡せる場合は渡す |
冪等性は、「同じWebhook IDを2回処理しない」だけでは足りません。WMS注文、kintone注文台帳、会計返金伝票、商品マスタ、在庫数が再実行で壊れない単位まで設計します。
Webhook処理は、すべて自動復旧できるわけではありません。SKU未登録、会計税区分不足、顧客重複、住所不備、権限スコープ不足のような業務エラーは人の判断が必要です。DLQは失敗イベントを捨てる場所ではなく、原因を見て、修正後に再実行する保留場所です。
| 失敗分類 | 自動リトライ | DLQ送りの条件 | 人の対応 |
|---|---|---|---|
| Shopify/外部APIの一時障害 | する | 上限回数を超えた | 復旧確認後に再実行 |
| SKU未登録 | しない | 外部商品マスタに存在しない | 商品マスタを登録して再実行 |
| 会計項目不足 | 原則しない | 税区分、勘定科目、手数料区分が未設定 | 会計ルールを補完して再実行 |
| schema変更 | しない | payload parseや必須fieldで失敗 | API version、topic、parserを修正 |
| テーブル | 主な項目 | 目的 |
|---|---|---|
| webhook_deliveries | webhook_id、event_id、shop、topic、received_at、hmac_status、payload_hash | 届いた配送の証跡と重複排除 |
| external_syncs | resource_type、shopify_id、external_system、external_id、sync_status | kintone、ERP、会計、WMSとの対応表 |
| dead_letter_events | delivery_id、failure_type、message、owner、resolution_status | 自動処理できないイベントの保留 |
| reconciliation_runs | target、from_at、to_at、found_count、missing_count、requeued_count | 欠損検知と再投入の履歴 |
この台帳があれば、「どの注文が届いたか」「kintoneには登録済みか」「ERP送信だけ失敗しているのか」「再実行してよいのか」を確認できます。
Webhookの受信基盤は、外部システムの正本設計とセットで考えます。Shopifyからイベントが来たからといって、すべての外部システムへ同じpayloadを送るわけではありません。
| 連携先 | 渡すデータ | 正本にしやすいもの | Webhook側でやること |
|---|---|---|---|
| 外部DB | Shopify ID、注文・顧客・商品スナップショット、処理状態 | 連携状態、分析用データ、再実行ログ | 受信payloadとAdmin API再取得結果を保存する |
| kintone | 注文台帳、顧客対応、例外処理、手動復旧タスク | 人が見る対応状況、補正メモ | 失敗・保留・要確認をレコード化する |
| ERP | 商品コード、受注、売上、在庫、出荷指示 | 社内商品マスタ、販売管理、在庫管理 | Shopify IDとERP IDの対応を保存する |
| 会計 | 売上、送料、割引、返金、税、手数料候補 | 仕訳、入金消込、月次締め | 自動連携範囲と経理確認範囲を分ける |
| WMS・在庫管理 | SKU、数量、配送先、出荷条件、在庫更新 | 引当、出荷実績、倉庫在庫 | 出荷対象条件と重複送信防止を持つ |
kintoneは全データ正本ではなく、例外処理や手動復旧の画面として使うと有効です。SKU未登録、会計項目不足、住所不備、ERP送信失敗を起票し、補正後に「再実行」へ戻す形にします。ERPや会計は二重登録の影響が大きいため、外部側の伝票IDや仕訳IDを保存し、再実行時は既存外部IDの状態確認から入ります。
Webhookは、本番に出してからしか試せない設計にすると危険です。ローカル開発、staging、本番で、同じ受信契約を検証できるようにします。
| 項目 | 設計方針 | 注意点 |
|---|---|---|
| local/dev testing | Shopify CLIやトンネル、保存済みpayloadで検証する | トンネルURL変更や相対URIの扱いを確認する |
| API version | subscription作成時のAPI versionを台帳化する | payload schema変更に備えてparserをversion別に持つ |
| topic棚卸し | 購読topic、スコープ、送信先URI、担当者を台帳化する | 使っていないtopicや重複subscriptionを止める |
| 監視 | 受信数、DLQ件数、キュー滞留、処理遅延を見る | HTTP 200だけでは業務成功を判断できない |
| reconciliation job | Shopify APIで対象期間を再取得し、未処理を検出する | Webhook欠損、長時間障害、subscription削除後の復旧に使う |
reconciliation jobは、Webhook運用の保険です。注文連携なら直近の注文をAdmin APIで取得し、未処理や外部同期未完了を再投入します。商品更新なら前日更新分の商品を取得し、外部DBの最終更新時刻と突合します。
GraphQL Admin APIでのquery/mutation設計は、Shopify GraphQL設計ガイドでも扱っています。Webhook後処理でも、payloadだけで判断せず、必要なfieldsをAdmin APIで取り直す設計が重要です。
Webhook連携は、作ったあとに監視を足すのでは遅いです。運用開始前に、何が起きたら誰が見るかを決めます。
| 監視項目 | 異常の見方 | 初動 |
|---|---|---|
| 受信数 | 急に0になる、または急増する | subscription、Shopify側障害、topic変更を確認 |
| 200応答失敗 | 3XX/4XX/5XXが増える | デプロイ、証明書、ルーティング、Keep-Aliveを確認 |
| キュー滞留 | job数や待ち時間が増える | 外部API停止、rate limit、ワーカー停止を確認 |
| DLQ件数 | topic別に増える | 原因分類を見て商品・会計・顧客マスタを補正 |
| reconciliation差分 | Webhook未処理が見つかる | 未処理イベントを再投入し、欠損原因を調査 |
| 障害 | 復旧手順 |
|---|---|
| 受信エンドポイント停止 | デプロイ、証明書、ルーティングを復旧し、Shopify側の再送状況とsubscription状態を確認する |
| subscription削除 | 再作成後、停止期間の対象データをreconciliation jobで取り直す |
| kintone項目変更 | mappingを修正し、DLQの対象だけ再実行する |
| 会計の二重登録疑い | external_syncsの外部IDと会計側伝票を突合し、新規作成を止める |
Shopify Webhookは、注文、顧客、商品、在庫、complianceイベントを外部システムへつなぐ強い起点です。ただし、本番で必要なのはWebhookの受け方だけではありません。topic選定、HMAC署名検証、raw body保持、X-Shopify-Webhook-Idによる重複排除、X-Shopify-Event-Idによる相関、1秒接続/5秒全体タイムアウトを前提にした即時ACK、8回/4時間の再送を踏まえたキュー、idempotency、DLQ、外部同期テーブル、監視、reconciliation job、手動復旧まで含めて設計する必要があります。
Webhookは、リアルタイムに見えるぶん、失敗が静かに積み上がります。kintone登録だけ止まる、会計連携だけ失敗する、再送でERPに二重登録されそうになる。こうした事故を避けるには、最初から「復旧できる受信基盤」として作ることが重要です。
Webhookは、受信エンドポイントだけではなく、失敗したあとに復旧できる仕組みまで作る必要があるんですね。
その通りです。HMAC検証、キュー、重複排除、外部ID対応、DLQ、再同期ジョブまで設計しておくと、外部連携を業務で使える状態にできます。
Bitlightでは、Shopify Webhookを単なるエンドポイント実装としてではなく、外部DB、kintone、ERP、会計、在庫管理をまたぐ連携基盤として設計します。topicの選び方、受信ログ、キュー、重複排除、外部ID対応、DLQ、監視、再同期ジョブ、復旧手順まで整理したうえで、EC運用を止めない形に落とし込みます。
千葉県出身。10歳の頃からプログラミングを始め、ゲーム、Webサイト、ロボット、スマホアプリなどを制作。大阪大学基礎工学部情報科学科で情報工学と統計学を学び、大学時代はAIを研究。大学在学中にWeb広告代理店でのインターンや人材系Webサービスの立ち上げを経験し、卒業後はフリーランスエンジニアとしてGISシステム、データ基盤構築、Webシステムの開発に従事。10年以上のWebアプリ開発・データ分析経験を基に、2023年9月に株式会社ビットライトを設立し、現場業務の仕組み化からデータ基盤構築、データ活用支援までを一気通貫で支援。