跳转至

DIP1 生产环境外部服务集成指南

文档编号:DOC-D01-EXT
版本:V1.0
创建日期:2026-08-11
最后更新:2026-08-11
目标读者:TL(技术负责人)/ 运维人员
前置要求:DIP1 后端服务已部署运行


概述

本文档提供 DIP1 生产环境所需外部服务的完整集成指南,包括:

  1. Cloudflare R2 - 对象存储服务(图片、附件等)
  2. WhatsApp Business API - OTP 验证码发送
  3. 前端三端部署 - OPR 管理后台 / WKR 师傅端 / CST 客户端

每项集成均包含: - ✅ 前置条件检查 - ✅ 逐步操作指令(可复制粘贴) - ✅ 验证方法 - ✅ 常见问题排查


第一部分:Cloudflare R2 存储服务集成

1.1 前置条件

条件 说明 验证方式
Cloudflare 账号 免费版即可 访问 https://dash.cloudflare.com
已创建 R2 Bucket 存储桶名称需与配置一致 R2 Dashboard 查看
Access Key 用于 API 认证 创建 API Token 获取

1.2 操作步骤

步骤 1:登录 Cloudflare Dashboard

  1. 访问 https://dash.cloudflare.com
  2. 使用邮箱密码登录

步骤 2:创建 R2 Bucket

  1. 左侧菜单点击 R2
  2. 点击 Create bucket 创建存储桶
  3. 填写信息:
  4. Bucket name: dip1-assets-prod(生产环境)或 dip1-assets-staging(测试环境)
  5. Region: 选择最近区域(自动选择)
  6. 点击 Create bucket 确认

步骤 3:获取 Access Key

  1. 进入 R2SettingsAPI
  2. 点击 Create API token
  3. 选择权限:
  4. Permission: Object Read & Write
  5. TTL: 选择有效期(建议 30 天或自定义)
  6. 创建后请立即保存以下信息:
  7. Access Key ID(保存,仅显示一次)
  8. Secret Access Key(保存,仅显示一次)

步骤 4:获取 Account ID

  1. 点击 Cloudflare 首页
  2. 在 URL 中找到 Account ID(格式:https://dash.cloudflare.com/?to=/:account/r2
  3. 或在 Overview 页面底部找到 Account ID

步骤 5:配置公开访问域名(可选)

  1. 进入 Bucket → SettingsPublic access
  2. 启用 Custom Domains 或使用默认 pub-bucket.r2.dev 域名
  3. 记录公开访问 URL(如 https://assets.weavely.hk

1.3 配置环境变量

编辑 .env.prod.local 文件,填写以下配置:

# Cloudflare R2 配置
# 从 Cloudflare Dashboard 获取这些值
R2_ACCOUNT_ID=<你的AccountID>                    # Example: abc123def456
R2_ACCESS_KEY_ID=<你的AccessKeyID>                # Example: ABCDEF123456
R2_SECRET_ACCESS_KEY=<你的SecretAccessKey>        # Example: abc123def456...
R2_BUCKET=dip1-assets-prod                        # 与步骤 2 一致
R2_PUBLIC_URL=https://assets.weavely.hk           # 你的公开访问域名

1.4 部署生效

# 重新构建并启动 API 服务
cd dip1
docker compose -f docker-compose.prod.yml --env-file .env.prod.local up -d --build

1.5 验证集成

方法 1:API 测试

# 调用上传接口(需先登录获取 token)
# 1. 获取 token
curl -X POST "http://localhost:8000/api/v1/auth/login" \
  -H "Content-Type: application/json" \
  -d '{"user_id":"你的管理员账号","password":"密码"}'

# 2. 使用 token 上传文件
curl -X POST "http://localhost:8000/api/v1/files/upload" \
  -H "Authorization: Bearer <token>" \
  -F "file=@test.jpg"

方法 2:代码测试

# 在 API 容器内运行测试
docker exec -it dip1-api-1 python -c "
from app.infrastructure.storage import get_r2_client

r2 = get_r2_client()

# 测试上传
result = r2.upload_file(
    key='test/hello.txt',
    file_bytes=b'Hello DIP1!',
    content_type='text/plain'
)
print('上传成功:', result)

# 测试下载
content = r2.download_file('test/hello.txt')
print('下载内容:', content)

# 测试删除
r2.delete_file('test/hello.txt')
print('删除成功')
"

方法 3:检查 Cloudflare Dashboard

  1. 访问 https://dash.cloudflare.com/?to=/:account/r2
  2. 选择 dip1-assets-prod bucket
  3. 查看 Files 列表确认文件已上传

1.6 常见问题

错误 原因 解决方案
403 Access Denied Access Key 权限不足 检查 Key 权限是否包含 Object Write
404 Bucket Not Found Bucket 名称错误 核对 R2_BUCKET 变量
签名验证失败 时间戳偏差 同步服务器时间
超时无响应 网络问题 检查防火墙和代理设置

第二部分:WhatsApp Business API 集成

2.1 前置条件

条件 说明 验证方式
Meta Business 账号 免费注册 https://business.facebook.com
WhatsApp Business API 访问权限 需要申请 Meta for Developers 后台
已验证的手机号 用于发送 OTP 完成号码验证流程
模板审核通过 OTP 模板需 Meta 审核 在 WhatsApp Manager 查看

2.2 操作步骤

步骤 1:创建 Meta 开发者账号

  1. 访问 https://developers.facebook.com
  2. 使用 Facebook 账号登录(如无则新建)
  3. 完成安全验证(手机号验证)

步骤 2:创建 Business 账号

  1. 访问 https://business.facebook.com
  2. 点击 Create Business Account
  3. 填写业务信息:
  4. Business name: 织布鸟智居科技有限公司
  5. Business email: t***@weavely.hk
  6. Business phone: +852XXXXXXX
  7. 完成验证(邮箱/手机号)

步骤 3:申请 WhatsApp API 访问

  1. 访问 https://developers.facebook.com/apps
  2. 创建新 App:
  3. 选择 Business 类型
  4. 填写 App 名称:weavely-dip1
  5. 在 App Dashboard 左侧菜单找到 Add ProductsWhatsApp
  6. 点击 Set up 开始配置

步骤 4:配置 WhatsApp 产品

  1. 选择 WhatsApp Business Platform
  2. 创建新的产品实例
  3. 添加手机号:
  4. 点击 Add phone number
  5. 填写准备用于业务的手机号(需海外号码,如香港号码)
  6. 完成短信验证
  7. 记录以下信息:
  8. Phone Number ID(格式:123456789012345
  9. WABA ID(可选)

步骤 5:创建 Access Token

  1. 在 App Dashboard → SettingsBasic
  2. 找到 App Secret 并保存
  3. 生成 Access Token:
  4. 访问 https://developers.facebook.com/tools/explorer
  5. 选择你的 App 和 Page
  6. 生成 Access Token(需包含 whatsapp_business_messaging 权限)
  7. 重要:Access Token 有效期 60 天,需定期刷新

步骤 6:创建 OTP 模板

  1. 进入 App → WhatsAppManager
  2. 点击 TemplateCreate template
  3. 创建模板:
  4. Template name: otp_login
  5. Category: 选择 AuthenticationUtility
  6. Language: English(或添加中文支持)
  7. Body: Your verification code is {{1}}. Do not share this code.
  8. 变量 {{1}} 对应 OTP 验证码
  9. 提交审核(通常 1-2 个工作日)
  10. 审核通过后模板即可使用

步骤 7:配置环境变量

编辑 .env.prod.local 文件:

# WhatsApp Business API 配置
# 从 Meta Developer Portal 获取
WHATSAPP_ACCESS_TOKEN=<你的Access Token>              # 从 Graph API Explorer 生成
WHATSAPP_PHONE_NUMBER_ID=<你的Phone Number ID>        # 从 WhatsApp Manager 获取
WHATSAPP_API_VERSION=v18.0                             # 最新稳定版本

2.3 部署生效

# 重新构建并启动 API 服务
cd dip1
docker compose -f docker-compose.prod.yml --env-file .env.prod.local up -d --build

2.4 验证集成

方法 1:Mock 模式测试(开发阶段)

# 在未配置真实凭据时,系统自动使用 Mock 模式
# 发送 OTP 请求
curl -X POST "http://localhost:8000/api/v1/auth/otp/send?phone=+85292230009&purpose=login"

# 查看容器日志,会显示 Mock 的验证码
docker logs dip1-api-1 --tail 20
# 输出示例: [MOCK WHATSAPP] OTP sent to 85292230009: 123456

方法 2:真实 API 测试

# 配置好真实凭据后,发送 OTP 请求
curl -X POST "http://localhost:8000/api/v1/auth/otp/send?phone=+8529XXXXXXXX&purpose=login"

# 检查响应
# 成功: {"status":"sent","message_id":"..."
# 失败: {"status":"error","error":"错误信息"}

方法 3:代码测试

# 在 API 容器内运行测试
docker exec -it dip1-api-1 python -c "
import asyncio
from app.infrastructure.otp import get_otp_provider

async def test():
    provider = get_otp_provider()

    # 发送 OTP
    result = await provider.send_otp_code(
        phone_number='+85292230009',
        otp_code='123456'
    )
    print('发送结果:', result)

    # 如果是 Mock 模式,会返回验证码
    if hasattr(provider, 'otp_code'):
        print('验证码:', result.get('otp_code'))

asyncio.run(test())
"

2.5 Access Token 刷新

Token 有效期:60 天

刷新方法: 1. 手动刷新: - 访问 https://developers.facebook.com/tools/explorer - 重新生成 Access Token - 更新 .env.prod.local 中的 WHATSAPP_ACCESS_TOKEN

  1. 自动刷新(建议长期运行时实现):
  2. 可实现定时任务,在 Token 过期前 7 天自动刷新
  3. 或监控 API 返回的错误码,触发刷新流程

2.6 常见问题

错误 原因 解决方案
401 Invalid Token Token 过期或无效 重新生成 Token
404 Not Found Phone Number ID 错误 核对 WHATSAPP_PHONE_NUMBER_ID
400 Template Not Found 模板名称错误或未审核 检查模板名称和审核状态
消息未送达 号码格式错误 使用 E.164 格式(国家代码+号码)
频率限制 发送过于频繁 遵守 OTP_RATE_LIMIT_PER_HOUR 设置

第三部分:前端三端部署

3.1 整体架构

┌─────────────────────────────────────────────────────────────┐
│                     DIP1 前端三端部署                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  OPR-Admin(运营后台)                                │   │
│  │  ├── 技术栈: Next.js 14 + React + Tailwind CSS       │   │
│  │  ├── 部署方式: Docker 容器 / Vercel / Cloudflare     │   │
│  │  ├── 域名: admin.weavely.hk                          │   │
│  │  └── 用户: OL(运营) / TL(技术) / BO(业务)            │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  WKR-App(师傅端)                                    │   │
│  │  ├── 技术栈: React Native + Expo + NativeWind        │   │
│  │  ├── 部署方式: EAS Build → App Store / Google Play  │   │
│  │  ├── 域名: wkr.weavely.hk (API)                     │   │
│  │  └── 用户: FL(师傅)                                  │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  CST-App(客户端)                                    │   │
│  │  ├── 技术栈: React Native + Expo + NativeWind        │   │
│  │  ├── 部署方式: EAS Build → App Store / Google Play  │   │
│  │  ├── 域名: cst.weavely.hk (API)                     │   │
│  │  └── 用户: Customer(客户)                            │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

3.2 环境依赖检查

通用依赖

工具 版本要求 安装命令 验证命令
Node.js >= 20 LTS fnm install 20 或官网下载 node --version
pnpm >= 9.x corepack enable && corepack prepare pnpm@latest --activate pnpm --version
Git >= 2.x 官网下载 git --version
Docker Desktop >= 4.x 官网下载 docker --version

OPR-Admin 额外依赖

工具 版本要求 说明
Nginx >= 1.24 可选,用于 Docker 部署反向代理
SSL 证书 Let's Encrypt / Cloudflare HTTPS 必需

WKR/CST Mobile 额外依赖

工具 版本要求 安装命令 说明
Expo CLI >= 0.18.x npm i -g expo-cli React Native 开发工具
EAS CLI >= 13.x npm i -g eas-cli Expo 云端构建
Xcode >= 15.4 Mac App Store iOS 构建(仅 macOS)
Android Studio Hedgehog+ 官网下载 Android 模拟器
Apple Developer $99/年 注册账号 App Store 发布
Google Play Console $25 一次性 注册账号 Google Play 发布

3.3 OPR-Admin 部署

方式 A:Docker 部署(推荐)

步骤 1:进入前端目录

cd dip1/frontend/apps/opr-admin

步骤 2:创建生产配置

创建 .env.production 文件:

# API 配置
NEXT_PUBLIC_API_URL=https://api.weavely.hk/api/v1

# 应用配置
NEXT_PUBLIC_APP_NAME=织布鸟运营后台
NEXT_PUBLIC_ENV=production

# 其他配置...

步骤 3:构建 Docker 镜像

# 在 opr-admin 目录创建 Dockerfile
cat > Dockerfile << 'EOF'
# 构建阶段
FROM node:20-alpine AS builder
WORKDIR /app

COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile

COPY . .
RUN pnpm build

# 运行阶段
FROM node:20-alpine AS runner
WORKDIR /app

ENV NODE_ENV=production
PORT=3000

COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/next.config.mjs ./

EXPOSE 3000
CMD ["node", "node_modules/.bin/next", "start"]
EOF

步骤 4:构建并运行

# 构建镜像
docker build -t weavely/opr-admin:latest .

# 运行容器
docker run -d \
  --name opr-admin \
  -p 3000:3000 \
  -e NEXT_PUBLIC_API_URL=https://api.weavely.hk/api/v1 \
  weavely/opr-admin:latest

步骤 5:配置 Nginx 反向代理(可选)

# /etc/nginx/conf.d/opr-admin.conf
server {
    listen 443 ssl http2;
    server_name admin.weavely.hk;

    ssl_certificate /etc/ssl/certs/admin.weavely.hk.pem;
    ssl_certificate_key /etc/ssl/private/admin.weavely.hk.key;

    location / {
        proxy_pass http://localhost:3000;
        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;
    }
}

方式 B:Vercel 部署(更简单)

步骤 1:登录 Vercel

# 安装 Vercel CLI
npm i -g vercel

# 登录
vercel login

步骤 2:部署

cd dip1/frontend/apps/opr-admin

# 首次部署
vercel

# 配置环境变量后重新部署
vercel --prod

步骤 3:绑定域名

  1. 访问 https://vercel.com/dashboard
  2. 选择项目 → Settings → Domains
  3. 添加域名 admin.weavely.hk
  4. 在 Cloudflare DNS 添加 CNAME 记录

步骤 4:配置环境变量

  1. Vercel Dashboard → Project → Settings → Environment Variables
  2. 添加:
  3. NEXT_PUBLIC_API_URL = https://api.weavely.hk/api/v1

3.4 WKR-App 师傅端部署

前置条件

  • Apple Developer 账号(iOS 发布)
  • Google Play Console 账号(Android 发布)
  • Expo EAS 账号
  • 已配置 Google Services / Apple Sign In(如需要)

步骤 1:配置 EAS

# 进入师傅端目录
cd dip1/frontend/apps/wkr-app

# 登录 Expo
expo login
# 输入 Expo 账号凭据

# 配置 EAS 项目
eas build:configure

步骤 2:配置 eas.json

{
  "cli": {
    "version": ">= 13.0.0"
  },
  "build": {
    "development": {
      "developmentClient": true,
      "distribution": "internal",
      "env": {
        "API_URL": "https://api.weavely.hk/api/v1"
      }
    },
    "preview": {
      "distribution": "internal",
      "android": {
        "buildType": "apk"
      },
      "ios": {
        "simulator": true
      },
      "env": {
        "API_URL": "https://api.weavely.hk/api/v1"
      }
    },
    "production": {
      "android": {
        "buildType": "app-bundle"
      },
      "ios": {
        "buildConfiguration": "Release"
      },
      "env": {
        "API_URL": "https://api.weavely.hk/api/v1"
      }
    }
  },
  "submit": {
    "production": {
      "android": {
        "serviceAccountKeyPath": "./google-services.json",
        "track": "internal"
      },
      "ios": {
        "appleId": "your-team-id@weavely.hk",
        "ascAppId": "1234567890",
        "appleTeamId": "YOUR_TEAM_ID"
      }
    }
  }
}

步骤 3:构建 Android APK(内部测试)

# 构建 preview 版本(APK 格式,可直接安装)
eas build --platform android --profile preview

# 等待构建完成,下载 APK 文件
# 扫描二维码或点击下载链接获取 APK

步骤 4:构建 iOS IPA(内部测试)

# 构建 preview 版本
eas build --platform ios --profile preview

# 注意:iOS 构建需要 Apple 开发者账号配置
# 在 Apple Developer 添加测试设备 UDID

步骤 5:发布到 App Store / Google Play

# 1. 构建生产版本
eas build --platform all --profile production

# 2. 提交到商店
# Google Play
eas submit --platform android --profile production

# App Store
eas submit --platform ios --profile production

3.5 CST-App 客户端部署

步骤与 WKR-App 相同

# 进入客户端目录
cd dip1/frontend/apps/cst-app

# 配置 EAS
eas build:configure

# 构建 Android
eas build --platform android --profile preview

# 构建 iOS
eas build --platform ios --profile preview

# 发布
eas submit --platform all --profile production

3.6 部署验证清单

OPR-Admin 验证

检查项 验证方法 预期结果
页面加载 访问 https://admin.weavely.hk 页面正常显示
登录功能 使用管理员账号登录 登录成功跳转首页
API 连通 打开浏览器 DevTools 查看网络请求 API 返回 200
样式正常 检查所有页面样式 无错位、无破损

WKR-App 验证

检查项 验证方法 预期结果
App 安装 在师傅手机安装 APK/IPA App 正常安装
登录功能 使用师傅账号登录 登录成功显示订单列表
接单功能 师傅点击接单 状态变更为"进行中"
打卡功能 L6 阶段打卡 上传照片成功
完成功能 L8 阶段完成 订单状态变更为"已完成"

CST-App 验证

检查项 验证方法 预期结果
App 安装 在客户手机安装 APK/IPA App 正常安装
注册功能 新客户手机号注册 OTP 验证后注册成功
登录功能 使用客户账号登录 登录成功显示订单列表
询价功能 选择服务提交询价 询价单提交成功
查看订单 查看订单状态更新 实时显示师傅位置
评分功能 完成后评分 评分提交成功

3.7 常见问题

问题 原因 解决方案
OPR-Admin 空白页 API URL 配置错误 检查 NEXT_PUBLIC_API_URL
WKR/CST 无法登录 API 域名不可达 检查 HTTPS 证书和 DNS
Expo 构建失败 依赖版本冲突 清理缓存后重试:expo doctor --fix
Google Play 提交失败 签名证书过期 生成新签名证书
App Store 提交被拒 审核不符合规则 查看审核反馈并修改

附录

A. 完整环境变量清单

# ====== 基础配置 ======
ENV=prod
TZ=Asia/Hong_Kong
APP_VERSION=2.0.0
APP_SECRET_KEY=<强密钥>

# ====== CORS ======
CORS_ORIGINS=["https://admin.weavely.hk","https://wkr.weavely.hk","https://cst.weavely.hk"]

# ====== 数据库 ======
DATABASE_URL=postgresql+asyncpg://user:pass@host:5432/db
DB_POOL_SIZE=20
DB_MAX_OVERFLOW=40

# ====== Redis ======
REDIS_URL=redis://host:6379/0

# ====== Cloudflare R2 ======
R2_ACCOUNT_ID=<account_id>
R2_ACCESS_KEY_ID=<access_key>
R2_SECRET_ACCESS_KEY=<secret_key>
R2_BUCKET=dip1-assets-prod
R2_PUBLIC_URL=https://assets.weavely.hk

# ====== WhatsApp Business API ======
WHATSAPP_ACCESS_TOKEN=<access_token>
WHATSAPP_PHONE_NUMBER_ID=<phone_number_id>
WHATSAPP_API_VERSION=v18.0

# ====== JWT 配置 ======
JWT_ALGORITHM=HS256
JWT_ACCESS_TOKEN_TTL_MIN=15
JWT_REFRESH_TOKEN_TTL_DAY=30

# ====== OTP 配置 ======
OTP_TTL_SECONDS=300
OTP_RATE_LIMIT_PER_HOUR=5

# ====== Expo/EAS ======
EXPO_USERNAME=weavely-dip1
EXPO_PROJECT_ID_WKR=<wkr_project_id>
EXPO_PROJECT_ID_CST=<cst_project_id>

# ====== 推送服务 ======
EXPO_PUSH_AUTH_TOKEN=<push_token>

# ====== 可观测性 ======
SENTRY_DSN=<sentry_dsn>
LOG_LEVEL=WARNING

B. 快速部署命令汇总

# 1. 克隆并配置
git clone <repo>/dip1.git
cd dip1
cp .env.prod.local .env.prod
# 编辑 .env.prod 填入真实凭据

# 2. 启动后端
docker compose -f docker-compose.prod.yml --env-file .env.prod up -d --build

# 3. 数据库迁移
docker exec dip1-api-1 alembic upgrade head

# 4. 种子数据
docker exec dip1-api-1 python -m app.infrastructure.db.seed.cli

# 5. 验证健康检查
curl http://localhost:8000/health

# 6. 部署 OPR-Admin(Docker)
cd frontend/apps/opr-admin
docker build -t weavely/opr-admin .
docker run -d -p 3000:3000 weavely/opr-admin

# 7. 构建 WKR-App
cd frontend/apps/wkr-app
eas build --platform android --profile preview

# 8. 构建 CST-App
cd frontend/apps/cst-app
eas build --platform android --profile preview

C. 文档索引

文档 路径 说明
DIP1-ARC 架构设计 docs/DIP1-ARC-架构设计.md 系统架构、ADR 决策
DIP1-P3 技术基础设施 docs/DIP1-P3-技术基础设施.md 开发环境、CI/CD
DIP1-OPS 管理员手册 docs/DIP1-OPS-生产环境管理员操作手册.md 运维操作指南
DIP1-IMP 实施指南 docs/DIP1-IMP-Code-Agent实施指南.md 项目计划

修订记录

版本 日期 修订人 修订内容
V1.0 2026-08-11 DT 初始版本,集成 R2/WhatsApp/前端三端部署

本指南为 DIP1 生产环境外部服务集成文档,由听写 DT 维护。
如有疑问请联系 TL 或 DT 获取技术支持。