> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hitheo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# WhatsApp 集成

> 使用 @hitheo/whatsapp 適配器將 Theo 連接到 WhatsApp。

`@hitheo/whatsapp` 軟件包將 Theo 連接到 WhatsApp Cloud API。客戶向你的 WhatsApp 號碼發送消息後，適配器會將每條消息轉發到 `POST /api/v1/completions`，再通過 Cloud API 回覆。

<Note>
  Theo 不會託管你的 WhatsApp 號碼或令牌。你在 Meta Business Suite 中擁有 WhatsApp Business 賬戶、持有訪問令牌，並在**你自己的**基礎設施上部署此適配器；Theo 只處理適配器轉發過來的補全流量。你的客戶是在與你的品牌對話，而不是我們的。
</Note>

## 前置條件

1. 一個 WhatsApp Business API 賬戶（通過 Meta Business Suite）
2. 一個 Theo API 密鑰（`theo_sk_...`）
3. 一個用於接收傳入消息的 Webhook URL
4. Meta App Secret（用於驗證 Webhook 簽名）

## 安裝

<CodeGroup>
  ```bash npm theme={null}
  npm install @hitheo/whatsapp
  ```

  ```bash yarn theme={null}
  yarn add @hitheo/whatsapp
  ```

  ```bash pnpm theme={null}
  pnpm add @hitheo/whatsapp
  ```
</CodeGroup>

## 快速設置

該軟件包導出三個函數：

* `createWhatsAppHandler(config)` — 返回一個用於處理 WhatsApp Webhook 負載的異步函數。
* `verifyWebhook(params)` — 在 Webhook 註冊期間校驗 Meta 的 GET 挑戰請求。
* `verifySignature(rawBody, headerSig, appSecret)` — 對入站 POST 請求進行 HMAC-SHA256 簽名校驗。你必須傳入**原始**請求正文（字節），而不是重新解析後的 JSON 對象。

```typescript theme={null}
import express from "express";
import {
  createWhatsAppHandler,
  verifyWebhook,
  verifySignature,
} from "@hitheo/whatsapp";

const app = express();

const handle = createWhatsAppHandler({
  theoApiKey: process.env.THEO_API_KEY!,
  whatsappToken: process.env.WHATSAPP_TOKEN!,
  phoneNumberId: process.env.WHATSAPP_PHONE_ID!,
  appSecret: process.env.WHATSAPP_APP_SECRET!,
  mode: "auto",
  skills: ["customer-support"],
});

// GET webhook verification
app.get("/webhook", (req, res) => {
  const challenge = verifyWebhook({
    mode: req.query["hub.mode"] as string,
    token: req.query["hub.verify_token"] as string,
    challenge: req.query["hub.challenge"] as string,
    verifyToken: process.env.WHATSAPP_VERIFY_TOKEN!,
  });
  if (challenge) return res.send(challenge);
  res.sendStatus(403);
});

// POST webhook — signature-verified, then handed off to the adapter
app.post(
  "/webhook",
  express.raw({ type: "application/json" }),
  async (req, res) => {
    const ok = verifySignature(
      req.body, // Buffer because of express.raw
      req.header("x-hub-signature-256"),
      process.env.WHATSAPP_APP_SECRET!,
    );
    if (!ok) return res.sendStatus(401);

    const payload = JSON.parse(req.body.toString("utf8"));
    await handle(payload);
    res.sendStatus(200);
  },
);

app.listen(3000, () => console.log("WhatsApp bot listening on :3000"));
```

## 工作原理

1. 客戶發送一條 WhatsApp 消息
2. Meta 通過帶有 `X-Hub-Signature-256` 請求頭的 POST 請求發送 Webhook 負載
3. 你的 HTTP 層通過 `verifySignature` 校驗簽名
4. 適配器遍歷消息，將文本和媒體轉發給 Theo（附帶按發送者區分的 `conversation_id`），並將 Theo 的響應通過 Cloud API 發回
5. 狀態事件（`delivered`、`read`）會被靜默確認——不會產生重複回覆

## 處理器配置

| 選項 | 類型 | 是否必填 | 說明 |
| - | - | - | - |
| `theoApiKey` | `string` | ✅ | 你的 `theo_sk_...` API 密鑰 |
| `whatsappToken` | `string` | ✅ | WhatsApp Cloud API 訪問令牌 |
| `phoneNumberId` | `string` | ✅ | 你的 WhatsApp 電話號碼 ID |
| `appSecret` | `string` | | Meta App Secret。將其存放在你的環境變量中並傳給 `verifySignature`；適配器本身不會讀取網絡流量。 |
| `theoBaseUrl` | `string` | | API 基礎 URL（默認：`https://www.hitheo.ai`） |
| `mode` | `ChatMode` | | 默認模式 |
| `persona` | `PersonaInput` | | 自定義角色，或 `"theo"` / `"none"` |
| `skills` | `string[]` | | 在每條消息上激活的技能 slug |
| `conversationStore` | `ConversationStore` | | 將發送者號碼映射到 Theo 的會話 ID。默認使用進程內的 `Map`。 |
| `enableVoice` | `boolean` | | 使用 Theo 語音轉文本轉寫語音/音頻，並將轉寫內容追加到提示詞中。默認關閉（語音轉文本會產生額外費用）。 |
| `maxChunkChars` | `number` | | 每條出站消息的最大字符數。默認 4000。 |

## 附件

圖片消息（以及 `image/*` 類型的文檔）會在適配器內部下載，並以**base64 圖片數據**的形式轉發給 Theo。適配器會向 Graph API 出示 Meta 訪問令牌以獲取字節數據，但絕不會將帶令牌的 Graph CDN URL 繼續向外傳遞——因此不會有憑據流出你的部署環境。圖片說明文字會作為提示詞文本。

語音和音頻消息默認會被忽略，除非你設置 `enableVoice: true`。啓用後，適配器會下載該音頻片段，使用 Theo 語音轉文本進行轉寫，並將轉寫內容以文本形式追加到提示詞中。

## 跨實例的會話持久化

默認的 `ConversationStore` 是進程內存儲。對於無服務器或多實例部署，請接入 Redis 或你自己的數據庫：

```typescript theme={null}
import Redis from "ioredis";

const redis = new Redis(process.env.REDIS_URL!);

const handle = createWhatsAppHandler({
  theoApiKey: process.env.THEO_API_KEY!,
  whatsappToken: process.env.WHATSAPP_TOKEN!,
  phoneNumberId: process.env.WHATSAPP_PHONE_ID!,
  conversationStore: {
    get: (from) => redis.get(`wa:conv:${from}`),
    set: async (from, id) => {
      await redis.set(`wa:conv:${from}`, id, "EX", 60 * 60 * 24 * 30);
    },
    clear: async (from) => {
      await redis.del(`wa:conv:${from}`);
    },
  },
});
```

<Tip>
  在開發階段使用 `theo_sk_test_` 密鑰，以避免產生計費。
</Tip>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.