Webhook解説:署名付きペイロードとリトライ

Backend2026-10-27TryQuickToolBox

決済プロバイダーのWebhookを統合して取引更新を受け取ったばかりだとします。テストではすべてうまくいきますが、本番環境ではトラフィックスパイク時にイベントが欠落したり、プロバイダーがリトライしたときに二重請求が発生したりすることに気づきます。Webhookは概念としてはシンプルですが、実際には扱いが難しいものです。ネットワーク境界を越え、遅延、重複、なりすましの可能性があります。この記事では、署名付きペイロードとスマートなリトライ戦略を使用して、堅牢なWebhookコンシューマーとプロデューサーを構築する方法を説明します。

Webhookとは?

Webhookは、イベントによってトリガーされるユーザー定義のHTTPコールバックです。ソースシステムで何かが起こると(例:新規注文)、指定したURLにHTTP POSTリクエストを送信します。ポーリングとは異なり、Webhookはほぼリアルタイムでデータをプッシュするため、レイテンシとサーバー負荷を削減できます。

ただし、Webhookには課題があります。リクエストが本当に期待される送信者からのものかを確認し、障害を適切に処理し、重複処理を避ける必要があります。

署名付きペイロードでWebhookを保護する

検証がないと、誰でも偽のリクエストをWebhookエンドポイントに送信できます。署名付きペイロードは、検証可能な暗号署名を含めることでこれを解決します。

HMAC署名の仕組み

送信者は、共有シークレットとリクエストボディを使用してハッシュベースのメッセージ認証コード(HMAC)を計算します。署名はヘッダー(例:X-Signature)で送信されます。受信側でHMACを再計算し、比較します。

// Node.jsの例:Webhook署名の検証
const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

タイミング攻撃を防ぐために、常にtimingSafeEqualのような定数時間比較関数を使用してください。

タイムスタンプを含める

リプレイ攻撃を防ぐために、署名付きペイロードにタイムスタンプを含め、数分(例:5分)より古いリクエストを拒否します。タイムスタンプは署名対象データの一部である必要があります。

信頼性の高いリトライの実装

ネットワークの問題や一時的なサーバーエラーにより、Webhookの配信が失敗する可能性があります。堅牢な送信者は、指数バックオフを使用して失敗した配信をリトライします。

リトライ戦略

例:Pythonでのバックオフ付きリトライ

import time
import requests
from requests.exceptions import RequestException

def send_webhook(url, payload, max_retries=5):
    for attempt in range(max_retries):
        try:
            response = requests.post(url, json=payload, timeout=5)
            if response.status_code < 500:
                return True  # 成功またはクライアントエラー(リトライしない)
        except RequestException:
            pass
        time.sleep(2 ** attempt)  # 指数バックオフ
    return False

Webhookコンシューマーのベストプラクティス

比較:Webhook vs ポーリング

側面Webhookポーリング
レイテンシほぼリアルタイム間隔に依存
サーバー負荷低い(プッシュのみ)高い(頻繁なリクエスト)
複雑さ高い(エンドポイント、セキュリティが必要)低い
信頼性リトライが必要本質的にリトライされる

FAQ

署名付きWebhookペイロードとは何ですか?

署名付きペイロードには、受信者がリクエストの真正性と整合性を検証できる暗号署名(通常はHMAC)が含まれています。

失敗したWebhookを何回リトライすべきですか?

一般的な方法は、指数バックオフで3〜5回のリトライですが、SLAとイベントの重要度によって異なります。

HTTPSなしでWebhookを使用できますか?

いいえ、ペイロードと署名の傍受を防ぐために常にHTTPSを使用してください。平文のHTTPは機密データを露出します。

Webhookペイロードをデバッグする際、JSONを素早く整形する必要があるかもしれません。JSONレスポンスを整形して検証するには、JSON Formatterをお試しください。