# 企业微信回调配置与联调说明 ## 一、企业微信后台配置 ### 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 ``` **处理流程**: 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 时间戳 ``` --- ## 四、加解密说明 ### 安全模式(推荐) - **加密算法**: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 ### 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 检索 - 实现工单转人工流程