> ## 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.