7.6 KiB
7.6 KiB
企业微信回调配置与联调说明
一、企业微信后台配置
1. 获取必要参数
在企业微信管理后台(https://work.weixin.qq.com)获取以下参数:
| 参数 | 获取位置 | 说明 |
|---|---|---|
| 企业 ID (CorpId) | 我的企业 → 企业信息 | 企业唯一标识 |
| Token | 自建应用 → 接收消息 → 设置 | 自定义字符串,用于签名校验 |
| EncodingAESKey | 自建应用 → 接收消息 → 设置 | 43 位 Base64 编码的 AES 密钥(自动生成或手动输入) |
| AgentId | 自建应用 → 应用详情 | 应用 ID |
| Secret | 自建应用 → 应用详情 | 应用密钥(用于主动发送消息,当前阶段可选) |
2. 配置回调 URL
- 进入 自建应用 → 选择你的应用 → 接收消息
- 点击 设置 API 接收
- 填写以下信息:
- 接收消息服务器 URL:
https://你的域名/api/wecom/callback - Token:填写你自定义的 Token(需与
.env中的WECOM_TOKEN一致) - EncodingAESKey:填写 43 位密钥(需与
.env中的WECOM_ENCODING_AES_KEY一致) - 消息加解密方式:选择 安全模式(推荐)或 明文模式(仅用于测试)
- 接收消息服务器 URL:
3. 保存配置
点击 保存 后,企业微信会立即发送 GET 请求到你的回调 URL 进行校验。如果配置正确,会显示 保存成功。
二、本地环境变量配置
在 .env 文件中配置以下变量:
# 企业微信配置
WECOM_CORP_ID=你的企业ID
WECOM_AGENT_ID=你的应用AgentId
WECOM_SECRET=你的应用Secret(可选,当前阶段用于主动发送消息)
WECOM_TOKEN=你的Token(需与企微后台一致)
WECOM_ENCODING_AES_KEY=你的43位EncodingAESKey(需与企微后台一致)
WECOM_API_BASE=https://qyapi.weixin.qq.com
WECOM_API_TIMEOUT=10
WECOM_API_RETRIES=2
重要:
WECOM_TOKEN和WECOM_ENCODING_AES_KEY必须与企微后台配置完全一致WECOM_CORP_ID用于加密回复时验证企业身份
三、回调机制说明
GET 请求(URL 校验)
企业微信在保存配置时会发送 GET 请求:
GET /api/wecom/callback?msg_signature=xxx×tamp=xxx&nonce=xxx&echostr=xxx
处理流程:
- 使用
msg_signature、timestamp、nonce、echostr验签 - 解密
echostr得到明文 - 将明文原样返回
成功响应:返回解密后的 echostr 明文(纯文本)
POST 请求(消息回调)
客户发送消息时,企业微信会发送 POST 请求:
POST /api/wecom/callback?msg_signature=xxx×tamp=xxx&nonce=xxx
Content-Type: application/xml
<xml>
<Encrypt><![CDATA[加密后的消息]]></Encrypt>
</xml>
处理流程:
- 解析 XML,提取
Encrypt节点 - 使用
msg_signature、timestamp、nonce、Encrypt验签 - 解密
Encrypt得到消息 XML - 解析消息(
MsgType、Content、FromUserName、MsgId等) - 记录日志(trace_id + external_userid + msgid + 内容摘要)
- 创建/更新会话,保存消息到数据库
- 构造回复 XML(当前为 echo:
已收到:{用户消息}) - 加密回复 XML
- 返回加密后的 XML 响应
成功响应:返回加密后的 XML(被动回复)
<xml>
<Encrypt><![CDATA[加密后的回复]]></Encrypt>
<MsgSignature><![CDATA[签名]]></MsgSignature>
<TimeStamp>时间戳</TimeStamp>
<Nonce><![CDATA[随机字符串]]></Nonce>
</xml>
四、加解密说明
安全模式(推荐)
- 加密算法:AES-256-CBC
- 填充方式:PKCS7
- 签名算法:SHA1
加密格式:
[16字节随机数][4字节消息长度][消息内容][企业ID][PKCS7填充]
解密流程:
- Base64 解码
- AES-CBC 解密
- 提取消息长度(第 16-20 字节)
- 按长度提取消息内容
- 验证尾部企业 ID
明文模式(仅测试)
如果选择明文模式,企业微信会直接发送未加密的 XML,但不推荐用于生产环境。
切换到明文模式:
- 在企微后台将 消息加解密方式 改为 明文模式
- 代码中需要修改
wecom.py,跳过解密步骤,直接解析 XML(当前实现仅支持安全模式)
五、本地联调测试
1. 启动服务
# 确保后端服务运行
docker compose up -d backend
# 查看日志
docker compose logs backend -f
2. 使用 curl 测试 GET 校验(模拟企微)
注意:实际测试需要真实的签名和加密数据。以下为示例格式:
# 需要先获取真实的签名和 echostr(从企微后台保存配置时的请求中获取)
curl -X GET "http://localhost:8000/api/wecom/callback?msg_signature=xxx×tamp=xxx&nonce=xxx&echostr=xxx"
预期响应:返回解密后的 echostr 明文
3. 使用 curl 测试 POST 回调(模拟企微)
注意:需要真实的加密 XML。可以从企微后台的实际回调请求中获取,或使用企业微信官方测试工具。
# 示例格式(需要替换为真实的加密 XML)
curl -X POST "http://localhost:8000/api/wecom/callback?msg_signature=xxx×tamp=xxx&nonce=xxx" \
-H "Content-Type: application/xml" \
-d '<xml><Encrypt><![CDATA[加密后的消息XML]]></Encrypt></xml>'
预期响应:返回加密后的回复 XML
4. 真实环境测试
- 配置回调 URL:将你的公网域名配置到企微后台(如使用 ngrok 等工具暴露本地服务)
- 保存配置:在企微后台点击保存,观察 GET 请求是否成功
- 发送测试消息:在企业微信中向应用发送一条文本消息
- 查看日志:检查后端日志,应看到:
INFO: wecom message received {"trace_id": "...", "external_userid": "...", "msgid": "...", "content_summary": "..."} INFO: wecom reply sent {"trace_id": "...", "external_userid": "...", "msgid": "...", "reply_summary": "..."} - 验证回复:在企业微信中应收到回复消息:
已收到:{你发送的消息}
六、日志格式
所有回调请求都会记录结构化日志,包含以下字段:
- trace_id:请求追踪 ID
- external_userid:外部用户 ID(客户 ID)
- msgid:消息 ID
- msg_type:消息类型(text/image/event 等)
- content_summary:消息内容摘要(前 50 字符)
- reply_summary:回复内容摘要(前 50 字符)
示例日志:
{
"timestamp": "2025-02-05T10:00:00Z",
"level": "INFO",
"message": "wecom message received",
"trace_id": "abc123",
"external_userid": "wmxxxxx",
"msgid": "1234567890",
"msg_type": "text",
"content_summary": "你好,我想咨询一下产品信息..."
}
七、常见问题
1. GET 校验失败
- 检查 Token:确保
.env中的WECOM_TOKEN与企微后台一致 - 检查 EncodingAESKey:确保
.env中的WECOM_ENCODING_AES_KEY与企微后台一致(43 位,不含等号) - 检查 URL:确保回调 URL 可公网访问
2. POST 回调失败
- 检查签名:确保
msg_signature校验通过 - 检查解密:确保
WECOM_ENCODING_AES_KEY正确 - 检查企业 ID:确保
WECOM_CORP_ID正确(用于验证解密后的企业 ID)
3. 回复未收到
- 检查日志:查看是否有错误日志
- 检查数据库:确认消息是否已入库
- 检查 XML 格式:确保回复 XML 格式正确
- 检查加密:确保回复加密正确
八、下一步(阶段 5+)
- 接入企业微信主动发送消息 API(需要
WECOM_SECRET获取 access_token) - 实现 FAQ 匹配和 RAG 检索
- 实现工单转人工流程