Files
huihuiSquare/digital-avatar-app/docs/H5_PRODUCTION_DEPLOYMENT.md
T

6.0 KiB

数字分身 H5 生产接入与部署

1. 接入方式

生产会会在用户已登录后打开以下地址:

https://digital.99hui.com/#/avatar/manage?token=<encodeURIComponent(会会 access token)>

测试环境示例:

http://192.168.1.188:8099/#/avatar/manage?token=<encodeURIComponent(token)>

兼容参数位于域名查询串的形式,但生产统一使用上面的 hash 路由形式。必须对 token 调用 encodeURIComponent,不能拼接用户 ID 代替 token。

免登录流程如下:

  1. H5 在页面渲染前读取 token,立即通过 history.replaceState 从地址栏和浏览器历史中移除。
  2. H5 调用 POST /api/huihui/token/login,不会把会会 token 当作数字分身接口 token 直接使用。
  3. 后端通过会会生产接口 /im/box/netease 换取 BOXIM 凭证,再调用 BOXIM /user/self 校验用户身份。
  4. 后端以返回的 huihuiUserId 绑定本地用户,保存会会凭证供 BOXIM 接管功能使用,并签发本系统 app_token。
  5. 浏览器只保存 app_token 和非敏感用户资料。会会原始 token 不返回浏览器存储。
  6. token 无效、过期或上游校验失败时清除旧会话并进入登录页,不会沿用上一位用户的缓存身份。

2. 生产配置

后端 .env 至少配置以下内容,密钥由部署平台注入,禁止提交 Git:

HUIHUI_DEV_MOCK=false
HUIHUI_AUTH_BASE_URL=https://99hui.com/api/usercenter
HUIHUI_PLATFORM_BASE_URL=https://open.99hui.com/api
BOXIM_API_BASE_URL=https://im.99hui.com/api
HUIHUI_APP_ID=<production-app-id>
HUIHUI_ACCESS_ID=<production-access-id>
HUIHUI_ACCESS_SECRET=<production-access-secret>
HUIHUI_CLIENT_CODE=<production-client-code>
BOXIM_TIMEOUT_SECONDS=20
HUIHUI_PAYMENT_BASE_URL=https://open.99hui.com/api/payment-v3
HUIHUI_PAYMENT_CALLBACK_BASE_URL=https://digital.99hui.com
HUIHUI_PAYMENT_CALLBACK_SECRET=<至少32位随机密钥>
HUIHUI_PAYMENT_TIMEOUT_SECONDS=30

DATABASE_URL=sqlite:////data/avatar.db
UPLOAD_DIR=/data/uploads
CHAT_MODEL_CONFIG_URL=http://<huihuisquare-api>/api/ai-models/runtime/digital-avatar

如生产 AI 配置中心不可用,还应提供当前项目支持的 OPENAI_API_KEY、OPENAI_BASE_URL、CHAT_MODEL 等兜底配置。/data 必须挂载持久卷,数据库与知识库文件不可存放在容器临时层。

积分充值使用会会支付体系的 payment-v3/payment/pay,渠道值为 WECHAT / ALIPAY,端内支付场景为 APP,微信内 H5 使用 JSAPI。HUIHUI_PAYMENT_CALLBACK_SECRET 只用于为每笔订单生成 HMAC 回调签名,不会发送到前端或直接出现在回调地址中。支付回调确认状态成功且金额与套餐价格完全一致后才增加积分,重复回调不会重复到账。

3. 构建与发布

首次发布前备份数据:

BACKUP_DIR="backups/$(date +%Y%m%d-%H%M%S)"
mkdir -p "$BACKUP_DIR"
cp /srv/digital-avatar/data/avatar.db "$BACKUP_DIR/"
tar -C /srv/digital-avatar/data -czf "$BACKUP_DIR/uploads.tgz" uploads

在发布目录执行:

git fetch origin
git checkout <已验收的提交SHA>
cd digital-avatar-app
docker compose build --pull avatar-backend avatar-frontend
docker compose up -d avatar-backend avatar-frontend
docker compose ps
curl -fsS http://127.0.0.1:8099/api/health

生产编排应把示例中的测试端口改为内网暴露,由统一 HTTPS 网关接入。后端暂时使用 SQLite,必须保持单实例写入;若扩展为多后端实例,应先迁移到 PostgreSQL,并把延迟接管任务改为共享队列。

4. 网关要求

必须使用 HTTPS。同域部署时,H5 静态资源与 /api/ 由同一域名提供,可避免跨域和 Cookie/来源策略问题。Nginx 关键配置示例:

server_name digital.99hui.com;

location / {
    try_files $uri $uri/ /index.html;
}

location /api/ {
    proxy_pass http://avatar-backend:8000;
    proxy_http_version 1.1;
    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_buffering off;
    proxy_read_timeout 300s;
    client_max_body_size 20m;
}

proxy_buffering off 用于数字分身 SSE 流式吐字,client_max_body_size 用于知识库文件上传。网关和应用日志必须关闭完整 URL 查询参数记录,任何异常日志都不得输出 token、Authorization 或平台密钥。建议同时设置严格的 Referrer-Policy: no-referrer。

5. 发布验收

  1. 已登录会会用户通过带 token 链接打开后直接进入 /avatar/manage,不出现登录页或创建新账号页。
  2. 页面加载后地址栏中不再包含 token,刷新页面仍使用本地 app_token 正常访问。
  3. 后端用户绑定的是 BOXIM 返回的 huihuiUserId,不是 BOXIM 内部 id;原有数字分身、独立知识库和积分余额均存在。
  4. A、B 两个会会用户分别进入时只能看到各自的数字分身与知识库,不会继承上一用户缓存。
  5. 使用过期或伪造 token 时进入登录页并显示凭证失效,不得继续访问旧用户数据。
  6. 分身聊天 SSE 逐段输出正常,Markdown 正常渲染,知识库优先级和积分扣费正常。
  7. 开启 BOXIM 主动接管后保持在线,默认三分钟回复、自定义等待时间、已读回执、分身防回环和主人发言暂停均正常。
  8. 重建容器后数据库、头像、知识库文档仍存在,/api/health 返回成功。
  9. https://digital.99hui.com/api/health 可访问,证书域名和有效期正确,HTTP 自动跳转 HTTPS。
  10. 微信和支付宝各创建一笔最小套餐订单,未付款时积分不变;支付成功后回调到账一次,重复回调积分不重复增加。

6. 回滚

保留上一版前后端镜像标签和发布前数据库/上传文件备份。代码回滚优先切回上一镜像;只有新版本执行了不可逆数据变更时才恢复数据库。恢复前先停止后端写入,恢复后对比用户数、分身数、知识库文档数并完成一次免登录和聊天验收。