457 lines
18 KiB
Markdown
457 lines
18 KiB
Markdown
# 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 Gateway(API_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 代码已落地、自动化验证通过、真实接口联调通过、不存在本地假数据兜底。
|