yumi-flutter/docs/后端接口对接规范.md

457 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Yumi Flutter 后端接口对接规范
> 适用仓库:`yumi-flutter`
> 后端代码:`yumi-java` + `yumi-golang`
> 最后核对2026-07-10
## 1. 目标与适用范围
本文档用于统一 Yumi Flutter 与 Java、Go 后端的接口对接方式,覆盖接口事实来源、路由归属、前端分层、响应解析、鉴权、错误处理、验证和问题流转。
核心原则:
- 先查代码和配置,再实现;禁止根据页面或旧模型猜测后端契约。
- Flutter 线程对两个后端仓库仅有只读权限,发现后端问题只记录证据和建议。
- 所有业务 HTTP 请求必须经过项目现有网络层,页面不直接解析原始响应。
- 接口失败时禁止使用本地假数据、硬编码列表或伪造成功结果还原页面。
- Bug 修复必须先说明 Root Cause 和影响面,经确认后再做最小改动并提供验证证据。
---
## 2. 仓库位置与责任边界
### 2.1 Flutter 客户端
```text
/Users/pinpaibu/flutter_code/yumi-flutter
```
当前技术和分层事实:
- 网络Dio统一客户端为 `lib/shared/data_sources/sources/remote/net/network_client.dart`
- 响应封装:`ResponseData<T>`
- 仓储接口:`lib/shared/business_logic/repositories/`
- 仓储实现:`lib/shared/data_sources/sources/repositories/`
- 请求/响应模型:`lib/shared/business_logic/models/req/``res/`
- 功能模块:`lib/modules/`;独立功能也可在模块内保留 `data/api/repository/models` 边界,例如 `lib/modules/room_game/data/`
- 页面状态Provider + ChangeNotifier全局管理器在 `lib/services/`
- 路由Fluro入口为 `lib/main.dart`
### 2.2 Java 后端
```text
/Users/pinpaibu/server_code/yumi-java
```
客户端相关的主要边界:
- `rc-gateway/`Spring Cloud Gateway是 Flutter 默认 HTTP 入口。
- `nacos_config/rc-gateway/application.yml`:外部路径到 Java/Go 服务的路由事实。
- `rc-auth/`:登录凭证和内部 Token 校验。
- `rc-service/rc-service-other/`:用户、配置、礼物、任务、房间外围等大量 App 业务。
- `rc-service/rc-service-live/`:语音房在线、麦位等实时业务。
- `rc-service/rc-service-wallet/`:钱包、余额、流水。
- `rc-service/rc-service-order/`:订单与支付。
- `rc-service/rc-service-external/`文件、短信、IM/TRTC 等外部能力。
- `rc-service/rc-inner-api/`Java 服务内部 Feign 契约Flutter 不直接调用。
Java `README.md` 可用于快速定位模块,但其端口和模块说明可能滞后;联调时必须以 Gateway/Nacos 路由和当前 Controller 为准。
### 2.3 Go 后端
```text
/Users/pinpaibu/server_code/yumi-golang
```
当前主要边界:
- `cmd/api/`HTTP API 启动和依赖装配。
- `cmd/consumer/`:事件消费入口。
- `internal/router/`Gin 路由、请求绑定、鉴权中间件和统一响应。
- `internal/service/<module>/`:按业务模块拆分的业务逻辑。
- `internal/integration/`Go 调用 Java 服务的网关封装。
- `internal/common/``AppError``AuthUser` 等跨模块类型。
- `internal/model/``migrations/`:表映射和数据库迁移。
- `internal/config/config.go`:运行配置与 Java 下游地址。
Go 本地 HTTP 默认监听 `:2900`,但 Flutter 默认仍应通过 Java Gateway 访问,不应在业务代码中硬编码内部端口。
---
## 3. 后端仓库只读红线
在 Flutter 对接任务中,`yumi-java``yumi-golang` 一律视为只读证据源。
允许:
- 使用 `rg``find``sed -n``git status --short``git diff``git show` 查看和搜索。
- 读取路由、Controller/Handler、DTO、Service、错误码、配置和测试。
- 在 Flutter 文档中记录后端证据路径和待确认事项。
禁止:
- 在后端仓库创建、修改、删除、移动或格式化任何代码、文档、配置、SQL、生成文件和测试。
- 运行会产生文件的命令,如 `gofmt -w``goimports -w``go mod tidy`、Maven 打包、代码生成、数据库迁移。
- 默认启动后端、Docker、消费者、定时任务或执行后端测试确有必要时必须先说明作用和文件/数据影响,并得到用户明确授权。
- 在后端仓库执行暂存、提交、切分支、合并、拉取或推送。
- 把调试标记或前端待办写入后端源码。
---
## 4. 实际请求拓扑与路由归属
### 4.1 默认链路
```text
Flutter
-> Java GatewayAPI_HOST
-> Java auth / external / order / wallet / live / other
-> Go API
-> MySQL / Redis / MQ
-> Java 内部服务(鉴权、用户、钱包、奖励等)
```
Flutter 默认基地址由 `SCVariant1Config.apiHost` 提供,可通过编译参数覆盖:
```bash
flutter run --dart-define=API_HOST=https://example-gateway/
```
不得在 Repository、Manager 或 Widget 中硬编码生产/测试域名。
### 4.2 Java Gateway 路由要点
`yumi-java/nacos_config/rc-gateway/application.yml` 为准,当前关键对外路径如下:
| Flutter 请求路径 | Gateway 处理 | 实际归属 |
| --- | --- | --- |
| `/auth/**` | 去掉 `/auth` | Java auth |
| `/external/**` | 去掉 `/external` | Java external |
| `/order/**` | 去掉 `/order` | Java order |
| `/wallet/**` | 去掉 `/wallet` | Java wallet |
| `/live/**` | 去掉 `/live` | Java live |
| `/go/**` | 去掉 `/go` | Go API |
| `/app/game/**` | 保留原路径 | Go API |
| 未匹配的普通路径 | 默认转发 | Java other |
| 带 `Req-Likei: true` 的加密路由 | `ForwardRoute` 解析后转发 | 由解析结果决定 |
Gateway 还对部分活动、回调和后台路径做了专用路由;对接具体接口时必须搜索完整 path不能只根据前缀推断服务归属。
### 4.3 Go 路径的两种对接形式
- 经 Gateway 的 `/go` 路由Flutter 请求 `/go/app/vip/status`Go 实际接收 `/app/vip/status`
- Gateway 专用路由:例如 Flutter 请求 `/app/game/providers`Go 仍接收 `/app/game/providers`
除已有调试边界外,新增 App 接口优先使用同一 `API_HOST` 经 Gateway 访问。项目已有两个可选直连覆盖:
- `VIP_API_HOST`VIP Go API 调试。
- `GAME_API_HOST`:房间游戏 Go API 调试。
仅在确认需要绕过 Gateway 联调时使用;不得为单个页面随意新增直连域名。
---
## 5. 接口事实参考顺序
当前两个后端仓库没有可覆盖全部 App 接口的统一 OpenAPI 契约,因此必须以可执行代码和当前路由配置为主证据。
### 5.1 先确定请求归属
1.`nacos_config/rc-gateway/application.yml` 搜索完整 path 或前缀。
2. 判断请求是否会 `StripPrefix`,记录 Flutter path 与下游 path。
3. 确认该路由是否在 `gateway.ignorePaths` 中;“忽略 Gateway 鉴权”不等于“业务无需鉴权”,还要继续检查下游实现。
### 5.2 Java 接口
按以下顺序核对:
1. `*-adapter/src/main/java/**/**RestController.java``@RequestMapping` + `@Get/Post/Put/DeleteMapping` 确认 method/path。
2. Controller 方法参数:确认 query/path/form/json、`@Validated` 和必填规则。
3. `*-client` / `*-inner` 中的 Command、CO、DTO、Enum确认字段名、类型、枚举和响应数据。
4. `*-application` 中对应 Service确认业务条件、空值和错误分支。
5. 错误码枚举、`ApiException` 和统一响应框架:确认业务失败语义。
6. 最后查看相关测试和 README/docs用于补充流程不用于覆盖当前代码。
### 5.3 Go 接口
按以下顺序核对:
1. `internal/router/<module>_routes.go`:确认 method/path、鉴权中间件、query/path/body 绑定。
2. `internal/service/<module>/types.go` 及对应业务文件:确认请求/响应字段、默认值、业务规则和 `AppError`
3. `internal/integration/`:如业务依赖 Java确认实际下游 endpoint、Header 和数值转换。
4. `internal/model/``migrations/``internal/config/`:仅用于理解字段来源、持久化和运行限制。
5. `*_test.go`:核对边界值和已固化行为。
### 5.4 证据冲突时
- Gateway 配置决定外部请求实际到达哪个服务。
- 当前 Router/Controller 实现决定 method、path 和参数接收方式。
- 当前 Service/DTO 实现决定业务语义和字段。
- README、注释、历史文档和 Flutter 旧模型只是补充证据。
- 冲突时以当前可到达的执行代码作为“现状事实”同时记录“待后端确认”Flutter 不自行改后端消除差异。
---
## 6. 已确认的网络契约
### 6.1 请求 Header
`ApiInterceptor` 会统一补充:
- `Authorization: Bearer <token>`(本地存在 Token 时)
- `req-lang`
- `req-imei`
- `req-app-intel`
- `req-client`
- `req-sys-origin`
- `Host`
- 已确认的加密路由才会添加 `Req-Likei: true`
对接时不得在 Widget/Manager 重复手工组装这些公共 Header也不得在代码或日志中写死 Token、密钥或完整鉴权数据。
Go App 路由的 `authMiddleware` 会读取 Bearer Token并调用 Java auth 校验凭证;因此 Go 接口鉴权仍与 Java 登录态一致。
### 6.2 Java/Go 兼容响应
Flutter `ResponseData<T>` 当前兼容两类字段:
```json
{
"status": true,
"errorCode": 0,
"errorCodeName": "",
"errorMsg": "success",
"body": {},
"time": 0
}
```
以及:
```json
{
"code": 200,
"message": "OK",
"data": {}
}
```
Go `writeOK` / `writeError` 会同时输出 `status/errorCode/errorMsg/body``code/message/data` 两套兼容字段。Flutter 解析规则为:
- 数据优先读取 `body`,不存在时读取 `data`
- 优先用 `status` 判定成败;缺失时,`code == 0``code == 200` 视为成功。
- 错误码读取 `errorCode``code`,错误信息读取 `errorMsg``message`
- HTTP 200 不代表业务成功,仍必须检查 envelope。
- HTTP 4xx/5xx 与业务失败都必须进入明确错误状态。
新接口不得在页面层再实现一套 envelope 判定逻辑。
### 6.3 空响应
- 只有后端契约明确表示成功无数据时,才允许使用可空泛型和 `allowNullBody: true`
- 不得用 `false``0`、空字符串或空列表掩盖本应返回对象的契约问题。
- 列表本身合法为空时,空列表是真实业务结果,不是接口失败的替代值。
### 6.4 路径与加密路由
- 旧接口在 Repository 中仍可能使用哈希形式的路由键,`network_client.dart` 会用 `_localRouteOverrides` 转为已知明文 path。
- 新对接优先使用后端路由中已确认的明文 path不复制或自行生成哈希。
- 若线上 Gateway 明确要求加密路由,必须先获得后端路由键/转发规则并在网络层集中处理,页面层不得设置 `Req-Likei`
---
## 7. Flutter 对接落地规范
### 7.1 分层责任
```text
Widget / Page
-> Provider / ChangeNotifier / Manager
-> Repository abstraction
-> Repository implementation / feature Api
-> NetworkClient
-> Java Gateway -> Java or Go
```
- `Widget / Page`:只负责渲染、交互与发出意图;不直接调 Dio不解析 JSON。
- `Provider / ChangeNotifier / Manager`:编排加载、成功、空态和错误状态,调用 Repository不处理原始 envelope。
- `Repository abstraction`:定义业务语义明确的方法和返回类型。
- `Repository implementation / feature Api`:定义 method/path/query/body调用 `http.get/post/put/delete`,完成 model 映射。
- `NetworkClient`:统一 base URL、Header、Token、超时、envelope 和通用错误处理。
对现有模块增加接口时,优先延续该模块的已有分层,不为单个接口引入第二套网络或状态管理方案。
### 7.2 Model 与字段
- 字段命名、类型、可空性、枚举值和时间单位必须有后端证据。
- 后端 `int64/Long` 字段如可能以数字或数字字符串返回,只能在 Model 解析边界做兼容,不得在 Widget 中反复转换。
- 时间字段必须明确是秒、毫秒还是 ISO-8601禁止通过数值长度猜测。
- 金额、金币和比例必须确认单位与精度,不得在 UI 层暗中乘除。
- 枚举未知值应有安全的“未知/不支持”分支,但不得把未知值伪装成某个已知业务类型。
- 不在 Model 中根据页面需求虚构后端未返回的业务字段。
### 7.3 请求参数
- GET 查询使用 `queryParams`path variable 只用已确认的 URL 片段。
- JSON 请求使用 `data`,参数命名与后端契约一致。
- 文件上传使用 `FormData`/`MultipartFile`必须同时确认表单字段名、MIME、扩展名、大小上限和超时。
- 幂等写操作的 key 由调用方在一次用户意图开始时创建,同一次超时重试必须复用;不得在每次底层请求时重新生成。
- 分页必须记录是 cursor、page/size 还是 lastId不得混用。
### 7.4 错误和登录态
- 网络层负责超时、HTTP 错误、通用业务错误和当前登录态校验。
- Manager/Provider 只负责将错误转为页面可表达的错误状态,必要时提供重试入口。
- Widget 不得看 `errorCode` 决定登出,不得自行重试鉴权失败。
- 不得把服务端内部堆栈、SQL、密钥、完整 Token 或敏感请求体输出到生产日志。
- 同一页面需要部分容错时,必须先定义每个数据源的独立成功/失败语义,不能用本地假数据补齐失败部分。
---
## 8. 严禁本地数据兜底
接口错误、超时、解析失败或返回不完整时,禁止:
- 返回内置 mock 列表、本地 JSON、调试 assets 或硬编码对象。
- 把异常转换为空列表、`false``0` 或“成功”,使页面误以为接口已成功。
- 因为新接口不可用而静默切换到语义不同的旧接口。
- 用占位数据触发下游支付、送礼、发奖、扣费、房间状态或其他写操作。
允许的仅是产品明确设计的本地能力,例如:
- 加载骨架、空态插图、错误提示和重试按钮,但不得表示为服务端真实数据。
- 明确定义的离线缓存,但必须保留“旧数据/离线”语义,不能覆盖本次请求失败事实。
- 纯 UI 预览和单元测试中的 Fake/Fixture必须与生产请求路径隔离。
---
## 9. 标准对接流程
1. 明确本次业务范围,不顺手改无关模块。
2. 在 Flutter 中搜索现有接口、Model、Manager 和测试,确认已有状态和兼容要求。
3. 查 Java Gateway 路由,确定请求归属和外部 path。
4. 按第 5 节读取 Java 或 Go 的 Router/Controller、DTO/Service、错误和测试。
5. 先写一份接口事实记录,至少包含 method/path/auth/request/response/error/evidence。
6. 说明改动对现有路由、网络层、登录态、模型和页面的影响;若为 Bug先提供 Root Cause 并等待用户确认。
7. 在 Flutter 做能解决问题的最小变更,不重构无关代码。
8. 增加 Model/envelope/分页/错误分支的针对性测试。
9. 按第 11 节执行验证,并记录真实 API 联调结果。
10. 如后端需要调整,只记录待确认项和证据,由用户协调后端处理。
---
## 10. 接口事实记录模板
```text
### 接口名称
- 业务模块:
- 调用链路Flutter -> Java Gateway -> Java / Go -> 下游
- Flutter Method / Path
- 下游 Method / Path
- Gateway 路由处理:保留路径 / StripPrefix / 加密转发
- Auth无 / Bearer / 其他
- Request
- path
- query
- header
- body/form
- Response body/data
- 空值与默认值:
- 业务错误码:
- 时间/金额/分页/幂等语义:
- 后端证据:
- Gateway
- Router / Controller
- DTO / Service
- Test / Doc
- Flutter 落地:
- repository/api
- model
- manager/provider
- view
- test
- 待后端确认:
- 当前状态:未对接 / 对接中 / 已对接 / 等后端
```
---
## 11. 验证规范
### 11.1 静态与自动化验证
只格式化本次改动的 Dart 文件,然后执行:
```bash
flutter analyze
flutter test
```
网络 envelope 或通用解析改动至少运行:
```bash
flutter test test/network_response_data_test.dart
```
业务 Model 改动应运行或新增对应 `*_test.dart`;不能只依赖 Widget 手工观察。
### 11.2 真实接口联调
至少验证:
1. 实际请求 method/path 与 Gateway 转发后 path 正确。
2. 需鉴权接口携带当前 Bearer Token无 Token/失效 Token 进入错误态。
3. 成功、真实空数据、业务失败、HTTP 失败、超时、解析失败各至少覆盖相关分支。
4. 重复点击、翻页、刷新和页面销毁不会产生重复写入或过期状态覆盖。
5. 接口失败时页面不出现本地假数据,也不把失败当作空数据。
6. 错误信息可理解、可重试,且日志不包含敏感信息。
### 11.3 回归影响
每次交付要明确说明:
- 是否修改公共 `NetworkClient``ResponseData`、公共 Header 或 Token 处理。
- 是否影响旧哈希路由、明文路由或 base URL override。
- 是否影响其他共用 Model、Repository、Provider 或实时消息。
- 针对上述影响执行了哪些测试,结果是什么。
---
## 12. 后端问题流转
出现以下情况时Flutter 不修改后端:
- Gateway 路由与 Router/Controller 不一致。
- Java/Go 响应字段、可空性、数值类型或枚举不一致。
- HTTP 状态码、`errorCode/code` 和业务语义不能支持前端分支。
- 鉴权、幂等、分页、排序、时区、时间单位或金额单位不清晰。
- Go 路由存在但 Java Gateway 没有可到达转发。
- 后端仅有占位实现、返回 mock或所需下游能力未上线。
记录模板:
```text
- 【待后端确认业务模块YYYY-MM-DD HH:mm CST】
问题:
现象:
证据:
- Gateway
- Java / Go
- Flutter
Root Cause 判断:
前端影响:
建议后端处理:
联调验收条件:
```
---
## 13. 文档维护要求
- 本文档记录稳定规则;具体接口事实应写入对应业务文档,避免把本文档变成无法维护的接口大全。
- 引用后端证据时写明仓库和相对路径,必要时补充类/函数名,不复制大段实现。
- 不在文档中记录真实 Token、密码、密钥、DSN、云服务凭证或内网敏感信息。
- 后端路由或响应契约变更后,同步更新相关业务接口记录和验证日期。
- 文档中的“已对接”必须同时满足Flutter 代码已落地、自动化验证通过、真实接口联调通过、不存在本地假数据兜底。