# 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`。 - 仓储接口:`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//`:按业务模块拆分的业务逻辑。 - `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/_routes.go`:确认 method/path、鉴权中间件、query/path/body 绑定。 2. `internal/service//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 时) - `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` 当前兼容两类字段: ```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 代码已落地、自动化验证通过、真实接口联调通过、不存在本地假数据兜底。