title: 企微 Webhook Relay 本地 Skill 接入指南 updated: 2026-07-27 project: claude-code-qiwe-assistant
本地 Skill 不暴露 Webhook 端口。企微事件先进入中央 Relay,本地通过长轮询领取属于当前租户和设备的事件。
企微消息
-> Token 级全局回调 /api/webhook/ingest
-> Relay 按消息体真实 guid 找到租户
-> 加密、去重并进入租户队列
-> 本地 Relay Client 长轮询
-> 解密、落盘、业务处理并 ACK
企微上游的回调配置对服务 Token 全局生效,不是每个客户或设备一条。因此回调地址固定为:
{RELAY_BASE_URL}/api/webhook/ingest
不要把回调设置成 /api/webhook/ingest/{tenantId}/{guid}。最后一次设置会覆盖此前客户,造成消息错投或中断。
guid 注册到该租户。Skill 调用 Fmode 专用接口:
POST {QIWEI_API_BASE}/relay/connect
Authorization: Bearer <Fmode Token>
Content-Type: application/json
{"uid":"本地设备 uid"}
Fmode 服务端校验订阅和设备后,使用服务端保存的回调地址与签名密钥调用企微 /client/setCallback。
MCP/Skill 自动确保本地 Relay 消费守护进程运行;无需启动 Dashboard。手工诊断时仍可执行:
npm run relay
客户端请求中只能出现 uid,不能提交任意回调 URL、签名密钥、上游 Token 或设备 guid。
Future Server 需要由运维设置以下环境变量:
QIWEI_RELAY_CALLBACK_URL=http://8.138.37.248:4000/api/webhook/ingest
QIWEI_RELAY_CALLBACK_SECRET=<服务端全局回调签名密钥>
签名密钥只保存在 Future Server 和 Relay 服务端,不能进入 Skill、浏览器、npm 包、日志或客户配置文件。
本地 Relay Client 只保存本租户的领取和解密凭据:
RELAY_BASE_URL
TENANT_ID
TENANT_API_KEY
TENANT_API_SECRET
RELAY_PRIVATE_KEY
RELAY_DEVICE_GUID
这些内容写入 .env.local,不得提交 Git 或打进 npm 包。RELAY_PRIVATE_KEY 使用 \n 表示 PEM 换行。
qiwei_webhook_status 显示 relayRunning=true;默认服务端队列保留 7 天,处理成功后才 ACK。guid 路由。历史消息不通过回调补采,产品口径为“从接入完成后开始接收”。
| 现象 | 检查项 |
|---|---|
/relay/connect 返回未配置 |
Future Server 是否设置两项 Relay 环境变量并重启 |
| Relay 收到消息但本地没有 | 设备 guid 是否属于当前租户,Relay Client 是否在线 |
| 本地能 poll 但不能解密 | 本地私钥是否属于当前租户,PEM 换行是否正确 |
| 消息进入错误客户会话 | 检查事件真实 guid、会话 ID 和群/私聊类型,禁止按当前页面会话兜底 |
| 回调突然中断 | 排查是否有个人进程再次调用 /client/setCallback 覆盖全局地址 |
客户自有服务器的独立服务 Token 可以使用自定义回调,但必须显式开启:
QIWEI_ALLOW_DIRECT_CALLBACK=true
共享 Token 环境禁止开启。默认关闭是为了避免个人版或本地测试覆盖企业版全局回调。