Initial commit: 浼佷笟寰俊 AI 鏈哄櫒浜哄姪鐞?MVP
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
243
docs/wecom.md
Normal file
243
docs/wecom.md
Normal file
@@ -0,0 +1,243 @@
|
||||
# 企业微信回调配置与联调说明
|
||||
|
||||
## 一、企业微信后台配置
|
||||
|
||||
### 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×tamp=xxx&nonce=xxx&echostr=xxx
|
||||
```
|
||||
|
||||
**处理流程**:
|
||||
1. 使用 `msg_signature`、`timestamp`、`nonce`、`echostr` 验签
|
||||
2. 解密 `echostr` 得到明文
|
||||
3. 将明文原样返回
|
||||
|
||||
**成功响应**:返回解密后的 `echostr` 明文(纯文本)
|
||||
|
||||
### POST 请求(消息回调)
|
||||
|
||||
客户发送消息时,企业微信会发送 POST 请求:
|
||||
|
||||
```
|
||||
POST /api/wecom/callback?msg_signature=xxx×tamp=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×tamp=xxx&nonce=xxx&echostr=xxx"
|
||||
```
|
||||
|
||||
**预期响应**:返回解密后的 `echostr` 明文
|
||||
|
||||
### 3. 使用 curl 测试 POST 回调(模拟企微)
|
||||
|
||||
**注意**:需要真实的加密 XML。可以从企微后台的实际回调请求中获取,或使用企业微信官方测试工具。
|
||||
|
||||
```bash
|
||||
# 示例格式(需要替换为真实的加密 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. 真实环境测试
|
||||
|
||||
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 检索
|
||||
- 实现工单转人工流程
|
||||
Reference in New Issue
Block a user