Files
wecom-ai-assistant/docs/wecom.md
2026-02-05 16:36:32 +08:00

244 lines
7.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 企业微信回调配置与联调说明
## 一、企业微信后台配置
### 1. 获取必要参数
在企业微信管理后台https://work.weixin.qq.com获取以下参数
| 参数 | 获取位置 | 说明 |
|------|---------|------|
| **企业 ID (CorpId)** | 我的企业 → 企业信息 | 企业唯一标识 |
| **Token** | 自建应用 → 接收消息 → 设置 | 自定义字符串,用于签名校验 |
| **EncodingAESKey** | 自建应用 → 接收消息 → 设置 | 43 位 Base64 编码的 AES 密钥(自动生成或手动输入) |
| **AgentId** | 自建应用 → 应用详情 | 应用 ID |
| **Secret** | 自建应用 → 应用详情 | 应用密钥(用于主动发送消息,当前阶段可选) |
### 2. 配置回调 URL
1. 进入 **自建应用** → 选择你的应用 → **接收消息**
2. 点击 **设置 API 接收**
3. 填写以下信息:
- **接收消息服务器 URL**`https://你的域名/api/wecom/callback`
- **Token**:填写你自定义的 Token需与 `.env` 中的 `WECOM_TOKEN` 一致)
- **EncodingAESKey**:填写 43 位密钥(需与 `.env` 中的 `WECOM_ENCODING_AES_KEY` 一致)
- **消息加解密方式**:选择 **安全模式**(推荐)或 **明文模式**(仅用于测试)
### 3. 保存配置
点击 **保存** 后,企业微信会立即发送 GET 请求到你的回调 URL 进行校验。如果配置正确,会显示 **保存成功**
---
## 二、本地环境变量配置
`.env` 文件中配置以下变量:
```bash
# 企业微信配置
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&timestamp=xxx&nonce=xxx&echostr=xxx
```
**处理流程**
1. 使用 `msg_signature``timestamp``nonce``echostr` 验签
2. 解密 `echostr` 得到明文
3. 将明文原样返回
**成功响应**:返回解密后的 `echostr` 明文(纯文本)
### POST 请求(消息回调)
客户发送消息时,企业微信会发送 POST 请求:
```
POST /api/wecom/callback?msg_signature=xxx&timestamp=xxx&nonce=xxx
Content-Type: application/xml
<xml>
<Encrypt><![CDATA[加密后的消息]]></Encrypt>
</xml>
```
**处理流程**
1. 解析 XML提取 `Encrypt` 节点
2. 使用 `msg_signature``timestamp``nonce``Encrypt` 验签
3. 解密 `Encrypt` 得到消息 XML
4. 解析消息(`MsgType``Content``FromUserName``MsgId` 等)
5. 记录日志trace_id + external_userid + msgid + 内容摘要)
6. 创建/更新会话,保存消息到数据库
7. 构造回复 XML当前为 echo`已收到:{用户消息}`
8. 加密回复 XML
9. 返回加密后的 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填充]
```
**解密流程**
1. Base64 解码
2. AES-CBC 解密
3. 提取消息长度(第 16-20 字节)
4. 按长度提取消息内容
5. 验证尾部企业 ID
### 明文模式(仅测试)
如果选择明文模式,企业微信会直接发送未加密的 XML但**不推荐用于生产环境**。
**切换到明文模式**
1. 在企微后台将 **消息加解密方式** 改为 **明文模式**
2. 代码中需要修改 `wecom.py`,跳过解密步骤,直接解析 XML当前实现仅支持安全模式
---
## 五、本地联调测试
### 1. 启动服务
```bash
# 确保后端服务运行
docker compose up -d backend
# 查看日志
docker compose logs backend -f
```
### 2. 使用 curl 测试 GET 校验(模拟企微)
**注意**:实际测试需要真实的签名和加密数据。以下为示例格式:
```bash
# 需要先获取真实的签名和 echostr从企微后台保存配置时的请求中获取
curl -X GET "http://localhost:8000/api/wecom/callback?msg_signature=xxx&timestamp=xxx&nonce=xxx&echostr=xxx"
```
**预期响应**:返回解密后的 `echostr` 明文
### 3. 使用 curl 测试 POST 回调(模拟企微)
**注意**:需要真实的加密 XML。可以从企微后台的实际回调请求中获取或使用企业微信官方测试工具。
```bash
# 示例格式(需要替换为真实的加密 XML
curl -X POST "http://localhost:8000/api/wecom/callback?msg_signature=xxx&timestamp=xxx&nonce=xxx" \
-H "Content-Type: application/xml" \
-d '<xml><Encrypt><![CDATA[加密后的消息XML]]></Encrypt></xml>'
```
**预期响应**:返回加密后的回复 XML
### 4. 真实环境测试
1. **配置回调 URL**:将你的公网域名配置到企微后台(如使用 ngrok 等工具暴露本地服务)
2. **保存配置**:在企微后台点击保存,观察 GET 请求是否成功
3. **发送测试消息**:在企业微信中向应用发送一条文本消息
4. **查看日志**:检查后端日志,应看到:
```
INFO: wecom message received {"trace_id": "...", "external_userid": "...", "msgid": "...", "content_summary": "..."}
INFO: wecom reply sent {"trace_id": "...", "external_userid": "...", "msgid": "...", "reply_summary": "..."}
```
5. **验证回复**:在企业微信中应收到回复消息:`已收到:{你发送的消息}`
---
## 六、日志格式
所有回调请求都会记录结构化日志,包含以下字段:
- **trace_id**:请求追踪 ID
- **external_userid**:外部用户 ID客户 ID
- **msgid**:消息 ID
- **msg_type**消息类型text/image/event 等)
- **content_summary**:消息内容摘要(前 50 字符)
- **reply_summary**:回复内容摘要(前 50 字符)
**示例日志**
```json
{
"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 检索
- 实现工单转人工流程