微信龙虾插件源码分析及MCP实现
目录
1. 项目概述与架构全景
2. 认证接口:QR 码登录流程
3. 核心通信接口:getUpdates 长轮询
4. 下行接口:sendMessage 消息发送
5. 媒体文件接口:CDN 加密上传/下载
6. 配置与打字状态接口
7. 通信协议细节:请求头、错误码、重试机制
8. 数据模型完整字段表
9. Session 生命周期管理
10. 消息处理内部管道
https://github.com/yindex/wx-mcp
1. 项目概述与架构全景
1.2 整体架构图
系统由三层构成:微信 iLink API 服务器、openclaw-weixin 插件层、OpenClaw Core Runtime,通过 HTTPS/JSON 双向通信,另有 CDN 服务器处理加密媒体文件。

图1:系统整体架构
1.3 目录结构
openclaw-weixin/├── index.ts # 插件注册入口├── src/│ ├── api/│ │ ├── api.ts # 所有 HTTP API 封装(核心)│ │ ├── types.ts # 协议数据类型定义│ │ ├── session-guard.ts # Session 暂停/恢复保护│ │ └── config-cache.ts # typing_ticket 缓存管理器│ ├── auth/│ │ ├── accounts.ts # 账号存储/加载(凭证管理)│ │ └── login-qr.ts # QR 码登录流程│ ├── cdn/│ │ ├── upload.ts # 媒体上传编排│ │ ├── cdn-upload.ts # CDN POST + AES 加密│ │ ├── aes-ecb.ts # AES-128-ECB 加解密│ │ └── pic-decrypt.ts # CDN 下载 + 解密│ ├── messaging/│ │ ├── inbound.ts # 入站消息归一化│ │ ├── send.ts # 文字/媒体消息发送│ │ ├── send-media.ts # 媒体类型路由│ │ └── process-message.ts # 主消息处理器│ ├── monitor/│ │ └── monitor.ts # 长轮询事件循环(核心)│ └── storage/│ └── sync-buf.ts # 游标持久化
2. 认证接口:QR 码登录流程
2.1 流程图

图2:QR 码登录流程
2.2 接口一:获取二维码
GEThttps://ilinkai.weixin.qq.com/ilink/bot/get_bot_qrcode?bot_type=3
请求头:
|
字段 |
值 |
说明 |
|
SKRouteTag |
可选数字字符串 |
路由标签,从 openclaw.json 读取 |
响应体:
{"qrcode": "weixin://xxxx...","qrcode_img_content": "https://mp.weixin.qq.com/..."}
|
字段 |
类型 |
说明 |
|
qrcode |
string |
二维码原始数据(用于轮询状态) |
|
qrcode_img_content |
string |
二维码图片 URL(展示给用户扫码) |
2.3 接口二:轮询二维码状态
端点:GET https://ilinkai.weixin.qq.com/ilink/bot/get_qrcode_status?qrcode={qrcode}
客户端超时:35 秒(AbortController),超时返回 { status: “wait” } 继续轮询
|
字段 |
类型 |
说明 |
|
status |
enum |
wait / scaned / confirmed / expired |
|
bot_token |
string? |
登录成功后的 Bot 凭证 Token |
|
ilink_bot_id |
string? |
Bot 账号 ID(存为 accountId) |
|
baseurl |
string? |
服务器分配的 API 地址 |
|
ilink_user_id |
string? |
扫码用户的 ID |
2.4 凭证存储
登录成功后,Token 持久化到本地文件系统(权限 0600):
~/.openclaw/openclaw-weixin/
├── accounts.json# 账号 ID 索引
└── accounts/
└──{normalizedAccountId}.json# 每个账号的凭证
账号凭证格式:
{"token": "ilink_bot_token_xxxxx","savedAt": "2026-03-22T10:00:00.000Z","baseUrl": "https://ilinkai.weixin.qq.com","userId": "user123@im.wechat"}
⚠ 注意:账号 ID 规范化:b0f5860fdecb@im.bot → b0f5860fdecb-im-bot(文件系统安全)
3. 核心通信接口:getUpdates 长轮询
3.1 长轮询机制

图3:getUpdates 长轮询状态机
3.2 通用请求头(所有 API 接口共用)
|
请求头 |
值 |
必填 |
说明 |
|
Content-Type |
application/json |
是 |
固定值 |
|
Authorization |
Bearer {token} |
是 |
ilink_bot_token 凭证 |
|
AuthorizationType |
ilink_bot_token |
是 |
鉴权类型标识 |
|
Content-Length |
字节数 |
是 |
UTF-8 编码后的 body 长度 |
|
X-WECHAT-UIN |
base64(随机uint32) |
是 |
反指纹随机标识,每次请求重新生成 |
|
SKRouteTag |
可选数字字符串 |
否 |
路由标签(多区域部署) |
3.3 请求体与响应体
端点:POST https://ilinkai.weixin.qq.com/ilink/bot/getupdates
// 请求体{"get_updates_buf": "xABC...", // 上次响应返回的游标,首次传 """base_info": { "channel_version": "1.0.2" }}// 响应体{"ret": 0,"errcode": 0, // 错误码(-14 = Session 过期)"errmsg": "","msgs": [ /* WeixinMessage[] */ ],"get_updates_buf": "xDEF...", // 下次请求必须带上的游标"longpolling_timeout_ms": 35000 // 服务器建议下次超时毫秒数}
3.4 游标持久化
游标文件:~/.openclaw/openclaw-weixin/accounts/{accountId}.sync.json
进程重启时读取此文件,实现断点续传,不丢失历史消息。
4. 下行接口:sendMessage 消息发送
4.1 发送流程

图4:下行消息发送流程
4.2 文字消息请求体
端点:POST https://ilinkai.weixin.qq.com/ilink/bot/sendmessage
{"msg": {"from_user_id": "", // Bot 发送时固定为空"to_user_id": "user123@im.wechat","client_id": "openclaw-weixin:1711094400000-a1b2","message_type": 2, // 2=Bot消息(固定)"message_state": 2, // 2=完成(固定)"context_token": "ctx_token_from_inbound_msg", // 必填!会话关联 Token"item_list": [{ "type": 1, "text_item": { "text": "AI 的回复内容" } }]},"base_info": { "channel_version": "1.0.2" }}
4.3 媒体消息请求体
// 图片消息 item (type=2){"type": 2,"image_item": {"media": {"encrypt_query_param": "CDN下载参数","aes_key": "base64编码的AES密钥","encrypt_type": 1},"mid_size": 102400 // 密文大小(字节)}}// 视频消息 item (type=5){ "type": 5, "video_item": { "media": {...}, "video_size": 5120000 } }// 文件附件 item (type=4){ "type": 4, "file_item": { "media": {...}, "file_name": "report.pdf", "len": "204800" } }
4.4 关键字段说明
|
字段 |
类型 |
说明 |
|
msg.from_user_id |
string |
Bot 发送时固定为空字符串 |
|
msg.to_user_id |
string |
目标用户 ID(如 xxx@im.wechat) |
|
msg.client_id |
string |
唯一ID:openclaw-weixin:{ts}-{8hex} |
|
msg.message_type |
number |
1=用户消息,2=Bot消息(固定2) |
|
msg.message_state |
number |
0=新建,1=生成中,2=完成(固定2) |
|
msg.context_token |
string |
必填!从入站消息回传,关联会话 |
|
item_list[].type |
number |
1=文字 2=图片 3=语音 4=文件 5=视频 |
⚠ 注意:context_token 仅存内存 Map,进程重启后丢失——重启后需等到用户发消息才能恢复回复能力。
5. 媒体文件接口:CDN 加密上传/下载
5.1 CDN 加密上传流程

图5:CDN 加密上传流程
5.2 getUploadUrl 接口
端点:POST https://ilinkai.weixin.qq.com/ilink/bot/getuploadurl
|
字段 |
类型 |
说明 |
|
filekey |
string |
32位随机 hex,文件唯一标识 |
|
media_type |
number |
1=图片 2=视频 3=文件 4=语音 |
|
to_user_id |
string |
接收方用户 ID |
|
rawsize |
number |
明文文件字节数 |
|
rawfilemd5 |
string |
明文文件 MD5 hex |
|
filesize |
number |
密文字节数(AES-128-ECB 含 PKCS7) |
|
no_need_thumb |
boolean |
true 跳过缩略图上传 URL |
|
aeskey |
string |
16字节 AES key 的 hex 字符串 |
5.3 AES-128-ECB 加密规格
算法:AES-128-ECB(无 IV)
填充:PKCS7(Node.js crypto 默认)
密钥:每次上传随机生成 16 字节 (crypto.randomBytes(16))
密文大小:ceil((plaintext_size + 1) / 16) * 16
加密:createCipheriv(“aes-128-ecb”, key, null)
解密:createDecipheriv(“aes-128-ecb”, key, null)
5.4 CDN 加密下载流程

图6:CDN 加密下载解密流程
6. 配置与打字状态接口
6.1 getConfig 接口
端点:POST https://ilinkai.weixin.qq.com/ilink/bot/getconfig
// 请求体
{
“ilink_user_id”:“user123@im.wechat”,
“context_token”:“ctx_token”,
“base_info”:{ “channel_version”: “1.0.2” }
}
// 响应体
{ “ret”: 0, “errmsg”: “”, “typing_ticket”: “base64编码的打字凭证…” }
缓存策略:
|
场景 |
行为 |
|
缓存命中且未过期 |
直接返回 typingTicket,不发请求 |
|
缓存未命中/已过期 |
调用 getConfig API |
|
API 成功 |
缓存 TTL = 随机(0 ~ 24h),重置 retryDelay=2s |
|
API 失败 |
retryDelay 指数退避,上限 60min |
6.2 sendTyping 接口
端点:POST https://ilinkai.weixin.qq.com/ilink/bot/sendtyping
{
“ilink_user_id”:“user123@im.wechat”,
“typing_ticket”:“base64编码的凭证”,
“status”:1,// 1=正在输入, 2=取消输入状态
“base_info”:{ “channel_version”: “1.0.2” }
}
7. 通信协议细节:请求头、错误码、重试机制
7.1 超时设置
|
接口类型 |
超时时间 |
说明 |
|
getUpdates |
35,000ms |
长轮询,超时视为正常(无消息),继续下一次 |
|
get_qrcode_status |
35,000ms |
长轮询,超时返回 { status: “wait” } |
|
sendMessage / getUploadUrl |
15,000ms |
普通 API |
|
getConfig / sendTyping |
10,000ms |
轻量 API |
7.2 错误码
|
错误码 |
含义 |
处理策略 |
|
0 |
成功 |
正常处理 |
|
-14 |
Session 过期 |
pauseSession() 暂停 60 分钟 |
|
其他非0 |
API 错误 |
计数累加,连续 3 次退避 30s |
|
HTTP 4xx |
CDN 客户端错误 |
立即失败,不重试 |
|
HTTP 5xx |
CDN 服务器错误 |
最多重试 3 次 |
7.3 重试策略总结
getUpdates:第1,2次失败→等2s;第3次→退避30s→重置计数
Session过期(errcode=-14):冷却60min,所有API请求前检查
getConfig失败退避:2s→4s→8s→…→上限60min
CDN上传:HTTP 5xx最多重试3次;HTTP 4xx立即失败
8. 数据模型完整字段表
8.1 WeixinMessage(消息主体)
interface WeixinMessage {seq?: number; // 消息序号message_id?: number; // 消息 IDfrom_user_id?: string; // 发送方 ID,格式 xxx@im.wechatto_user_id?: string; // 接收方 IDclient_id?: string; // 客户端唯一 IDcreate_time_ms?: number; // 创建时间戳(毫秒)update_time_ms?: number; // 更新时间戳(毫秒)delete_time_ms?: number; // 删除时间戳(撤回消息)session_id?: string; // 会话 IDgroup_id?: string; // 群组 ID(仅群聊)message_type?: number; // 1=用户消息,2=Bot消息message_state?: number; // 0=新建,1=生成中,2=完成item_list?: MessageItem[]; // 消息内容列表context_token?: string; // 会话关联 Token(回复时必须带上)}
8.2 MessageItem 类型枚举
|
type 值 |
类型 |
对应字段 |
说明 |
|
1 |
TEXT |
text_item.text |
纯文本 |
|
2 |
IMAGE |
image_item.media / aeskey |
图片,含 CDN 引用和 AES key |
|
3 |
VOICE |
voice_item.media / text |
语音,含 STT 转文字结果 |
|
4 |
FILE |
file_item.media / file_name / len |
文件附件 |
|
5 |
VIDEO |
video_item.media / video_size |
视频 |
8.3 CDNMedia(CDN 媒体引用)
{encrypt_query_param?: string; // CDN 下载参数(含认证信息)aes_key?: string; // base64 编码的 AES 密钥encrypt_type?: number; // 0=只加密fileid,1=打包缩略图等信息}
8.4 语音编码类型(VoiceItem.encode_type)
|
encode_type |
编码格式 |
|
1 |
PCM |
|
2 |
ADPCM |
|
4 |
Speex |
|
5 |
AMR |
|
6 |
Silk(微信私有格式) |
|
7 |
MP3 |
|
8 |
OGG-Speex |
9. Session 生命周期管理

图7:Session 生命周期与 Context Token 管理
⚠ 注意:context_token 存于纯内存 Map,进程重启后丢失。生产环境建议持久化到 Redis(TTL 24h)。
10. 消息处理内部管道

图8:入站消息完整处理管道
10.2 消息类型优先级
当 item_list 包含多种媒体类型时(罕见),处理优先级:
图片(type=2) > 视频(type=5) > 文件(type=4) > 语音(type=3, 文字回退)
11. 如何剥离 OpenClaw 实现通用消息通知系统
11.1 核心洞察
当前代码的 OpenClaw 依赖仅集中在 3 个接触点,其余 90% 代码与框架完全无关:
openclaw/plugin-sdk 依赖点:
① channelRuntime.dispatchReplyFromConfig(ctx)— AI 处理入站消息
② channelRuntime.recordInboundSession(ctx)— 记录会话
③ stripMarkdown()— Markdown 转纯文本工具
11.2 通用消息通知系统架构

图9:剥离 OpenClaw 后的通用消息通知系统
11.3 生产级部署架构

图10:生产级微信通知系统部署架构
11.4 自定义应用消息测试

https://github.com/yindex/wx-mcp
夜雨聆风