@pawastation/wechat-kf 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +122 -237
- package/README.zh-CN.md +149 -324
- package/dist/src/bot.js +72 -12
- package/dist/src/bot.js.map +1 -1
- package/dist/src/config-schema.d.ts +6 -0
- package/dist/src/config-schema.js +6 -0
- package/dist/src/config-schema.js.map +1 -1
- package/dist/src/types.d.ts +1 -0
- package/openclaw.plugin.json +5 -3
- package/package.json +2 -3
- package/index.ts +0 -42
package/README.zh-CN.md
CHANGED
|
@@ -6,401 +6,226 @@
|
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
[](https://openclaw.dev)
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
让微信用户通过**微信客服**与你的 OpenClaw AI Agent 对话。
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
##
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
13
|
+
## 功能介绍
|
|
14
|
+
|
|
15
|
+
### 可接收的消息类型
|
|
16
|
+
|
|
17
|
+
| 消息类型 | 说明 |
|
|
18
|
+
| ---------- | ---------------------------------------------------- |
|
|
19
|
+
| 文本 | 普通文字,含菜单回调 |
|
|
20
|
+
| 图片 | 图片附件 |
|
|
21
|
+
| 语音 | AMR 格式语音 |
|
|
22
|
+
| 视频 | 视频附件 |
|
|
23
|
+
| 文件 | 各类文件附件 |
|
|
24
|
+
| 链接 | 分享的链接卡片 |
|
|
25
|
+
| 小程序 | 小程序消息卡片 |
|
|
26
|
+
| 位置 | 地理位置(含坐标) |
|
|
27
|
+
| 合并转发 | 多条消息合并转发 |
|
|
28
|
+
| 视频号商品 | 视频号商品卡片 |
|
|
29
|
+
| 视频号订单 | 视频号订单消息 |
|
|
30
|
+
| 视频号消息 | 视频号动态、直播或名片,仅返回部分字段(昵称、标题) |
|
|
31
|
+
| 用户笔记 | 仅识别类型,API 不支持读取内容 |
|
|
32
|
+
|
|
33
|
+
### 可发送的消息类型
|
|
34
|
+
|
|
35
|
+
| 消息类型 | 说明 |
|
|
36
|
+
| ---------- | ---------------- |
|
|
37
|
+
| 文本 | 普通文字 |
|
|
38
|
+
| 图片 | 图片附件 |
|
|
39
|
+
| 语音 | AMR 语音 |
|
|
40
|
+
| 视频 | 视频附件 |
|
|
41
|
+
| 文件 | 各类文件 |
|
|
42
|
+
| 链接卡片 | 带封面图的富链接 |
|
|
43
|
+
| 小程序卡片 | 小程序跳转卡片 |
|
|
44
|
+
| 菜单 | 快捷回复菜单按钮 |
|
|
45
|
+
| 名片 | 企业员工名片 |
|
|
46
|
+
| 位置 | 地理位置 |
|
|
47
|
+
| 获客链接 | 企业获客链接卡片 |
|
|
48
|
+
|
|
49
|
+
### 微信特色功能
|
|
50
|
+
|
|
51
|
+
- **Markdown 样式**:Agent 回复中的粗体、列表、标题等 Markdown 格式,自动转换为微信可显示的 Unicode 样式(粗体用 𝗯𝗼𝗹𝗱 字体,列表用符号等):
|
|
52
|
+
|
|
53
|
+

|
|
54
|
+
|
|
55
|
+
- **消息防抖合并**(`debounceMs`):用户连续快速发出多条消息时,插件会等待设定的时间窗口内无新消息后,再将所有消息合并一次性发给 Agent,避免 Agent 对同一用户意图重复响应。
|
|
32
56
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
1. 一个**企业微信账号**,且拥有管理员权限 — [注册地址](https://work.weixin.qq.com/)
|
|
36
|
-
2. 至少一个**客服账号**(在企业微信的「微信客服」模块中创建)
|
|
37
|
-
3. 一个**公网可访问的 URL**,用于接收回调 — 可使用 [Tailscale Funnel](https://docs.openclaw.ai/gateway/tailscale#tailscale)(推荐,OpenClaw Gateway 内置支持)、[ngrok](https://ngrok.com/)、[Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) 或有公网 IP 的服务器
|
|
38
|
-
4. 已安装并运行 **OpenClaw Gateway**(`openclaw gateway start`)
|
|
39
|
-
|
|
40
|
-
微信客服 API 有**两种接入方式**,请根据实际情况选择:
|
|
57
|
+
---
|
|
41
58
|
|
|
42
|
-
|
|
43
|
-
| ----------------- | ----------------------------------------------------------------- | -------------------------------------------------- |
|
|
44
|
-
| **管理入口** | [企业微信管理后台](https://work.weixin.qq.com/wework_admin/frame) | [微信客服管理后台](https://work.weixin.qq.com/kf/) |
|
|
45
|
-
| **Secret 来源** | 自建应用的 Secret(应用密钥) | 微信客服专属 Secret(开发配置中查看) |
|
|
46
|
-
| **回调配置位置** | 企业微信后台 → 微信客服 → API → 回调设置 | 微信客服后台 → 开发配置 → 回调设置 |
|
|
47
|
-
| **回调 URL 要求** | 必须使用经过企业认证的域名(需在企业微信后台完成可信域名配置) | 无此限制,任意公网可访问的 URL 即可 |
|
|
48
|
-
| **需要自建应用** | 是 — 需创建应用并关联微信客服权限 | 否 — 直接在微信客服后台配置 |
|
|
49
|
-
| **IP 白名单** | 在自建应用中配置「企业可信 IP」 | 不需要(微信客服后台无此限制) |
|
|
50
|
-
| **适用场景** | 已有企业微信自建应用、需与其他企微功能集成 | 仅需微信客服能力、追求简单快速接入 |
|
|
51
|
-
| **推荐程度** | 功能更完整,适合复杂场景 | 配置更简单,适合快速上手 |
|
|
59
|
+
## 为什么选微信客服 API?
|
|
52
60
|
|
|
53
|
-
|
|
61
|
+
相比其他接入微信的方式,微信客服(WeChat KF API)有几个明显优势:
|
|
54
62
|
|
|
55
|
-
|
|
63
|
+
1. **不需要关注公众号** — 用户可以直接点链接发起对话,无需先关注任何账号(后续也可在客服消息中找回历史对话)
|
|
64
|
+
2. **可以发起主动消息** — 在 48 小时会话窗口内,你可以主动给用户发消息(最多五次,但用户恢复后即重置)
|
|
65
|
+
3. **支持多种消息类型** — 文本、图片、语音、视频、文件、链接卡片、小程序卡片、菜单等
|
|
66
|
+
4. **接入简单** — 不需要认证域名,不需要 IP 白名单,用普通 Tunnel 公网地址就能跑
|
|
67
|
+
5. **个人就能注册** — 不需要企业资质,用企业微信 App 就能注册一个"企业"并创建客服账号
|
|
68
|
+
6. **免费** — 微信客服 API 本身免费,无需公众号认证或服务号
|
|
56
69
|
|
|
57
|
-
|
|
58
|
-
openclaw plugins install @pawastation/wechat-kf
|
|
59
|
-
```
|
|
70
|
+
---
|
|
60
71
|
|
|
61
|
-
##
|
|
72
|
+
## 前提条件
|
|
62
73
|
|
|
63
|
-
|
|
74
|
+
1. **企业微信账号** — 用企业微信 App 注册即可(个人就能注册,不需要真实企业)
|
|
75
|
+
2. **已安装并运行 OpenClaw** — 参考 [OpenClaw 文档](https://docs.openclaw.ai/)
|
|
64
76
|
|
|
65
77
|
---
|
|
66
78
|
|
|
67
|
-
|
|
79
|
+
## 快速开始
|
|
68
80
|
|
|
69
|
-
|
|
81
|
+
### 第 1 步:安装插件
|
|
70
82
|
|
|
71
|
-
|
|
83
|
+
```bash
|
|
84
|
+
openclaw plugins install @pawastation/wechat-kf
|
|
85
|
+
```
|
|
72
86
|
|
|
73
|
-
|
|
74
|
-
2. 点击左侧菜单最下方的**「我的企业」**
|
|
75
|
-
3. 在页面底部找到并复制**「企业ID」** — 格式如 `wwXXXXXXXXXXXXXXXX`
|
|
87
|
+
### 第 2 步:安装 Tunnel(cloudflared)
|
|
76
88
|
|
|
77
|
-
|
|
89
|
+
微信客服需要一个公网可访问的回调地址。推荐使用 Cloudflare Tunnel:
|
|
78
90
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
91
|
+
```bash
|
|
92
|
+
# macOS
|
|
93
|
+
brew install cloudflare/cloudflare/cloudflared
|
|
82
94
|
|
|
83
|
-
|
|
95
|
+
# 启动 tunnel(把 7860 换成你的 OpenClaw Gateway 端口)
|
|
96
|
+
cloudflared tunnel --url http://localhost:7860
|
|
97
|
+
```
|
|
84
98
|
|
|
85
|
-
|
|
99
|
+
启动后会显示一个 `https://xxxx.trycloudflare.com` 地址,记下来后面要用。
|
|
86
100
|
|
|
87
|
-
|
|
88
|
-
2. 点击**「API」**小按钮
|
|
89
|
-
3. 在**「可调用接口的应用」**中选择你在第 2 步创建的自建应用
|
|
90
|
-
4. 在**「通过 API 管理微信客服账号 → 企业内部开发」**中,勾选需要通过 API 管理的客服账号
|
|
101
|
+
> 也可以使用 Tailscale Funnel、ngrok 等服务来生成公网地址。
|
|
91
102
|
|
|
92
|
-
|
|
103
|
+
### 第 3 步:注册企业微信
|
|
93
104
|
|
|
94
|
-
|
|
105
|
+
如果你还没有企业微信账号:
|
|
95
106
|
|
|
96
|
-
1.
|
|
97
|
-
2.
|
|
98
|
-
|
|
99
|
-
https://your-domain.com/wechat-kf
|
|
100
|
-
```
|
|
101
|
-
> 使用你的公网 URL。企业微信回调 URL 必须使用经过企业认证的域名(需在企业微信后台完成可信域名配置)。
|
|
102
|
-
3. 设置 **Token** — 任意随机字符串(英文或数字,不超过 32 位),或点击**「随机获取」**自动生成
|
|
103
|
-
4. 设置 **EncodingAESKey** — 43 位字符串(英文或数字),或点击**「随机获取」**自动生成
|
|
104
|
-
5. 点击**「保存」** — 企业微信会发送一个 GET 验证请求到你的回调地址
|
|
107
|
+
1. 下载**企业微信** App
|
|
108
|
+
2. 菜单点击 → 创建/加入企业
|
|
109
|
+
3. 选择**其他**(按实际情况填写表单提交)
|
|
105
110
|
|
|
106
|
-
|
|
111
|
+

|
|
107
112
|
|
|
108
|
-
|
|
113
|
+
### 第 4 步:创建客服账号
|
|
109
114
|
|
|
110
|
-
|
|
115
|
+
1. 打开[微信客服管理后台](https://kf.weixin.qq.com/)(用企业微信 App 扫码登录)
|
|
116
|
+
2. 创建一个客服账号(设置名称和头像)
|
|
111
117
|
|
|
112
|
-
|
|
113
|
-
2. 添加你服务器的公网 IP 地址
|
|
114
|
-
3. 查看当前公网 IP:`curl -s https://api.ipify.org`
|
|
118
|
+

|
|
115
119
|
|
|
116
|
-
|
|
120
|
+
同时在这里复制**企业 ID**(Corp ID)备用:
|
|
117
121
|
|
|
118
|
-
|
|
122
|
+

|
|
119
123
|
|
|
120
|
-
|
|
121
|
-
2. 配置客服名称、头像等信息
|
|
122
|
-
3. 记录 **open_kfid** — 格式如 `wkXXXXXXXXXXXXXXXX`
|
|
123
|
-
4. 生成**「客服链接」**分享给用户 — 微信用户通过此链接发起咨询
|
|
124
|
+
### 第 5 步:在微信客服后台配置回调
|
|
124
125
|
|
|
125
|
-
|
|
126
|
+
1. 打开[微信客服管理后台](https://kf.weixin.qq.com/) → **开发配置** → **开始使用**
|
|
127
|
+
2. 填入回调地址(你的 Tunnel 地址 + `/wechat-kf`,例如 `https://xxxx.trycloudflare.com/wechat-kf`)
|
|
128
|
+
3. 点击**「随机获取」**生成 Token 和 EncodingAESKey
|
|
126
129
|
|
|
127
|
-
|
|
130
|
+

|
|
128
131
|
|
|
129
|
-
|
|
132
|
+
**先复制好 Token 和 EncodingAESKey,暂时不要点「保存」** — 下一步先把这两个值填入 OpenClaw,再回来保存验证。
|
|
130
133
|
|
|
131
|
-
|
|
134
|
+
### 第 6 步:配置 OpenClaw 后台
|
|
132
135
|
|
|
133
|
-
|
|
136
|
+
进入 OpenClaw 后台,添加微信客服渠道配置。`appSecret` 先随便填一个占位值(第 8 步替换),把上一步生成的 Token 和 EncodingAESKey 填入对应字段,**保存配置**:
|
|
134
137
|
|
|
135
|
-
|
|
136
|
-
2. 点击**「我的企业」**,复制**「企业ID」** — 格式如 `wwXXXXXXXXXXXXXXXX`
|
|
138
|
+

|
|
137
139
|
|
|
138
|
-
|
|
140
|
+
OpenClaw 配置示例:
|
|
139
141
|
|
|
140
|
-
|
|
142
|
+
```yaml
|
|
143
|
+
channels:
|
|
144
|
+
wechat-kf:
|
|
145
|
+
enabled: true
|
|
146
|
+
corpId: "wwXXXXXXXXXXXXXXXX" # 第 4 步复制的企业 ID
|
|
147
|
+
appSecret: "placeholder" # 先填占位,第 8 步替换
|
|
148
|
+
token: "从第 5 步复制"
|
|
149
|
+
encodingAESKey: "从第 5 步复制"
|
|
150
|
+
```
|
|
141
151
|
|
|
142
|
-
|
|
143
|
-
2. 进入**「开发配置」**
|
|
144
|
-
3. 点击**「启用 API」**,按照指引填写回调配置
|
|
152
|
+
保存后 OpenClaw 会立即开始监听回调地址,下一步微信的验证请求才能通过。
|
|
145
153
|
|
|
146
|
-
|
|
154
|
+
### 第 7 步:回到微信客服后台完成验证,获取 Secret
|
|
147
155
|
|
|
148
|
-
|
|
149
|
-
2. 此 Secret 由企业微信团队下发给管理员,是**微信客服专属 Secret**,与自建应用 Secret 不同
|
|
150
|
-
3. 如未显示 Secret,点击查看/重置后复制
|
|
156
|
+
回到[微信客服管理后台](https://kf.weixin.qq.com/)的开发配置页面,点击**「保存」** — 微信会立即向你的回调地址发一个验证请求,OpenClaw 自动回应,验证通过后配置生效。
|
|
151
157
|
|
|
152
|
-
|
|
158
|
+

|
|
153
159
|
|
|
154
|
-
|
|
160
|
+
验证通过后,在同一页面复制 **App Secret**:
|
|
155
161
|
|
|
156
|
-
|
|
157
|
-
2. 设置**回调地址(URL)**:
|
|
158
|
-
```
|
|
159
|
-
https://your-domain.com/wechat-kf
|
|
160
|
-
```
|
|
161
|
-
3. 设置 **Token** — 任意随机字符串,或点击**「随机获取」**自动生成
|
|
162
|
-
4. 设置 **EncodingAESKey** — 43 位字符串,或点击**「随机获取」**自动生成
|
|
163
|
-
5. 保存配置 — 系统会发送 GET 验证请求到回调地址
|
|
162
|
+

|
|
164
163
|
|
|
165
|
-
|
|
164
|
+
### 第 8 步:更新 Secret
|
|
166
165
|
|
|
167
|
-
|
|
166
|
+
把第 6 步填的占位 Secret 替换为刚复制的实际值,保存配置:
|
|
168
167
|
|
|
169
|
-
|
|
170
|
-
2. 记录 **open_kfid**
|
|
171
|
-
3. 生成**「客服链接」**分享给用户
|
|
168
|
+

|
|
172
169
|
|
|
173
|
-
|
|
170
|
+
### 第 9 步:开始聊天
|
|
174
171
|
|
|
175
|
-
|
|
172
|
+
在微信客服后台找到你的客服账号,复制**客服链接**分享给用户(或者自己先测试):
|
|
176
173
|
|
|
177
|
-
|
|
174
|
+

|
|
178
175
|
|
|
179
|
-
|
|
180
|
-
| ----------------- | ------------------------------------------------------------------------------ | ---------------------------------------------------------------- |
|
|
181
|
-
| **配置复杂度** | 较高 — 需创建应用、关联权限、配置白名单 | 较低 — 直接启用 API 即可 |
|
|
182
|
-
| **Secret 类型** | 自建应用 Secret(应用密钥) | 微信客服专属 Secret |
|
|
183
|
-
| **回调 URL 要求** | 必须使用经过企业认证的域名(需完成可信域名配置) | 无此限制,任意公网可访问的 URL 即可 |
|
|
184
|
-
| **IP 白名单** | 必须配置(自建应用安全要求) | 无需配置 |
|
|
185
|
-
| **API 能力** | 完整 — 可同时调用企业微信其他 API | 仅限微信客服相关接口 |
|
|
186
|
-
| **管理灵活性** | 高 — 可精细控制哪些客服账号走 API | 中 — API 启用后覆盖所有账号 |
|
|
187
|
-
| **与企微集成** | 天然集成 — 员工可在企微客户端接待 | 独立运作 — 不依赖企微客户端 |
|
|
188
|
-
| **适合谁** | 已有企微开发经验、需要多功能集成的团队 | 只需 AI 客服、追求最快上手的开发者 |
|
|
189
|
-
| **凭证获取** | 企业微信管理后台 → 应用管理 → 应用详情 | 微信客服管理后台 → 开发配置 |
|
|
190
|
-
| **回调配置** | 企业微信后台 → 微信客服 → API → 回调设置 | 微信客服后台 → 开发配置 → 回调设置 |
|
|
191
|
-
| **官方文档** | [企业微信开发者文档](https://developer.work.weixin.qq.com/document/path/94638) | [微信客服 API 文档](https://kf.weixin.qq.com/api/doc/path/93304) |
|
|
176
|
+
用微信扫码或点开链接,就能和你的 AI Agent 对话了。
|
|
192
177
|
|
|
193
|
-
|
|
178
|
+
### 第 10 步:安全设置(推荐)
|
|
194
179
|
|
|
195
|
-
|
|
180
|
+
默认情况下,任何拿到客服链接的人都可以发消息。如果你想限制访问,可以开启 `pairing`(配对)模式:
|
|
196
181
|
|
|
197
|
-
|
|
182
|
+
在 OpenClaw 后台把 `dmPolicy` 改为 `pairing`:
|
|
198
183
|
|
|
199
|
-
|
|
200
|
-
channels:
|
|
201
|
-
wechat-kf:
|
|
202
|
-
enabled: true
|
|
203
|
-
corpId: "wwXXXXXXXXXXXXXXXX" # 企业 ID
|
|
204
|
-
appSecret: "your-app-secret-here" # 应用密钥(自建应用 Secret 或微信客服 Secret)
|
|
205
|
-
token: "your-callback-token" # 回调 Token
|
|
206
|
-
encodingAESKey: "your-43-char-key" # 回调 EncodingAESKey(43 位字符)
|
|
207
|
-
webhookPath: "/wechat-kf" # Webhook URL 路径(默认:/wechat-kf)
|
|
208
|
-
dmPolicy: "open" # 访问控制:open | allowlist | pairing | disabled
|
|
209
|
-
# allowFrom: # 仅在 dmPolicy 为 allowlist 时使用
|
|
210
|
-
# - "external_userid_1"
|
|
211
|
-
# - "external_userid_2"
|
|
212
|
-
```
|
|
184
|
+

|
|
213
185
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|
|
217
|
-
| ---------------- | -------- | ------ | ------------ | ------------------------------------------------------------- |
|
|
218
|
-
| `enabled` | boolean | 否 | `false` | 是否启用该渠道 |
|
|
219
|
-
| `corpId` | string | **是** | — | 企业 ID |
|
|
220
|
-
| `appSecret` | string | **是** | — | 自建应用密钥或微信客服 Secret |
|
|
221
|
-
| `token` | string | **是** | — | Webhook 回调 Token |
|
|
222
|
-
| `encodingAESKey` | string | **是** | — | 43 位 AES 加密密钥 |
|
|
223
|
-
| `webhookPath` | string | 否 | `/wechat-kf` | Webhook 回调 URL 路径 |
|
|
224
|
-
| `dmPolicy` | string | 否 | `"open"` | `open`(开放)/ `allowlist`(白名单)/ `pairing`(配对)/ `disabled`(禁用) |
|
|
225
|
-
| `allowFrom` | string[] | 否 | `[]` | 允许的 external_userid 列表(dmPolicy 为 `allowlist` 时使用) |
|
|
226
|
-
|
|
227
|
-
## 验证
|
|
228
|
-
|
|
229
|
-
1. 启动 OpenClaw Gateway:
|
|
230
|
-
```bash
|
|
231
|
-
openclaw gateway start
|
|
232
|
-
```
|
|
233
|
-
2. 将 Gateway 暴露到公网(如果不在公网服务器上)。方式 A — Tailscale Funnel(内置支持):
|
|
234
|
-
```bash
|
|
235
|
-
openclaw gateway --tailscale funnel --auth password
|
|
236
|
-
```
|
|
237
|
-
方式 B — ngrok:
|
|
238
|
-
```bash
|
|
239
|
-
ngrok http <gateway-port>
|
|
240
|
-
```
|
|
241
|
-
3. 复制 HTTPS URL(如 `https://your-machine.tail1234.ts.net` 或 `https://xxxx.ngrok-free.app`),在企业微信中设置回调地址:
|
|
242
|
-
```
|
|
243
|
-
https://<your-public-host>/wechat-kf
|
|
244
|
-
```
|
|
245
|
-
4. 企业微信发送 GET 验证请求 — 插件自动解密 `echostr` 并响应
|
|
246
|
-
5. 从微信中通过客服链接发送测试消息,确认 Agent 正常回复
|
|
247
|
-
|
|
248
|
-
## 使用方式
|
|
249
|
-
|
|
250
|
-
配置完成并运行后,插件自动工作:
|
|
251
|
-
|
|
252
|
-
1. **用户**在微信中点击客服链接发起对话
|
|
253
|
-
2. **入站消息**通过 webhook 到达 → 插件解密、通过 `sync_msg` 同步消息、下载媒体附件,然后分发给 OpenClaw Agent
|
|
254
|
-
3. **Agent** 处理消息并生成回复
|
|
255
|
-
4. **出站回复**通过企业微信 `send_msg` API 发送,Markdown 自动转换为 Unicode 格式化纯文本
|
|
256
|
-
|
|
257
|
-
### 从 Agent 发送消息
|
|
258
|
-
|
|
259
|
-
Agent 可以使用 `message` 工具发送消息:
|
|
260
|
-
|
|
261
|
-
- **回复当前对话** — 省略 `target`,回复将发送给发消息的用户
|
|
262
|
-
- **发送给特定用户** — 将 `target` 设为用户的 `external_userid`
|
|
263
|
-
- **发送媒体** — 使用 `filePath` 或 `media` 附加图片、语音、视频或文件
|
|
264
|
-
|
|
265
|
-
### 支持的入站消息类型
|
|
266
|
-
|
|
267
|
-
| 微信消息类型 | 处理方式 |
|
|
268
|
-
| ------------ | ----------------------------------------- |
|
|
269
|
-
| 文本 | 原样传递给 Agent |
|
|
270
|
-
| 图片 | 下载保存为媒体附件,向 Agent 发送占位文本 |
|
|
271
|
-
| 语音 | 下载为 AMR 格式,保存为媒体附件 |
|
|
272
|
-
| 视频 | 下载为 MP4 格式,保存为媒体附件 |
|
|
273
|
-
| 文件 | 下载保存为媒体附件 |
|
|
274
|
-
| 位置 | 转换为文本:`[位置: 名称 地址]` |
|
|
275
|
-
| 链接 | 转换为文本:`[链接: 标题 URL]`(含 desc、pic_url)|
|
|
276
|
-
| 小程序 | 转换为文本,包含标题、appid 和 pagepath |
|
|
277
|
-
| 视频号 | 转换为文本,包含类型、昵称、标题 |
|
|
278
|
-
| 视频号商品 | 转换为文本,包含商品信息 |
|
|
279
|
-
| 视频号订单 | 转换为文本,包含订单信息 |
|
|
280
|
-
| 笔记 | 转换为文本,包含笔记内容 |
|
|
281
|
-
| 名片 | 转换为文本,包含 userid |
|
|
282
|
-
| 合并转发消息 | 解析并展开为可读文本 |
|
|
283
|
-
|
|
284
|
-
### 支持的出站消息类型
|
|
285
|
-
|
|
286
|
-
文本、图片、语音、视频、文件、链接、位置、小程序、菜单、名片、视频号文章和原始 JSON 消息(`[[wechat_raw:...]]`)。富消息类型通过 `[[wechat_*:...]]` 文本指令发送。所有来源的媒体(本地文件、HTTP URL、file:// URI)通过框架 loadWebMedia 加载后自动上传到微信临时素材存储。
|
|
287
|
-
|
|
288
|
-
## 架构
|
|
186
|
+
开启后,新用户第一次发消息会收到配对码:
|
|
289
187
|
|
|
290
|
-
|
|
291
|
-
微信用户
|
|
292
|
-
|
|
|
293
|
-
v
|
|
294
|
-
企业微信服务器(腾讯)
|
|
295
|
-
|
|
|
296
|
-
|--- POST 回调 ---> webhook.ts ---> 验证签名 + 大小/方法守卫
|
|
297
|
-
| (加密 XML) | 解密 AES-256-CBC
|
|
298
|
-
| | 提取 OpenKfId + Token
|
|
299
|
-
| v
|
|
300
|
-
| bot.ts ---> DM 策略检查
|
|
301
|
-
| | per-kfId 互斥锁 + msgid 去重
|
|
302
|
-
| | sync_msg API(拉取消息)
|
|
303
|
-
| | 基于游标的增量同步
|
|
304
|
-
| | 处理事件(enter_session 等)
|
|
305
|
-
| | 下载媒体附件
|
|
306
|
-
| v
|
|
307
|
-
| OpenClaw Agent(通过 runtime 分发)
|
|
308
|
-
| |
|
|
309
|
-
| +-----------+-----------+
|
|
310
|
-
| v v
|
|
311
|
-
| outbound.ts reply-dispatcher.ts
|
|
312
|
-
| (框架驱动) (插件内部流式处理)
|
|
313
|
-
| chunker 声明 markdown -> unicode
|
|
314
|
-
| sendText / sendMedia 文本分块 + 延迟
|
|
315
|
-
| | |
|
|
316
|
-
| +-----------+-----------+
|
|
317
|
-
| v
|
|
318
|
-
| send-utils.ts
|
|
319
|
-
| formatText, mediaKindToWechatType
|
|
320
|
-
| detectMediaType, uploadAndSendMedia
|
|
321
|
-
| resolveThumbMediaId
|
|
322
|
-
| v
|
|
323
|
-
+--- send_msg API <-- api.ts
|
|
324
|
-
(JSON)
|
|
325
|
-
```
|
|
188
|
+

|
|
326
189
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
| 模块 | 职责 |
|
|
330
|
-
| --------------------- | ------------------------------------------------------------------------------------- |
|
|
331
|
-
| `webhook.ts` | HTTP 处理器(框架网关)— GET 验证、POST 事件处理、大小/方法守卫 |
|
|
332
|
-
| `crypto.ts` | AES-256-CBC 加密/解密、SHA-1 签名验证、PKCS#7 填充校验 |
|
|
333
|
-
| `token.ts` | Access Token 缓存,哈希键存储,自动刷新 |
|
|
334
|
-
| `api.ts` | 企业微信 API 客户端(sync_msg、send_msg、sendRawMessage、媒体上传/下载),Token 过期自动重试 |
|
|
335
|
-
| `accounts.ts` | 动态客服账号发现、解析、启用/禁用/删除生命周期 |
|
|
336
|
-
| `bot.ts` | 消息同步(互斥锁 + 去重)、DM 策略检查、事件处理、Agent 分发 |
|
|
337
|
-
| `monitor.ts` | 共享上下文管理器(setSharedContext/getSharedContext/waitForSharedContext/clearSharedContext)|
|
|
338
|
-
| `reply-dispatcher.ts` | 插件内部流式回复投递,包含分块、格式化、延迟 |
|
|
339
|
-
| `outbound.ts` | 框架驱动的出站适配器,声明 chunker |
|
|
340
|
-
| `send-utils.ts` | 共享出站工具(formatText、mediaKindToWechatType、detectMediaType、uploadAndSendMedia、resolveThumbMediaId) |
|
|
341
|
-
| `wechat-kf-directives.ts` | `[[wechat_*:...]]` 指令解析器,用于 agent 回复中的富文本消息类型 |
|
|
342
|
-
| `constants.ts` | 共享常量(WECHAT_TEXT_CHUNK_LIMIT、超时、错误码) |
|
|
343
|
-
| `fs-utils.ts` | 原子文件操作(临时文件 + 重命名) |
|
|
344
|
-
| `unicode-format.ts` | Markdown 转 Unicode 数学字母符号格式化 |
|
|
345
|
-
| `channel.ts` | ChannelPlugin 接口,包含安全适配器(resolveDmPolicy、collectWarnings) |
|
|
346
|
-
| `config-schema.ts` | wechat-kf 渠道配置的 JSON Schema 校验 |
|
|
347
|
-
| `runtime.ts` | OpenClaw 运行时引用持有 |
|
|
348
|
-
|
|
349
|
-
### 状态持久化
|
|
350
|
-
|
|
351
|
-
- **同步游标** — 按客服账号保存在 `~/.openclaw/state/wechat-kf/wechat-kf-cursor-{kfid}.txt`(原子写入)
|
|
352
|
-
- **已发现的客服 ID** — 保存在 `~/.openclaw/state/wechat-kf/wechat-kf-kfids.json`(原子写入)
|
|
353
|
-
- **Access Token** — 仅内存缓存,使用哈希键(重启后重新获取)
|
|
354
|
-
|
|
355
|
-
## 限制与已知问题
|
|
356
|
-
|
|
357
|
-
- **开放访问特性** — 微信客服在微信生态中本质上是公开服务。任何获取到客服联系方式(链接或二维码)的人都可以向客服账号发送消息 — 这在微信平台层面无法阻止。插件的 `dmPolicy: "allowlist"` 模式可以限制 agent 只回复白名单内的用户(非白名单用户的消息会被静默丢弃,不会触发 agent 也不会收到回复),但无法阻止未知用户触达客服入口本身。请在生产环境部署前充分了解这一公开服务特性。
|
|
358
|
-
- **48 小时回复窗口** — 微信仅允许在用户最后一条消息后 48 小时内回复。插件检测此限制(errcode 95026)并记录清晰警告。
|
|
359
|
-
- **5 条消息限制** — 在用户发送下一条消息前,最多只能发送 5 条回复。插件检测此限制并相应记录日志。
|
|
360
|
-
- **语音格式** — 入站语音消息为 AMR 格式;转录取决于 OpenClaw Agent 的媒体处理能力。
|
|
361
|
-
- **仅临时素材** — 上传的媒体使用微信临时素材 API(3 天有效期)。未实现永久素材上传。
|
|
362
|
-
- **单一 webhook 端点** — 所有客服账号共享同一个 webhook 路径。这是设计如此(企业微信为每个企业发送所有回调到同一个 URL)。
|
|
363
|
-
- **不支持群聊** — 微信客服仅支持一对一会话。插件仅支持 `direct` 聊天类型。
|
|
364
|
-
- **IP 白名单漂移** — 如果服务器公网 IP 变化,API 调用将静默失败。请监控 IP 或使用静态 IP。
|
|
365
|
-
|
|
366
|
-
## 开发
|
|
190
|
+
在 openclaw 所在电脑上运行以下命令批准:
|
|
367
191
|
|
|
368
192
|
```bash
|
|
369
|
-
|
|
370
|
-
|
|
193
|
+
openclaw pairing approve wechat-kf <配对码>
|
|
194
|
+
```
|
|
371
195
|
|
|
372
|
-
|
|
373
|
-
pnpm run build
|
|
196
|
+
---
|
|
374
197
|
|
|
375
|
-
|
|
376
|
-
pnpm run typecheck
|
|
198
|
+
## 配置参考
|
|
377
199
|
|
|
378
|
-
|
|
379
|
-
|
|
200
|
+
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|
|
201
|
+
| ---------------- | -------- | ------ | ------------ | -------------------------------------------------------------------------------------------------------------- |
|
|
202
|
+
| `enabled` | boolean | 否 | `false` | 是否启用该渠道 |
|
|
203
|
+
| `corpId` | string | **是** | — | 企业 ID |
|
|
204
|
+
| `appSecret` | string | **是** | — | 微信客服 Secret(从微信客服后台「开发配置」获取) |
|
|
205
|
+
| `token` | string | **是** | — | Webhook 回调 Token |
|
|
206
|
+
| `encodingAESKey` | string | **是** | — | 43 位 AES 加密密钥 |
|
|
207
|
+
| `webhookPath` | string | 否 | `/wechat-kf` | Webhook 回调 URL 路径 |
|
|
208
|
+
| `dmPolicy` | string | 否 | `"open"` | `open`(开放)/ `allowlist`(白名单)/ `pairing`(配对)/ `disabled`(禁用) |
|
|
209
|
+
| `allowFrom` | string[] | 否 | `[]` | 允许的 external_userid 列表(dmPolicy 为 `allowlist` 时使用) |
|
|
210
|
+
| `debounceMs` | number | 否 | `2000` | 消息防抖窗口(毫秒,0–10000):等待窗口内无新消息后再发给 Agent,适合用户分多条消息输入的场景;设为 `0` 可禁用 |
|
|
380
211
|
|
|
381
|
-
|
|
382
|
-
pnpm run test:watch
|
|
212
|
+
---
|
|
383
213
|
|
|
384
|
-
|
|
385
|
-
pnpm run lint
|
|
214
|
+
## 有什么限制?
|
|
386
215
|
|
|
387
|
-
|
|
388
|
-
|
|
216
|
+
- **任何人都能发消息** — 拿到客服链接的人都能发消息,这是微信平台层面的设计,无法阻止。可以用 `dmPolicy: "pairing"` 或 `"allowlist"` 让 Agent 只回复指定用户。
|
|
217
|
+
- **48 小时回复窗口** — 用户最后一条消息后 48 小时内才能回复。超时后需要用户再发一条消息才能继续。
|
|
218
|
+
- **5 条消息限制** — 在用户发下一条消息前,最多只能发 5 条回复。
|
|
219
|
+
- **语音格式** — 入站语音为 AMR 格式,是否能转录取决于你的 Agent 配置。
|
|
220
|
+
- **Tunnel 地址会变** — 使用 cloudflared 免费隧道时,每次重启地址会变。固定地址可以购买域名并解析到服务器,或使用付费 Tunnel(如 Cloudflare Zero Trust)、有静态 IP 的服务器。
|
|
389
221
|
|
|
390
|
-
|
|
391
|
-
pnpm run format
|
|
222
|
+
---
|
|
392
223
|
|
|
393
|
-
|
|
394
|
-
pnpm run check
|
|
395
|
-
```
|
|
224
|
+
## 开发者文档
|
|
396
225
|
|
|
397
|
-
|
|
226
|
+
架构设计、模块说明、开发命令和贡献流程,请参阅 [CONTRIBUTING.md](./CONTRIBUTING.md)。
|
|
398
227
|
|
|
399
|
-
|
|
400
|
-
2. 创建功能分支(`git checkout -b feature/my-feature`)
|
|
401
|
-
3. 修改代码并添加测试
|
|
402
|
-
4. 运行 `pnpm run check && pnpm run typecheck && pnpm test` 验证
|
|
403
|
-
5. 提交 Pull Request
|
|
228
|
+
---
|
|
404
229
|
|
|
405
230
|
## 许可证
|
|
406
231
|
|