OpenClaw Zalo 频道插件接入指南:Bot API 配置、Webhook 模式与群组访问控制

原创2026-10-15 23:47:411,717 阅读
文章标签:人工智能大模型AI 应用后端LLM 网关即时通讯AI Agent插件系统本地部署MCP Clients

OpenClaw Zalo 频道插件接入指南:Bot API 配置、Webhook 模式与群组访问控制

Zalo 是越南市场主流的即时通讯平台,OpenClaw 通过 @openclaw/zalo 插件接入其 Bot API,让 Gateway 可以运行 Zalo 机器人,处理 1:1 私聊与群聊消息。本文基于 zalo/README.md 与仓库源码,系统讲解插件的安装、令牌配置、Webhook 模式、DM/群组访问控制、能力边界与常见排障,读完即可完成从零到可用的 Zalo 频道接入,并理解其底层运行机制。

插件定位与前置要求

Zalo 频道以插件形式提供,不随 OpenClaw 核心安装包内置。插件通过 OpenClaw 的 Channel Plugin SDK 注册,入口文件为 zalo/index.ts,其核心声明(id: "zalo"、别名 zl、能力列表等)定义在 zalo/src/channel.ts。接入前你需要:

  • 一个可用的 OpenClaw Gateway 环境;
  • 在 Zalo Bot Platform(https://bot.zaloplatforms.com)创建 Bot 并取得 bot token(形如 12345689:abc-xyz);
  • 决定消息接收方式:默认长轮询(long-polling),无需公网地址;若使用 Webhook 模式则需一个 HTTPS 公网地址。

从源码结构看,Zalo 在 OpenClaw 中的定位是"确定性路由"频道:回复始终回到同一 Zalo 会话,模型不会自行选择发往哪个渠道,适合做客服、通知等需要固定回路的场景。

插件安装

方式一:本地源码目录安装

在仓库源码检出的环境中执行:

openclaw plugins install ./extensions/zalo

方式二:npm 安装

openclaw plugins install @openclaw/zalo

方式三:Onboarding 引导安装

在 OpenClaw 的初始化引导(onboarding)流程中选择 Zalo,并确认安装提示,插件会被自动拉取。插件包元数据位于 zalo/package.json,其中声明了 openclaw.extensions、setupEntry 与频道注册信息;zalo/openclaw.plugin.json 声明了 channels: ["zalo"] 的频道归属。

基础配置与令牌解析

最小配置

在 OpenClaw 配置文件中加入以下片段(JSON5 格式):

{
  channels: {
    zalo: {
      enabled: true,
      botToken: "12345689:abc-xyz",
      dmPolicy: "pairing",
      proxy: "http://proxy.local:8080",
    },
  },
}

字段说明:

配置项 说明 默认值
enabled 是否启动该频道 true
botToken Zalo Bot Platform 签发的 bot token 无
dmPolicy 私聊访问策略:pairing | allowlist | open | disabled pairing
proxy 走代理访问 Zalo API(如 http://proxy.local:8080) 无

令牌的四种来源与解析优先级

Zalo 插件对令牌的解析集中在 zalo/src/token.ts,优先级依次为:

  1. 账户级配置 channels.zalo.accounts.<id>.botToken(config 来源);
  2. 账户级令牌文件 channels.zalo.accounts.<id>.tokenFile(configFile 来源);
  3. 频道级 channels.zalo.botToken / channels.zalo.tokenFile;
  4. 环境变量 ZALO_BOT_TOKEN(仅默认账户可用,env 来源)。

令牌文件通过 tryReadSecretFileSync 读取,并带有 rejectSymlink: true 的安全校验(拒绝符号链接文件)。账户的合并逻辑见 zalo/src/accounts.ts:enabled 为频道级与账户级取与,令牌解析结果会记录 tokenSource(env | config | configFile | none),供状态面板展示与诊断。

多账户配置

插件支持多账户,使用 channels.zalo.accounts.<id> 为每个账户单独配置令牌、名称、策略与代理:

{
  channels: {
    zalo: {
      enabled: true,
      defaultAccount: "support",
      accounts: {
        support: {
          name: "Support Bot",
          botToken: "111:aaa",
          dmPolicy: "allowlist",
          allowFrom: [123456789],
        },
        notifier: {
          botToken: "222:bbb",
          dmPolicy: "pairing",
        },
      },
    },
  },
}

多账户能力由 createCatchallMultiAccountChannelSchema 支持(见 zalo/src/config-schema.ts),账户合并时跳过 defaultAccount 键。

通过环境变量配置

默认账户(default account)可以直接使用环境变量,无需写入配置文件:

export ZALO_BOT_TOKEN=12345689:abc-xyz

注意:ZALO_BOT_TOKEN 仅对默认账户生效;非默认账户必须使用 botToken 或 tokenFile 配置(见 zalo/src/setup-core.ts 中的校验逻辑)。

Webhook 模式

如果希望 Zalo 主动推送事件(而不是轮询),配置 Webhook 模式:

{
  channels: {
    zalo: {
      webhookUrl: "https://example.com/zalo-webhook",
      webhookSecret: "your-secret-8-plus-chars",
      webhookPath: "/zalo-webhook",
    },
  },
}

约束与校验

从 zalo/src/monitor.ts 的运行时校验可以看到 Webhook 模式的硬性要求:

  • webhookUrl 与 webhookSecret 必须同时提供,否则启动报错;
  • Webhook URL 必须以 https:// 开头(强制 HTTPS);
  • webhookSecret 长度必须在 8~256 字符之间;
  • 若省略 webhookPath,插件会从 Webhook URL 中推导路径(取 URL 的 pathname),推导失败则报错。

事件验证与安全防护

zalo/src/monitor.webhook.ts 实现了完整的 Webhook 请求管道:

  • 只接受 POST 请求,且要求 Content-Type: application/json(或 +json 类型);
  • Zalo 通过 X-Bot-Api-Secret-Token 请求头携带 secret,插件使用 timingSafeEqual 常量时间比较进行鉴权(monitor.webhook.ts),防止时序侧信道攻击;
  • 按 path + client IP 做固定窗口限流(createFixedWindowRateLimiter),突发流量会返回 HTTP 429;
  • 对 event_name + message_id 做 5 分钟去重窗口(createDedupeCache),忽略重复投递事件;
  • 异常状态码会被 webhookAnomalyTracker 记录并告警;
  • Zalo 的更新体是直接形如 { event_name, message, ... } 的 JSON(并非 Telegram 的 { ok, result } 包装),解析逻辑兼容两种形态(monitor.webhook.ts)。

Webhook 注册后,插件在启动时会调用 setWebhook 向 Zalo 登记,停止时调用 deleteWebhook 清理;切换到轮询模式时也会先检查并删除已有 Webhook(部分 Zalo 环境不支持 webhook 检查时按 404 容错继续,见 monitor.ts)。

Webhook 与长轮询互斥

getUpdates(轮询)与 Webhook 在 Zalo API 文档中是互斥的。配置了 webhookUrl 即进入 Webhook 模式,轮询模式启动前会清除已配置的 Webhook。

长轮询模式

默认模式为长轮询(ZaloApiError.isPollingTimeout,即 errorCode 408 表示"无更新")。轮询循环实现在 zalo/src/monitor.ts:以 30 秒超时调用 getUpdates,每次调用返回单个更新(与 Telegram 返回数组不同,见 zalo/src/api.ts 的注释),循环使用 setImmediate 连续调度,出错后延迟 5 秒重试。该模式无需公网地址,适合本地开发与内网环境。

消息处理流程与媒体支持

支持的入站消息类型

zalo/src/monitor.ts 按 event_name 分发:

事件 处理方式
message.text.received 完整处理,进入回复管线
message.image.received 下载图片后处理(受 mediaMaxMb 限制)
message.sticker.received 仅记录日志,不触发 Agent 回复
message.unsupported.received 仅记录日志(如受保护用户的消息)

图片收发

  • 入站:通过 core.channel.media.fetchRemoteMedia 下载 photo_url,经 saveMediaBuffer 存入沙箱媒体工作区,大小上限为 mediaMaxMb * 1024 * 1024 字节;下载失败只记录错误,不阻断流程(monitor.ts)。
  • 出站:图片通过 sendPhoto 发送,支持 caption(zalo/src/send.ts)。

文本长度限制与分块

Zalo API 的文本上限为 2000 字符(常量 ZALO_TEXT_LIMIT,同时定义于 zalo/src/channel.ts 与 zalo/src/monitor.ts)。插件在出站时按 chunkMarkdownTextWithMode 分块发送,并依据 channels.zalo.markdown 配置将 Markdown 表格转换为代码块形式;回复前还会发送 typing 聊天动作(5 秒超时)。

能力边界

从 zalo/src/channel.ts 的 capabilities 声明可以确认:

能力 状态
私聊(DM) ✅ 支持
群组 ⚠️ 支持,默认 fail-closed(allowlist)
图片媒体 ✅ 支持
Reactions ❌ 不支持
Threads / Polls ❌ 不支持
原生命令 ❌ 不支持
流式输出 ⚠️ 默认阻断(受 2000 字符限制影响)

访问控制

DM 私聊策略(dmPolicy)

默认值为 pairing,未知发送者会收到配对码,配对码 1 小时后过期,批准前消息被忽略。配对批准命令:

openclaw pairing list zalo
openclaw pairing approve zalo <CODE>

配对通过后,插件会向该用户发送确认消息(PAIRING_APPROVED_MESSAGE,见 zalo/src/channel.runtime.ts)。DM 策略可选值:

  • pairing:配对码交换(默认);
  • allowlist:仅允许 allowFrom 中的用户 ID;
  • open:任何用户可直聊(需在 allowFrom 中配置 "*",且 openclaw channels status 会提示安全风险,见 zalo/src/status-issues.ts);
  • disabled:禁止所有私聊。

allowFrom 只接受数字用户 ID(如 123456789),不支持用户名解析;配置引导向导会校验输入必须为纯数字(zalo/src/setup-surface.ts)。ID 可带 zalo: 或 zl: 前缀,运行时会被归一化剥离。

群组策略(groupPolicy)

  • 默认值:allowlist(fail-closed,未显式配置时按安全默认处理);
  • groupAllowFrom 用于限制群内可触发 Bot 的发送者 ID;未设置时回退到 allowFrom;
  • groupPolicy: "disabled":丢弃所有群消息;
  • groupPolicy: "open":允许任意群成员触发(需 @ 提及 Bot,mention-gated);
  • 运行时兜底:即使 channels.zalo 配置段完全缺失,群组访问仍回退为 allowlist 安全策略(zalo/src/group-access.ts)。

群组策略的告警收集逻辑在 zalo/src/channel.ts:当 groupPolicy="open" 且未配置任何 allowlist 时,会提示"任意群成员可触发(mention-gated)",并建议设置 channels.zalo.groupPolicy="allowlist" 与 channels.zalo.groupAllowFrom。

完整配置参考

以下是综合 zalo/src/types.ts 与配置文档得到的全部配置项:

{
  channels: {
    zalo: {
      enabled: true,
      botToken: "12345689:abc-xyz",   // Bot Platform 令牌
      tokenFile: "/path/to/token",    // 或从文件读取令牌
      name: "My Zalo Bot",            // 账户显示名(CLI/UI 列表)
      dmPolicy: "pairing",            // pairing | allowlist | open | disabled
      allowFrom: [123456789],         // DM 白名单(数字用户 ID)
      groupPolicy: "allowlist",       // open | allowlist | disabled
      groupAllowFrom: [123456789],    // 群内发送者白名单,缺省回退 allowFrom
      mediaMaxMb: 5,                  // 入站/出站媒体上限(MB,默认 5)
      markdown: { tables: "code" },   // Markdown 表格输出模式
      proxy: "http://proxy.local:8080",
      responsePrefix: "Bot: ",        // 出站回复前缀覆盖
      // Webhook 模式:
      webhookUrl: "https://example.com/zalo-webhook",
      webhookSecret: "your-secret-8-plus-chars",
      webhookPath: "/zalo-webhook",
    },
  },
}

多账户额外支持:

  • channels.zalo.accounts.<id>.botToken / tokenFile / name / enabled;
  • channels.zalo.accounts.<id>.dmPolicy / allowFrom / groupPolicy / groupAllowFrom;
  • channels.zalo.accounts.<id>.webhookUrl / webhookSecret / webhookPath / proxy;
  • channels.zalo.defaultAccount:指定默认账户 ID。

所有配置修改后需要重启 Gateway 生效(插件声明了 reload: { configPrefixes: <a href="https://link.gitcode.com/i/371273daac589bea68fb3b7ca8fb0eef" target="_blank">"channels.zalo"] },见 [zalo/src/channel.ts)。

CLI 发送与投递目标

Zalo 频道支持通过 CLI/cron 直接投递消息,目标为聊天 ID:

openclaw message send --channel zalo --target 123456789 --message "hi"

目标解析支持 zalo: / zl: 前缀与 group: 前缀(群聊),路由构建见 zalo/src/session-route.ts。Bot 还会向 Agent 暴露 sendMessage 工具动作(to、message、media 参数,见 zalo/src/actions.ts),供模型在授权范围内主动发送 Zalo 消息。

故障排查

Bot 不回复:

  • 校验令牌有效性:openclaw channels status --probe(探测逻辑调用 getMe,见 zalo/src/probe.ts);
  • 确认发送者已批准(配对或 allowFrom 白名单);
  • 查看 Gateway 日志:openclaw logs --follow。

Webhook 收不到事件:

  • 确认 Webhook URL 为 HTTPS;
  • 确认 secret 长度在 8~256 字符之间;
  • 确认 Gateway HTTP 端点在配置的 webhookPath 可达;
  • 确认没有同时运行 getUpdates 轮询(两者互斥)。

启动异常排查: 观察启动日志中 mode=polling|webhook、mediaMaxMb 与探测耗时信息(zalo/src/channel.runtime.ts),探测失败会在 provider 启动前告警,但不会阻断启动。

总结

Zalo 插件为 OpenClaw 提供了完整的越南市场消息接入能力:安装可通过本地路径、npm 或 onboarding 三种方式;令牌支持环境变量、配置与文件三种来源并可按账户隔离;默认长轮询、可选 HTTPS Webhook,并内置常量时间比较、限流、去重与异常追踪等安全机制;DM 默认配对、群组默认 allowlist 的安全默认设计保证了接入即受控。按照本文的配置片段与 CLI 命令即可完成接入,后续可结合 openclaw channels status 与日志持续观测运行状态。

登录后查看全文
openclaw-zero-token