コンテンツにスキップ

Webhook 連携ガイド

Gift Card Hero は、特定のギフトカードイベントが発生すると、サーバーに HTTP POST リクエストを送信します。Webhook を使うと、外部システムをギフトカードの動きとリアルタイムに同期できます。


セットアップ

  1. 左側のナビゲーションで For developers に移動します
  2. Enable REST API にチェックを入れて保存します。Webhook の設定は、REST API が有効な間だけ表示されます
  3. Generate Secret をクリックして、Webhook の署名用シークレットを作成します

Webhook シークレットの作成

シークレットは一度しか表示されません

シークレットをコピーして、安全に保管してください。紛失した場合は Regenerate Secret をクリックして新しいシークレットを作成します。古いシークレットはすぐに無効になるため、サーバー側の設定も更新してください。

  1. 受け取りたい Webhook の種類ごとにエンドポイントの URL を入力し、保存バーの Save をクリックします

Webhook のエンドポイント URL

新規または変更したエンドポイント URL は https:// で始まり、インターネットから到達できるサーバーを指している必要があります。localhost、127.0.0.1、10.x.x.x、192.168.x.x などのプライベートネットワーク内のアドレスは、保存時に拒否されます。このルールより前に保存された URL は、変更するまで引き続き機能しますが、呼び出されるのは公開アドレスを指している場合だけです。ローカルのサーバーでテストするには、ngrok などのトンネルで公開し、発行された公開 https URL を使用してください。


イベントの種類

Gift Card Hero には 3 つの Webhook URL フィールドがあります:

イベント Topic ヘッダーの値 送信されるタイミング
Gift card order gift_card_order Gift Card Hero が注文のギフトカードを処理したとき。ペイロードには、その注文に属するカードが一覧で含まれます
Gift card payment gift_card_payment 全額または一部がギフトカードで支払われた注文が作成されたとき
Gift card balance change gift_card_balance 現在は送信されません

残高変更の Webhook

Gift card balance webhook URL フィールドは画面にありますが、Gift Card Hero はまだこのイベントを送信しません。現時点で残高の変化を追跡するには、GET /gift-cards/transactions をポーリングするか、支払いについては gift_card_payment イベントを使用してください。

Webhook は、Enable REST API が有効で、そのイベントの URL が入力されている場合にのみ送信されます。


配信

  • メソッド: POST
  • タイムアウト: 6 秒
  • 試行回数: 合計で最大 5 回 (初回と最大 4 回の再試行)。遅延は約 30 ~ 60 秒から始まり、徐々に長くなります
  • リダイレクト: 追従しません。3xx のレスポンスは配信失敗として扱われるため、エンドポイントの最終 URL を指定してください

エンドポイントが 6 秒以内に 2xx のレスポンスを返さない場合、配信は失敗とみなされ、再試行されます。


ヘッダー

すべての Webhook リクエストには、次のヘッダーが含まれます。

ヘッダー 値
Content-Type application/json
User-Agent GiftHero-Webhooks/1.0
X-GiftHero-Topic イベントの種類 (例: gift_card_order)
X-GiftHero-Signature 検証用の HMAC-SHA256 署名。Webhook シークレットを作成している場合にのみ送信されます

署名の検証

X-GiftHero-Signature ヘッダーには、16 進数でエンコードされ、sha256= が前に付いた HMAC-SHA256 署名が含まれます。

重要: 署名は、ペイロード本体の { type, timestamp } だけを含む JSON オブジェクトに対して計算されます。リクエスト本文全体ではありません。

検証の手順

  1. リクエスト本文を解析し、type と timestamp フィールドを取り出します
  2. 署名対象のペイロードを作成します: JSON.stringify({ type, timestamp })
  3. Webhook シークレットを鍵として HMAC-SHA256 を計算します
  4. 結果を 16 進数でエンコードし、sha256= を前に付けます
  5. 定数時間比較を使って、X-GiftHero-Signature ヘッダーと比較します

例 (Node.js)

const crypto = require('crypto');

function verifyWebhook(body, signature, secret) {
  const signingPayload = JSON.stringify({
    type: body.type,
    timestamp: body.timestamp
  });

  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(signingPayload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

ペイロードのスキーマ

すべてのリクエスト本文は同じ形式です。イベントの詳細は data の中に含まれます:

{
  "type": "gift_card_order",
  "timestamp": "2026-03-15T10:30:00.000Z",
  "data": { }
}

ギフトカード注文 (gift_card_order)

{
  "type": "gift_card_order",
  "timestamp": "2026-03-15T10:30:00.000Z",
  "data": {
    "order": {
      "id": 5551234567890,
      "name": "#1042",
      "email": "buyer@example.com",
      "createdAt": "2026-03-15T10:30:00.000Z",
      "lineItems": [
        {
          "id": 11198765432100,
          "title": "Gift Card",
          "quantity": 1,
          "sku": "GC-50",
          "variantId": 44556677
        }
      ]
    },
    "giftCards": [
      {
        "id": 987654321,
        "balance": "50.00",
        "currency": "USD",
        "lastCharacters": "ab12",
        "initialValue": "50.00",
        "customer": { "id": 123, "email": "buyer@example.com", "name": "Alex Buyer" },
        "recipient": { "id": 456, "email": "friend@example.com", "name": "Sam Friend" },
        "code": "abcd1234efgh5678",
        "lineItemId": 11198765432100,
        "sku": "GC-50"
      }
    ]
  }
}

ギフトカード支払い (gift_card_payment)

giftCards の各項目には、注文の支払いに使われた transaction も含まれます。

{
  "type": "gift_card_payment",
  "timestamp": "2026-03-16T14:22:00.000Z",
  "data": {
    "order": {
      "id": 5551234567891,
      "name": "#1043",
      "email": "shopper@example.com",
      "createdAt": "2026-03-16T14:22:00.000Z",
      "lineItems": [
        { "id": 11198765432200, "title": "Running Shoes", "quantity": 1, "sku": "SHOE-9" }
      ]
    },
    "giftCards": [
      {
        "id": 987654321,
        "balance": "0.00",
        "currency": "USD",
        "lastCharacters": "ab12",
        "initialValue": "50.00",
        "customer": null,
        "recipient": null,
        "transaction": {
          "id": "gid://shopify/OrderTransaction/123456789",
          "amount": "50.00",
          "currency": "USD",
          "type": "debit",
          "createdAt": "2026-03-16T14:22:00.000Z"
        }
      }
    ]
  }
}

フィールドの補足

  • data.order と data.giftCards が、連携の基礎として使うフィールドです。data の直下にも一部の注文フィールド (orderId、orderName、orderEmail、createdAt、lineItems) が含まれており、内部用のフィールド (storeId、shop、jobType) も含まれています。これらには依存しないでください。
  • balance は、注文時ではなく Webhook の作成時点におけるカードの残高です。
  • code はギフトカードコードの全体です。Gift Card Hero がそのコードを記録している場合にのみ含まれ、それ以外の場合は省略されます。パスワードと同様に扱い、エンドポイントが安全に保護されていることを確認してください。
  • lineItemId と sku は、カードを注文の明細行と対応付けできる場合に含まれます。
  • lineItems の各項目には id、title、quantity、sku、variantId が含まれます (価格は含まれません)。
  • カードの詳細を読み込めない場合、その項目は id、金額 0、空の lastCharacters だけに縮小されます。その場合は REST API でカードを再取得してください。

ベストプラクティス

  • 2xx をすばやく返す — Webhook を受け取ったらすぐに確認応答を返し、ペイロードの処理は非同期で行ってください。6 秒を超えるレスポンスは失敗として扱われます。
  • 重複を処理する — 再試行のため、同じイベントが複数回配信されることがあります。イベントデータの注文 ID とギフトカード ID を使って重複を排除してください。timestamp は各試行の時刻のため、安定したキーにはなりません。
  • HMAC 署名を検証する — ペイロードを処理する前に、必ず X-GiftHero-Signature ヘッダーを検証してください。署名が無効なリクエストは拒否してください。
  • 冪等性を確保する — 同じイベントを 2 回処理しても結果が同じになるよう、Webhook のハンドラーを冪等に設計してください。
  • 失敗を監視する — エンドポイントが継続的に失敗している場合、Gift Card Hero は合計 5 回の試行の後に再試行を停止します。サーバーのログとエンドポイントの状態を定期的に確認してください。