123 lines
4.3 KiB
Markdown
123 lines
4.3 KiB
Markdown
# Policy Links(技术计划)
|
||
|
||
## 1. 目标与原则
|
||
|
||
**目标**:让客户端所有「隐私协议 / 使用协议」入口(至少包含:首次同意页 + 个人主页弹窗)统一通过后端接口获取链接,并支持按设备语言分发,缺省回退 EN。
|
||
|
||
**原则**:
|
||
|
||
- 客户端不写死协议 URL(避免发版更新)
|
||
- 请求失败不阻塞主流程(尤其是首次同意页)
|
||
- 语言选择策略一致、可解释、可排查(返回 `resolvedLang`)
|
||
|
||
## 2. 接口与契约
|
||
|
||
### 2.1 HTTP 接口
|
||
|
||
- **方法与路径**:`GET /v1/legal/links`
|
||
- **请求头**:
|
||
- `Accept-Language`: `en` / `tc`(当前仅支持 EN / TC;客户端可按 i18n/设备语言映射为其中之一)
|
||
- **响应**(JSON):
|
||
- `privacyPolicyUrl: string`
|
||
- `termsOfUseUrl: string`
|
||
- `resolvedLang: "en" | "tc"`
|
||
|
||
### 2.2 语言回退(服务端决策)
|
||
|
||
- 若 `Accept-Language` 缺失/无法解析:回退 `en`
|
||
- 若目标语言的链接未配置:回退 `en`
|
||
- `resolvedLang` 表示服务端最终命中的语言(用于排查)
|
||
|
||
## 3. 后端实现方案(FastAPI)
|
||
|
||
### 3.1 配置来源
|
||
|
||
采用环境变量(Pydantic Settings)承载各语言链接配置:
|
||
|
||
- 推荐配置(EN):
|
||
- `LEGAL_PRIVACY_URL_EN`
|
||
- `LEGAL_TERMS_URL_EN`
|
||
- 可选:
|
||
- `LEGAL_PRIVACY_URL_TC` / `LEGAL_TERMS_URL_TC`
|
||
|
||
> 补充:若未配置 `LEGAL_*`,后端将使用**内置协议内容页**作为兜底,保证客户端点击后“必有内容”。
|
||
|
||
### 3.2 路由与业务逻辑
|
||
|
||
- 新增 `v1/legal` 路由模块
|
||
- 读取 `Accept-Language` 做轻量解析(只关心 en/tc,其他回退 en)
|
||
- 根据解析结果选择 URL;如缺失则回退到 EN URL
|
||
|
||
### 3.3 内置协议内容页(兜底,保证有内容)
|
||
|
||
- **页面接口**:
|
||
- `GET /v1/legal/privacy`:隐私协议(HTML)
|
||
- `GET /v1/legal/terms`:使用协议(HTML)
|
||
- **内容来源**:
|
||
- 直接使用仓库文档:`设计说明文档/隐私协议.md`、`设计说明文档/用户使用协议.md`
|
||
- **语言策略**:
|
||
- 仍按 `Accept-Language` 解析 `en/tc`;若文档缺少 tc 段落则回退 en
|
||
- **链接下发回退**:
|
||
- 当 `LEGAL_*` 未配置(或显式走内置)时,`GET /v1/legal/links` 返回当前服务域名下的上述内置页面绝对 URL
|
||
|
||
### 3.4 兼容性与安全
|
||
|
||
- 要求链接为 HTTPS(推荐);返回前做基本 URL 校验(通过响应模型约束)
|
||
- 不引入数据库变更
|
||
|
||
### 3.5 后端测试(建议)
|
||
|
||
- 单测覆盖:
|
||
- `Accept-Language` 缺失 → `resolvedLang=en`
|
||
- `tc` 命中/缺失回退
|
||
- `zh-hant/zh-hk/zh-tw` 等输入能解析为 `tc`
|
||
|
||
## 4. 客户端实现方案(React Native + Expo)
|
||
|
||
### 4.1 统一 service
|
||
|
||
- 新增 `src/services/legalApi.ts`:
|
||
- 统一拼接 `API_BASE_URL + /v1/legal/links`
|
||
- 统一设置 `Accept-Language`
|
||
- 统一超时与错误处理(抛错由调用方兜底)
|
||
|
||
### 4.2 接入点
|
||
|
||
- **首次同意页**(`app/(splash)/splash.tsx`):
|
||
- 页面展示时拉取链接
|
||
- 拉取失败:不崩溃、不阻塞「同意并继续」
|
||
- 点击协议入口:使用 `expo-web-browser` 打开下发链接
|
||
- **个人主页弹窗**(`components/home/ProfileModal.tsx`):
|
||
- 弹窗打开时拉取链接
|
||
- 点击「隐私协议/使用协议」时打开下发链接(不再 `toastTodo`)
|
||
|
||
### 4.3 语言映射策略(客户端)
|
||
|
||
- 将客户端当前语言映射到 `en / tc` 二选一:
|
||
- 任意 `zh*` → `tc`
|
||
- 其他语言 → `en`
|
||
|
||
## 5. 可观测与排障
|
||
|
||
- 开发环境打印:
|
||
- 请求地址、请求头(含 `Accept-Language`)
|
||
- 拉取失败原因(仅 dev)
|
||
- 线上环境:
|
||
- 不打印用户相关敏感信息(本接口仅链接配置,风险较低,但仍应克制日志)
|
||
|
||
## 6. 发布与回滚策略
|
||
|
||
- **灰度**:dev 环境可先不配 `LEGAL_*`,直接验证内置页面能打开;再逐步切到外部托管链接
|
||
- **补齐多语言**:逐步补齐 `zh-CN` / `zh-TW` 链接配置
|
||
- **回滚**:
|
||
- 后端:回滚到仅 EN 配置仍可运行(客户端自动回退)
|
||
- 客户端:即使接口失败也不阻塞主流程(保持可用)
|
||
|
||
## 7. 验收映射(对应 spec)
|
||
|
||
- 首次同意页 + 个人主页弹窗均从 API 获取链接
|
||
- 设备语言为 EN/TC 时分别打开对应链接
|
||
- 不支持语言回退 EN
|
||
- 后端不可达时 App 不崩溃,且同意流程可继续
|
||
|