Initial commit: 浼佷笟寰俊 AI 鏈哄櫒浜哄姪鐞?MVP
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
415
docs/deploy-cloud-minimal.md
Normal file
415
docs/deploy-cloud-minimal.md
Normal file
@@ -0,0 +1,415 @@
|
||||
# 云端最小回调壳部署方案
|
||||
|
||||
## 一、目标
|
||||
|
||||
**阶段目标**:在备案域名上部署最小可用回调壳,使企业微信能完成 URL 校验与回调联调。
|
||||
|
||||
**最小功能范围**:
|
||||
- ✅ `/api/wecom/callback` GET 校验(兼容 `signature`/`msg_signature`)
|
||||
- ✅ `/api/wecom/callback` POST 密文消息回调(验签、解密、echo 回复)
|
||||
- ✅ 结构化日志 + trace_id
|
||||
- ✅ Nginx 反代 + HTTPS(Let's Encrypt)
|
||||
- ⏸️ 数据库(可先不启用,但接口与配置要预留)
|
||||
- ⏸️ Admin 后台(可先占位)
|
||||
|
||||
---
|
||||
|
||||
## 二、架构
|
||||
|
||||
```
|
||||
企业微信 → HTTPS (443) → Nginx → Backend (8000)
|
||||
↓
|
||||
PostgreSQL (可选)
|
||||
```
|
||||
|
||||
**服务清单**:
|
||||
- `backend`: Python 3.12 + FastAPI + Uvicorn(最小回调壳)
|
||||
- `nginx`: 反代 + HTTPS(Let'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
|
||||
|
||||
# JWT(admin 登录,可选)
|
||||
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
|
||||
|
||||
# SSL(Let'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. **服务器**:Linux(Ubuntu 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:使用 Certbot(Let'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×tamp=123&nonce=abc&echostr=xxx"
|
||||
```
|
||||
|
||||
### 5.2 本地测试 POST 回调
|
||||
|
||||
```bash
|
||||
# 使用企业微信官方测试工具生成测试请求
|
||||
# 或使用 curl 模拟(需要正确的签名和加密)
|
||||
curl -X POST "http://localhost:8000/api/wecom/callback?msg_signature=xxx×tamp=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)
|
||||
Reference in New Issue
Block a user