Initial commit: 浼佷笟寰俊 AI 鏈哄櫒浜哄姪鐞?MVP

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
bujie9527
2026-02-05 16:36:32 +08:00
commit 59275ed4dc
126 changed files with 9120 additions and 0 deletions

View File

@@ -0,0 +1,415 @@
# 云端最小回调壳部署方案
## 一、目标
**阶段目标**:在备案域名上部署最小可用回调壳,使企业微信能完成 URL 校验与回调联调。
**最小功能范围**
-`/api/wecom/callback` GET 校验(兼容 `signature`/`msg_signature`
-`/api/wecom/callback` POST 密文消息回调验签、解密、echo 回复)
- ✅ 结构化日志 + trace_id
- ✅ Nginx 反代 + HTTPSLet's Encrypt
- ⏸️ 数据库(可先不启用,但接口与配置要预留)
- ⏸️ Admin 后台(可先占位)
---
## 二、架构
```
企业微信 → HTTPS (443) → Nginx → Backend (8000)
PostgreSQL (可选)
```
**服务清单**
- `backend`: Python 3.12 + FastAPI + Uvicorn最小回调壳
- `nginx`: 反代 + HTTPSLet's Encrypt
- `db`: PostgreSQL 16可选先不启用
---
## 三、环境变量配置
### 3.1 必需变量(`.env`
```bash
# ============ Backend ============
API_HOST=0.0.0.0
API_PORT=8000
# Database可选先不启用
DATABASE_URL=postgresql+asyncpg://wecom:wecom_secret@db:5432/wecom_ai
DATABASE_URL_SYNC=postgresql://wecom:wecom_secret@db:5432/wecom_ai
# JWTadmin 登录,可选)
JWT_SECRET=your-jwt-secret-change-in-production
JWT_ALGORITHM=HS256
JWT_EXPIRE_MINUTES=60
# WeCom Callback必须从企业微信管理后台获取
WECOM_CORP_ID=你的企业ID
WECOM_AGENT_ID=你的应用AgentId
WECOM_SECRET=你的应用Secret可选用于主动发送消息
WECOM_TOKEN=你的Token必须与企微后台一致
WECOM_ENCODING_AES_KEY=你的43位密钥必须与企微后台一致
# WeCom API
WECOM_API_BASE=https://qyapi.weixin.qq.com
WECOM_API_TIMEOUT=10
WECOM_API_RETRIES=2
# Log
LOG_LEVEL=INFO
LOG_JSON=true
# ============ Nginx ============
# 域名(必须,备案域名)
DOMAIN=your-domain.com
# SSLLet's Encrypt
SSL_EMAIL=your-email@example.com
```
### 3.2 关键变量说明
| 变量 | 说明 | 来源 |
|------|------|------|
| `WECOM_TOKEN` | 企业微信回调 Token | 企微后台 → 应用 → 接收消息 → Token |
| `WECOM_ENCODING_AES_KEY` | 43 位 Base64 编码密钥 | 企微后台 → 应用 → 接收消息 → EncodingAESKey |
| `WECOM_CORP_ID` | 企业 ID | 企微后台 → 我的企业 → 企业信息 |
| `WECOM_AGENT_ID` | 应用 AgentId | 企微后台 → 应用管理 → 自建应用 → 应用详情 |
| `DOMAIN` | 备案域名 | 你的域名服务商 |
---
## 四、部署步骤
### 4.1 前置条件
1. **备案域名**:已备案且主体关联的域名(例如:`api.yourdomain.com`
2. **服务器**LinuxUbuntu 20.04+ / CentOS 7+),公网 IP开放 80/443 端口
3. **Docker**:已安装 Docker 和 docker-compose
4. **GitHub**:代码已推送到 GitHub用于 CI/CD
### 4.2 服务器初始化
```bash
# 1. 安装 Docker 和 docker-compose
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# 2. 克隆项目(或通过 CI/CD 部署)
git clone https://github.com/your-org/wecom-ai-assistant.git
cd wecom-ai-assistant
# 3. 创建 .env 文件
cp .env.example .env
# 编辑 .env填入上述必需变量
```
### 4.3 配置 Nginx + HTTPS
#### 方案 A使用 CertbotLet's Encrypt
```bash
# 1. 安装 Certbot
sudo apt-get update
sudo apt-get install certbot python3-certbot-nginx
# 2. 先启动 HTTP 服务(用于验证)
docker-compose up -d backend
# 3. 配置 Nginx临时 HTTP 配置)
# 编辑 deploy/nginx.conf添加 server_name
# 然后运行docker-compose up -d nginx
# 4. 获取 SSL 证书
sudo certbot --nginx -d your-domain.com -d www.your-domain.com --email your-email@example.com --agree-tos --non-interactive
# 5. 更新 nginx.conf使用 Certbot 生成的配置
# Certbot 会自动修改 /etc/nginx/sites-available/default
# 将配置复制到 deploy/nginx.conf或使用 volume 挂载
```
#### 方案 B手动配置 Nginx + Let's Encrypt
创建 `deploy/nginx-ssl.conf`
```nginx
events { worker_connections 1024; }
http {
upstream backend {
server backend:8000;
}
# HTTP → HTTPS 重定向
server {
listen 80;
server_name your-domain.com www.your-domain.com;
return 301 https://$server_name$request_uri;
}
# HTTPS
server {
listen 443 ssl http2;
server_name your-domain.com www.your-domain.com;
# SSL 证书Let's Encrypt
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# /api -> backend
location /api/ {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 30s;
}
# 健康检查
location /health {
proxy_pass http://backend/health;
access_log off;
}
}
}
```
更新 `docker-compose.yml`
```yaml
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./deploy/nginx-ssl.conf:/etc/nginx/nginx.conf:ro
- /etc/letsencrypt:/etc/letsencrypt:ro # SSL 证书
depends_on:
- backend
```
### 4.4 启动服务
```bash
# 1. 构建镜像
docker-compose build backend
# 2. 启动服务(最小回调壳:只启动 backend + nginx
docker-compose up -d backend nginx
# 3. 检查日志
docker-compose logs -f backend
```
### 4.5 验证服务
```bash
# 1. 检查服务状态
docker-compose ps
# 2. 检查健康检查
curl https://your-domain.com/health
# 3. 检查回调接口(应返回 400因为缺少参数
curl https://your-domain.com/api/wecom/callback
```
---
## 五、本地验证
### 5.1 本地启动最小回调壳
```bash
# 1. 启动后端(不启动 db/admin
docker-compose up -d backend
# 2. 检查日志
docker-compose logs backend
# 3. 测试 GET 校验(模拟企业微信)
# 注意:需要正确的 signature/timestamp/nonce/echostr
curl "http://localhost:8000/api/wecom/callback?signature=xxx&timestamp=123&nonce=abc&echostr=xxx"
```
### 5.2 本地测试 POST 回调
```bash
# 使用企业微信官方测试工具生成测试请求
# 或使用 curl 模拟(需要正确的签名和加密)
curl -X POST "http://localhost:8000/api/wecom/callback?msg_signature=xxx&timestamp=123&nonce=abc" \
-H "Content-Type: application/xml" \
-d '<xml><Encrypt><![CDATA[加密内容]]></Encrypt></xml>'
```
### 5.3 验证日志格式
检查日志输出是否符合结构化日志格式:
```json
{
"timestamp": "2025-02-05T10:00:00Z",
"level": "INFO",
"message": "wecom verify success",
"trace_id": "abc123",
"echostr_length": 43
}
```
---
## 六、线上验证
### 6.1 企业微信后台配置
1. **登录企业微信管理后台**https://work.weixin.qq.com
2. **进入应用设置**:应用管理 → 自建应用 → 选择你的应用
3. **配置回调 URL**
- 接收消息服务器 URL`https://your-domain.com/api/wecom/callback`
- Token`.env` 中的 `WECOM_TOKEN` **完全一致**
- EncodingAESKey`.env` 中的 `WECOM_ENCODING_AES_KEY` **完全一致**
- 消息加解密方式:**安全模式**
4. **点击保存**
### 6.2 验证 GET 校验
保存后,企业微信会立即发送 GET 请求验证。观察后端日志:
```bash
docker-compose logs -f backend
```
**成功日志**
```
INFO: wecom verify success {"trace_id": "...", "echostr_length": 43}
```
**失败日志**
```
WARNING: wecom verify failed {"trace_id": "...", "timestamp": "...", "nonce": "..."}
```
如果验证失败,检查:
- Token 是否一致
- EncodingAESKey 是否一致
- 域名是否可访问(`curl https://your-domain.com/api/wecom/callback`
### 6.3 验证 POST 回调
1. **在企业微信中发送测试消息**
- 打开企业微信客户端
- 找到你配置的应用
- 发送文本消息:`你好,测试一下`
2. **观察后端日志**
```bash
docker-compose logs -f backend
```
**成功日志**
```json
{
"timestamp": "2025-02-05T10:00:00Z",
"level": "INFO",
"message": "wecom message received",
"trace_id": "abc123",
"external_userid": "external_userid_xxx",
"msgid": "123456",
"msg_type": "text",
"content_summary": "你好,测试一下"
}
```
```json
{
"timestamp": "2025-02-05T10:00:01Z",
"level": "INFO",
"message": "wecom reply sent",
"trace_id": "abc123",
"external_userid": "external_userid_xxx",
"msgid": "123456",
"reply_summary": "已收到:你好,测试一下"
}
```
3. **检查企业微信客户端**:应收到回复:`已收到:你好,测试一下`
---
## 七、常见问题
### 7.1 GET 校验失败
**原因**
- Token 不一致
- EncodingAESKey 不一致
- 签名算法错误
**解决**
1. 检查 `.env` 中的 `WECOM_TOKEN``WECOM_ENCODING_AES_KEY`
2. 确保与企微后台配置**完全一致**(包括大小写、空格)
3. 重启后端:`docker-compose restart backend`
### 7.2 POST 回调失败
**原因**
- 签名验证失败
- 解密失败
- XML 解析失败
**解决**
1. 检查日志中的错误信息
2. 确认 EncodingAESKey 正确
3. 确认消息加解密方式为**安全模式**
### 7.3 HTTPS 证书问题
**原因**
- Let's Encrypt 证书未正确配置
- 证书过期
**解决**
1. 检查证书:`sudo certbot certificates`
2. 续期证书:`sudo certbot renew`
3. 重启 Nginx`docker-compose restart nginx`
### 7.4 域名无法访问
**原因**
- DNS 未解析
- 防火墙未开放 80/443 端口
- Nginx 配置错误
**解决**
1. 检查 DNS`nslookup your-domain.com`
2. 检查端口:`netstat -tlnp | grep -E '80|443'`
3. 检查 Nginx 日志:`docker-compose logs nginx`
---
## 八、下一步
完成最小回调壳部署后,按以下顺序逐步接入:
1.**最小回调壳**(当前阶段)
2. ⏭️ **数据库接入**(会话与消息入库)
3. ⏭️ **Admin 后台**(会话列表、工单、知识库)
4. ⏭️ **FAQ/RAG**(智能回复)
---
## 九、参考文档
- [企业微信回调配置](./wecom.md)
- [企业微信测试指南](./wecom-test-guide.md)
- [GitHub Actions CI/CD](../deploy/ci/github-actions.yml)