This commit is contained in:
ray zhou
2026-06-29 14:51:55 +08:00
parent 225fb2bd28
commit 2dd9f17da9
319 changed files with 29461 additions and 9412 deletions

View File

@@ -0,0 +1,118 @@
---
name: Console innerapi 架构说明
overview: 说明 slot_console 在本项目中的双重角色C 端 BFF + 活动域服务slot_sdk ConsoleClient 仅封装 `/innerapi/*` 供后端互调;若要坚持「纯 BFF 不被后端调用」,需拆分活动域或改异步回调。
todos: []
isProject: false
---
# slot_console 为何可被 slot_sdk 调用?
## 结论(先答你的疑问)
**可以给别人调,但调的不是「给 App 用的 BFF 接口」,而是同一进程里的 `/innerapi/*` 内部契约。**
在本仓库里,`slot_console` **不是纯 BFF**,而是:
| 路由前缀 | 中间件 | 谁调用 | 职责 |
| --- | --- | --- | --- |
| `/api/*` | `AuthMiddleware`JWT | **C 端 App/PWA** | BFF聚合 user/wallet/agent暴露 Lucky Rewards 等 C 端 API |
| `/innerapi/*` | `InnerAuthMiddleware` | **其它后端**agent、admin、pwa… | 活动域/内部能力:统计、邮件、游戏历史、**邀请回调** |
| `/napi/*` | `NAuthMiddleware` | 大厅等 | 非 C 端 JWT 的另一套入口 |
[`slot_sdk` 的 `ConsoleClient`](slot_sdk/src/service/console/ConsoleClient.php) 注释已写明:**「slot_console 内部 API 客户端」**,封装的是 `innerapi/...`,不是 `api/lucky-reward/spin` 这类 C 端路径。
```mermaid
flowchart LR
subgraph clients [调用方]
App[C端App]
Agent[slot_agent]
Admin[slot_admin]
end
subgraph console [slot_console]
ApiLayer["/api/* BFF"]
InnerLayer["/innerapi/* 域服务"]
Logic[LuckyRewardInviteLogic等]
end
App --> ApiLayer
Agent -->|"ConsoleClient via slot_sdk"| InnerLayer
Admin --> InnerLayer
ApiLayer --> Logic
InnerLayer --> Logic
```
---
## slot_sdk 里 console 接口是干什么的?
当前 [`ConsoleService`](slot_sdk/src/service/console/ConsoleService.php) 只有三类 **innerapi**
1. `innerapi/free-credits/statistics|list`**slot_admin** 后台统计代理
2. `innerapi/lucky-reward/invite-bind-callback`**slot_agent** 邀请绑定后回调转盘助力
**实际调用方**(仓库内):
- [`LuckyRewardInviteCallbackGatewayService`](slot_agent/app/service/LuckyRewardInviteCallbackGatewayService.php) → agent 调 console
- [`ConsoleAPIService`](backend/slot_admin/app/service/api/ConsoleAPIService.php) / Free Credits 统计 → admin 调 console
- [`slot_pwa` ConsoleService](slot_pwa/app/service/console/ConsoleService.php) → `innerapi/game/update-history`
C 端 **不会****不应该** 通过 slot_sdk 调 consoleC 端直接打 `consoleApiHost``/api/*`
---
## 为什么 agent 要调 console而不是反过来
这是 Lucky Rewards 需求里**刻意**定的边界(见 [01 文档](docs/requirements/lucky_rewards/01_slot_agent邀请回调对接方案.md)、[00 §1](docs/requirements/lucky_rewards/00_整体技术方案.md)
- **agent**:只管邀请关系、代理树、绑码奖励(通用裂变)
- **console**:拥有转盘业务状态(`lucky_reward_player`、Spin、helper、弹窗
- 邀请绑定成功后agent 广播「关系已建立」→ console **裁决**是否算转盘有效助力并发 Spin
所以不是「BFF 被乱调」,而是 **活动域挂在 console 上**agent 通过 innerapi 触发 console 内的 [`LuckyRewardInviteLogic::handleInviteBind()`](slot_console/app/api/logic/LuckyRewardInviteLogic.php)。
`/api``/innerapi` 可以共用同一套 Logicinvite 回调与 C 端 invite-link 都走 `LuckyRewardInviteLogic`),只是入口和鉴权不同。
---
## 「console 是 BFF」和现状如何对齐
更准确的说法:
- **对 C 端**console 的 `/api/*` 承担 BFF薄 Controller + Logic 编排 + 调 user/wallet/agent SDK
- **对活动数据**console 同时是 **活动域 owner**(表在 `s_common`,逻辑在 console历史上 Free Credits、签到、红包等同构
- **innerapi** = 把「活动域能力」暴露给 **trusted backend**,不是给浏览器/App
因此 slot_sdk 出现 `ConsoleClient` 与「console 有 BFF 职责」**不矛盾**——SDK 封装的是 **服务间** 调用,符合 [cross-service-sdk 规则](.cursor/rules/cross-service-sdk.mdc)(调用方用 slot_sdk被调方实现 innerapi Controller/Logic
---
## 若你认为「BFF 绝不能被后端调」——可选演进(非现状)
只有当你要把 console **严格降级为纯 BFF** 时,才需要改架构;代价是拆服务或改通信方式:
| 方案 | 做法 | 优缺点 |
| --- | --- | --- |
| **A. 拆 slot_activity** | 转盘域独立服务console 只转发 C 端agent 调 activity 而非 console | 边界最清晰;迁移成本高 |
| **B. MQ 替代 HTTP 回调** | agent 发 `lucky_reward_invite_bind` MQconsole 消费 | 解耦、可重试;需 MQ 契约与消费幂等 |
| **C. 维持现状** | console = BFF + 活动域innerapi 仅 trusted 服务 | **当前实现**;与现网 Free Credits innerapi 一致 |
**建议**:除非全站统一「活动全部拆独立服务」,否则 **C 方案是本项目既定模式**,不必因 slot_sdk 有 ConsoleClient 而视为设计错误。
---
## 安全与边界(现状)
- innerapi 走 [`InnerAuthMiddleware`](slot_console/app/middleware/InnerAuthMiddleware.php)(内网 + 日志;生产通常靠网络隔离 + `server-name` 头标识调用方)
- agent 回调带 `server-name: agent`(见 [deploy 文档](slot_console/doc/lucky_reward_deploy.md)
- **禁止**:在 agent/user 等业务代码里手写 `consoleApiHost + path` 字符串;应走 slot_sdk与 wallet/user 一致)
---
## 无需改代码时的认知对齐
1. **slot_sdk ConsoleClient ≠ C 端调 console**
2. **console `/api` = BFF`/innerapi` = 活动域对后端开放**
3. **agent → console** 是转盘需求文档明确的服务边界,不是临时 hack
若你后续希望 **agent 不再 HTTP 调 console**,再单独立项做方案 BMQ或方案 A拆服务当前代码与文档是一致的。