@openclaw-china/wechat-mp
v2026.3.22
Published
OpenClaw WeChat Official Account (微信公众号) channel plugin
Downloads
1,446
Readme
@openclaw-china/wechat-mp
wechat-mp 是一个独立的微信公众号(订阅号 / 服务号)渠道插件,用于把公众号消息接入 OpenClaw。
功能特性
入站消息
| 消息类型 | 支持状态 | 说明 | |---------|---------|------| | 文本消息 | ✅ | 完整支持,自动处理超长分割 | | 图片消息 | ✅ | 返回图片 URL 和 MediaId | | 语音消息 | ✅ | 支持 ASR 自动转文字 | | 视频消息 | ✅ | 返回视频 MediaId | | 短视频消息 | ✅ | 返回短视频 MediaId | | 位置消息 | ✅ | 返回经纬度和地址 | | 链接消息 | ✅ | 返回标题、描述和 URL | | 事件消息 | ✅ | subscribe/unsubscribe/scan/click/view |
主动发送
| 发送类型 | 支持状态 | 说明 | |---------|---------|------| | 文本消息 | ✅ | 支持超长自动分割 | | 模板消息 | ✅ | 业务通知消息 | | 图片消息 | ✅ | 自动上传并发送 | | 语音消息 | ✅ | 自动上传并发送 | | 视频消息 | ✅ | 自动上传并发送 |
高级功能
- 语音转文字 (ASR): 集成腾讯云语音识别,自动将语音转为文字
- 重试机制: 支持指数退避重试,处理网络波动和限流
- 时间窗口检查: 48小时交互窗口检测,发送前权限验证
- Markdown 渲染: 自动转换为公众号友好的纯文本格式
配置示例
基础配置
{
"channels": {
"wechat-mp": {
"enabled": true,
"webhookPath": "/wechat-mp",
"appId": "wx1234567890abcdef",
"appSecret": "your-app-secret",
"token": "your-callback-token",
"encodingAESKey": "your-43-char-encoding-aes-key",
"messageMode": "safe",
"replyMode": "active",
"activeDeliveryMode": "split",
"renderMarkdown": true,
"welcomeText": "你好,欢迎关注。"
}
}
}完整配置(含 ASR)
{
"channels": {
"wechat-mp": {
"enabled": true,
"webhookPath": "/wechat-mp",
"appId": "wx1234567890abcdef",
"appSecret": "your-app-secret",
"token": "your-callback-token",
"encodingAESKey": "your-43-char-encoding-aes-key",
"messageMode": "safe",
"replyMode": "active",
"activeDeliveryMode": "split",
"renderMarkdown": true,
"welcomeText": "你好,欢迎关注。",
"dmPolicy": "open",
"allowFrom": [],
"retryConfig": {
"maxRetries": 3,
"initialDelay": 1000,
"maxDelay": 10000,
"backoffMultiplier": 2
},
"asr": {
"enabled": true,
"appId": "腾讯云 AppId",
"secretId": "腾讯云 SecretId",
"secretKey": "腾讯云 SecretKey",
"engineType": "16k_zh",
"timeoutMs": 30000
}
}
}
}多账号配置
{
"channels": {
"wechat-mp": {
"defaultAccount": "main",
"accounts": {
"main": {
"appId": "wx-main-account",
"appSecret": "main-secret",
"token": "main-token"
},
"sub": {
"appId": "wx-sub-account",
"appSecret": "sub-secret",
"token": "sub-token"
}
}
}
}
}配置字段说明
基础配置
| 字段 | 类型 | 必填 | 说明 |
|-----|------|-----|------|
| enabled | boolean | 否 | 是否启用,默认 true |
| webhookPath | string | 否 | 回调路径,默认 /wechat-mp |
| appId | string | 是 | 公众号 AppId |
| appSecret | string | 条件 | 主动发送必填 |
| token | string | 是 | 回调 Token |
| encodingAESKey | string | 条件 | safe/compat 模式必填 |
| messageMode | string | 否 | 消息模式:plain / safe / compat |
| replyMode | string | 否 | 回复模式:passive / active |
| activeDeliveryMode | string | 否 | 主动发送模式:split / merged |
| renderMarkdown | boolean | 否 | 是否渲染 Markdown,默认 true |
| welcomeText | string | 否 | 关注欢迎语 |
| dmPolicy | string | 否 | DM 策略:open / pairing / allowlist / disabled |
| allowFrom | string[] | 否 | 允许的用户列表 |
重试配置 (retryConfig)
| 字段 | 类型 | 默认值 | 说明 |
|-----|------|-------|------|
| maxRetries | number | 3 | 最大重试次数 |
| initialDelay | number | 1000 | 初始延迟(毫秒) |
| maxDelay | number | 10000 | 最大延迟(毫秒) |
| backoffMultiplier | number | 2 | 退避乘数 |
ASR 配置 (asr)
| 字段 | 类型 | 必填 | 说明 |
|-----|------|-----|------|
| enabled | boolean | 否 | 是否启用 ASR |
| appId | string | 是 | 腾讯云 AppId |
| secretId | string | 是 | 腾讯云 SecretId |
| secretKey | string | 是 | 腾讯云 SecretKey |
| engineType | string | 否 | 引擎类型,默认 16k_zh |
| timeoutMs | number | 否 | 超时时间,默认 30000 |
API 使用示例
发送文本
import { wechatMpOutbound } from "@openclaw-china/wechat-mp";
// 发送文本
await wechatMpOutbound.sendText({
cfg,
to: "user:openid123",
text: "Hello, World!"
});发送模板消息
await wechatMpOutbound.sendTemplate({
cfg,
to: "user:openid123",
templateId: "template_id_here",
data: {
first: { value: "您好,您有新的通知" },
keyword1: { value: "订单号:123456" },
keyword2: { value: "已发货" },
remark: { value: "点击查看详情" }
},
url: "https://example.com/order/123456"
});发送媒体消息
import { readFileSync } from "fs";
// 发送图片
await wechatMpOutbound.sendMedia({
cfg,
to: "user:openid123",
mediaType: "image",
buffer: readFileSync("./image.jpg"),
filename: "image.jpg"
});
// 发送语音
await wechatMpOutbound.sendMedia({
cfg,
to: "user:openid123",
mediaType: "voice",
buffer: readFileSync("./voice.amr"),
filename: "voice.amr"
});
// 发送视频
await wechatMpOutbound.sendMedia({
cfg,
to: "user:openid123",
mediaType: "video",
buffer: readFileSync("./video.mp4"),
filename: "video.mp4"
});检查发送能力
// 检查用户是否在 48 小时交互窗口内
const capability = await wechatMpOutbound.checkCapability({
cfg,
to: "user:openid123"
});
if (!capability.canSend) {
console.log(`无法发送:${capability.reason}`);
}
// 检查时间窗口
const inWindow = wechatMpOutbound.checkTimeWindow({
config: { mode: "business" } // 工作时间 9:00-18:00
});记录用户交互
// 在处理入站消息时调用,用于 48 小时窗口跟踪
await wechatMpOutbound.recordInteraction({
cfg,
openId: "openid123"
});联调要点
- 回调配置:公众号后台服务器地址指向网关回调地址
- 消息模式:
plain:明文模式,最小链路验证safe:加密模式,需要encodingAESKeycompat:兼容模式,同时支持明文和加密
- 主动发送:必须配置
appSecret - 回复模式:
passive:5 秒内 HTTP 回包active:使用客服消息 API 主动发送
- 消息长度:2048 字节限制,超长自动分割
- 语音识别:
- 方法一:公众号后台开启"语音识别"功能
- 方法二:配置
asr使用腾讯云 ASR
开发测试
# 构建
pnpm -F @openclaw-china/wechat-mp build
# 测试
pnpm -F @openclaw-china/wechat-mp test
# 类型检查
pnpm -F @openclaw-china/wechat-mp typecheck文档入口
- 开发计划:
doc/guides/wechat-mp/doc/开发计划.md - 配置指南:
doc/guides/wechat-mp/configuration.md - 微信官方文档:
doc/guides/wechat-mp/doc/mp接口文档/
