LogoWisora

リファレンス
  1. Home
  2. リファレンス
  3. Webhook を利用する
  4. Webhook でイベントを通知する

Webhook でイベントを通知する

ハンドオーバーなどのイベントを外部システムへ通知する Webhook の設定方法を説明します。

担当者の対応が必要になったことを、外部システムへ Webhook で通知できます。Webhook は、選択中のボットごとに設定します。

Webhook を設定する

  1. 管理コンソールにログイン して、管理コンソールで操作するボットを切り替える の手順で、設定するボットを選択します。

  2. 選択中のボットカードの [] [Webhook 設定] を順にクリックします。

    Webhook 設定画面が表示されます。

  3. 以下の項目を設定します。

    項目説明
    [Webhook を有効にする] チェックを入れると、選択したイベントが発生したときに Webhook を送信します。
    [シークレット] Webhook の署名に使用する値です。 [コピー] をクリックすると、シークレットをコピーできます。新しい値へ変更する場合は [生成] をクリックします。変更した場合は、Webhook を受信する外部システムにも新しい値を設定してください。
    [通知するイベント]

    通知するイベントを選択します。

    • [ハンドオーバーリクエスト] : エンドユーザーが担当者への対応を依頼したときに発生します。
    • [返信待ち] : 担当者が公開コメントを送信したあとに、エンドユーザーから新しいメッセージが届いたときに発生します。
    [送信先 URL] https:// から始まる外部システムの URL を入力します。明示的にポートを指定する場合は、443 だけを利用できます。
  4. [保存] をクリックします。

Webhook で送信される内容

選択したイベントが発生すると、 [送信先 URL] へ HTTPS の POST リクエストが送信されます。リクエストボディは JSON 形式です。以下は、送信される JSON の例です。

{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "eventName": "AWAITING_HUMAN_REPLY",
  "timestamp": "2026-08-25T03:00:17.232Z",
  "data": {
    "conversationId": "cv-example",
    "url": "https://example.wisora.example/ui/chat-logs/cv-example",
    "botId": "Additional-8f3c2a71",
    "botName": "サンプルボット"
  }
}

各プロパティの意味は以下のとおりです。

プロパティ説明
idイベントを識別する ID です。
eventName

イベントの種類です。

  • HUMAN_REQUEST: エンドユーザーが担当者への対応を依頼したイベントです。
  • AWAITING_HUMAN_REPLY: 担当者が公開コメントを送信したあとに、エンドユーザーから新しいメッセージが届いたイベントです。
timestampイベントが発生した日時です。ISO 8601 形式の UTC で送信されます。
dataイベントの詳細です。
data.conversationIdイベントが発生したチャットの会話 ID です。
data.urlイベントが発生した会話を表示するチャットログ画面の URL です。
data.botIdイベントが発生したボットの ID です。含まれない場合があります。
data.botNameイベントが発生したボットの名前です。含まれない場合があります。
data.externalUserId外部認証でチャットしたエンドユーザーの ID です。外部認証を利用していない場合は含まれません。

同じ id のイベントが複数回送信される場合があります。外部システムでは、処理済みの id を記録し、同じイベントを重複して処理しないようにしてください。

署名を検証する

Wisora は、 [シークレット] を鍵として、リクエストボディから HMAC-SHA256 の署名を計算します。計算した署名を Base64 形式に変換し、x-wisora-signature ヘッダーに設定します。

  1. JSON として解析する前のリクエストボディを、UTF-8 のバイト列として取得します。

  2. [シークレット] の UTF-8 バイト列を鍵にして、リクエストボディの HMAC-SHA256 を計算します。

  3. 計算結果を Base64 形式へ変換します。

  4. 変換した値と x-wisora-signature ヘッダーの値を、処理時間が値に左右されない方法で比較します。

  5. 値が一致した場合だけ、リクエストボディを処理します。

リクエストボディを変更しないでください

署名を検証するときは、受信したリクエストボディを整形したり、JSON として解析した内容を再生成したりせず、受信したバイト列をそのまま使用してください。空白、改行、プロパティの順序が変わると署名は一致しません。JSON として解析するのは、署名を検証したあとにしてください。

Node.js で署名を検証する

Node.js では、標準モジュールの node:crypto を使って署名を検証できます。

  1. 以下のコードを webhook-verification.js として保存します。

    import { createHmac, timingSafeEqual } from "node:crypto";
    import { readFile } from "node:fs/promises";
    import { pathToFileURL } from "node:url";
    
    export function createWisoraSignature(rawBody, secret) {
      if (!Buffer.isBuffer(rawBody) || typeof secret !== "string") {
        return null;
      }
    
      return createHmac("sha256", Buffer.from(secret, "utf8"))
        .update(rawBody)
        .digest("base64");
    }
    
    export function verifyWisoraSignature(rawBody, signature, secret) {
      const expectedSignature = createWisoraSignature(rawBody, secret);
      if (expectedSignature === null || typeof signature !== "string") {
        return false;
      }
    
      const expectedSignatureBytes = Buffer.from(expectedSignature, "base64");
    
      let actualSignature;
      try {
        actualSignature = Buffer.from(signature, "base64");
      } catch {
        return false;
      }
    
      return (
        actualSignature.length === expectedSignatureBytes.length &&
        timingSafeEqual(actualSignature, expectedSignatureBytes)
      );
    }
    
    async function main() {
      const [bodyPath] = process.argv.slice(2);
      const signature = process.env.WISORA_WEBHOOK_SIGNATURE;
      const secret = process.env.WISORA_WEBHOOK_SECRET;
    
      if (!bodyPath || !secret) {
        console.error(
          "WISORA_WEBHOOK_SECRET を設定し、JSON ファイルを指定してください。",
        );
        process.exitCode = 2;
        return;
      }
    
      const rawBody = await readFile(bodyPath);
      if (!signature) {
        console.log(createWisoraSignature(rawBody, secret));
        return;
      }
    
      const verified = verifyWisoraSignature(rawBody, signature, secret);
    
      if (!verified) {
        console.error("署名が一致しません。");
        process.exitCode = 1;
        return;
      }
    
      console.log("署名が一致しました。");
    }
    
    if (
      process.argv[1] &&
      import.meta.url === pathToFileURL(process.argv[1]).href
    ) {
      await main();
    }
    webhook-verification.js をダウンロード
  2. 以下のリクエストボディを、末尾に改行を付けずに webhook-body.json として保存します。

    「Webhook で送信される内容」の JSON は読みやすいように整形しています。この例では、同じ内容を 1 行にしたリクエストボディを使用します。

    {"id":"123e4567-e89b-12d3-a456-426614174000","eventName":"AWAITING_HUMAN_REPLY","timestamp":"2026-08-25T03:00:17.232Z","data":{"conversationId":"cv-example","url":"https://example.wisora.example/ui/chat-logs/cv-example","botId":"Additional-8f3c2a71","botName":"サンプルボット"}}
    webhook-body.json をダウンロード
  3. 説明用のシークレットを指定して、署名を生成します。

    WISORA_WEBHOOK_SECRET='00000000-0000-4000-8000-000000000000' \
    node webhook-verification.js webhook-body.json

    署名が生成されます。

    Ac23s8CC0vUCk7oBL1qLXwFh3LTZPPu116XknBwti2s=

    この署名と、x-wisora-signature ヘッダーの値を比較してください。一致した場合は、Webhook が Wisora から送信されたことを表します。

署名が一致しないリクエストは処理しないでください。