--- name: 邀请回调改MQ overview: 将 agent → console 的 Lucky Rewards 邀请助力从 HTTP innerapi 改为经 `console_bus` MQ 投递;删除 innerapi 与 slot_sdk 对应方法;console EventBus 消费后复用现有 `LuckyRewardInviteLogic::handleInviteBind()`。 todos: - id: agent-mq-producer content: "slot_agent: Gateway 改发 console_bus MQ + MQBusEntity 常量" status: completed - id: console-consumer content: "slot_console: EventBus 消费 TYPE_LUCKY_REWARD_INVITE_BIND + 删 innerapi Controller" status: completed - id: sdk-cleanup content: "slot_sdk: 删除 luckyRewardInviteBindCallback 及 Entity" status: completed - id: tests-docs-mq content: 单测 + 需求/deploy 文档更新 status: completed isProject: false --- # Agent 邀请回调改走 console_bus MQ ## 目标 - **删除**:`POST /innerapi/lucky-reward/invite-bind-callback`、slot_sdk `luckyRewardInviteBindCallback` - **新增**:agent 发 MQ → console `event:bus` 消费 → 发 Spin / helper - **复用**:[`LuckyRewardInviteLogic::handleInviteBind()`](slot_console/app/api/logic/LuckyRewardInviteLogic.php) 业务不变;仍仅 `share_origin=wheel` 计转盘助力 ```mermaid sequenceDiagram participant User as slot_user participant AgentBus as agent_bus participant Agent as slot_agent participant ConsoleBus as console_bus participant Console as slot_console User->>AgentBus: TYPE_INVITE_BIND Agent->>AgentBus: 建关系/绑码奖励 Agent->>ConsoleBus: TYPE_LUCKY_REWARD_INVITE_BIND Console->>Console: handleInviteBind ``` 对照现网邮件:[`EventBus::notifyRewardEmail()`](slot_agent/app/command/EventBus.php) 已用 `EXCHANGE_CONSOLE` + `QUEUE_CONSOLE_BUS`。 --- ## 1. MQ 契约 **Exchange / Queue**(与现网一致): - Exchange: `slot_console`(`MQKeyManagerService::EXCHANGE_CONSOLE`) - Queue: `console_bus`(`MQKeyManagerService::QUEUE_CONSOLE_BUS`) **新事件类型**(agent、console 两侧常量字符串一致): ```php const TYPE_LUCKY_REWARD_INVITE_BIND = 'lucky_reward_invite_bind'; ``` **消息体**(与现 HTTP body 同形,便于 DTO 复用): ```json { "uid": 2001, "type": "lucky_reward_invite_bind", "data": { "event_id": "invite_bind:2001", "inviter_uid": 100, "invitee_uid": 2001, "invite_code": "ABC123", "channel_code": "default", "bind_time": 1710000000, "share_origin": "wheel", "is_new_register": 1, "landing_scene": "", "landing_token": "" } } ``` - `uid` = **被邀请人** `invitee_uid`(对齐其它 console_bus 消息) - `event_id` 仍用 `invite_bind:{invitee_uid}` 幂等 --- ## 2. slot_agent(生产者) **重构** [`LuckyRewardInviteCallbackGatewayService`](slot_agent/app/service/LuckyRewardInviteCallbackGatewayService.php): | 变更 | 说明 | | --- | --- | | 删除 | `ConsoleClient`、slot_sdk Entity、`consoleApiHost`、HTTP 重试 | | 保留 | `isEnabled` 开关、`share_origin=wheel` 粗筛、参数校验 | | 新增 | `RabbitMqService::getInstance(EXCHANGE_CONSOLE, QUEUE_CONSOLE_BUS)->sendMessageByBusEntity(...)` | [`MQBusEntity`](slot_agent/app/entity/mq/MQBusEntity.php) 增加 `TYPE_LUCKY_REWARD_INVITE_BIND`。 [`LuckyRewardInviteCallbackResultEntity`](slot_agent/app/entity/lucky_reward/LuckyRewardInviteCallbackResultEntity.php): - `dispatched=true` 表示 **MQ 发送成功** - `reason`:`mq_failed` 替代 `http_failed`;去掉 `console_api_host_empty` **触发点不变**: - [`EventBus::inviteBindEvent()`](slot_agent/app/command/EventBus.php)(新建关系) - [`AgentLogic::bindInviteCode()`](slot_agent/app/innerapi/logic/AgentLogic.php)(手工绑码补偿) **配置**:[`LuckyRewardInviteCallbackConfigService`](slot_agent/app/service/LuckyRewardInviteCallbackConfigService.php) 可移除 `timeout`/`retrySleep`(HTTP 专用);保留 `lucky_reward_callback_enabled`。 --- ## 3. slot_console(消费者) **[`MQBusEntity`](slot_console/app/entity/mq/MQBusEntity.php)**:增加 `TYPE_LUCKY_REWARD_INVITE_BIND`。 **[`EventBus::deal()`](slot_console/app/command/EventBus.php)**:新增 `case`,调用 private `luckyRewardInviteBindEvent(int $uid, array $data)`: ```php $callbackDto = InviteBindCallbackDTO::fromRequest($busEntity->data); $result = (new LuckyRewardInviteLogic())->handleInviteBind($callbackDto); LoggerService::info('lucky_reward_invite_bind', $result->activeData()); ``` **[`InviteBindCallbackDTO`](slot_console/app/dto/luckyReward/InviteBindCallbackDTO.php)**:`fromRequest()` 已可读 MQ `data` 数组,无需改签名;PHPDoc 注明 HTTP/MQ 共用。 **ack 策略**(对齐业务语义,非 5xx 不重试): - `handleInviteBind` 正常返回(含 `skipped_*`、`already_processed`)→ **ack** - 未捕获 `Throwable`(DB 异常等)→ **log + ack**(与多数 console_bus 分支一致;避免无限 requeue)。若需失败重试可后续单独加 dead-letter,本期不扩 scope。 **删除** [`app/innerapi/controller/LuckyRewardController.php`](slot_console/app/innerapi/controller/LuckyRewardController.php)(仅此一个 action)。 --- ## 4. slot_sdk(清理) 删除或不再使用: - [`ConsoleService::luckyRewardInviteBindCallback()`](slot_sdk/src/service/console/ConsoleService.php) - [`LuckyRewardInviteBindCallbackRequestEntity`](slot_sdk/src/service/console/entity/LuckyRewardInviteBindCallbackRequestEntity.php) - [`LuckyRewardInviteBindCallbackResultEntity`](slot_sdk/src/service/console/entity/LuckyRewardInviteBindCallbackResultEntity.php) 保留 `freeCreditsStatistics/list`(admin 仍用)。 agent `composer.json` 若仅为该回调依赖 console SDK 路径,无需改依赖(agent 仍可能间接用 slot_sdk 其它能力)。 --- ## 5. 测试 | 仓库 | 用例 | | --- | --- | | slot_console | 新增 `EventBusLuckyRewardInviteBindTest`:mock AMQPMessage,`type=lucky_reward_invite_bind`,断言调用 Logic / ack(参考 [`EventBusFreeCreditInitTest`](slot_console/tests/Unit/EventBusFreeCreditInitTest.php)) | | slot_console | 现有 [`LuckyRewardInviteBindIntegrationTest`](slot_console/tests/Integration/LuckyRewardInviteBindIntegrationTest.php) 继续直调 Logic,不受影响 | | slot_agent | 单测 Gateway:wheel 发 MQ、user_agent skip、disabled 不发(可 mock RabbitMqService 或测 payload 组装 private 方法) | --- ## 6. 文档 - [01_slot_agent邀请回调对接方案.md](docs/requirements/lucky_rewards/01_slot_agent邀请回调对接方案.md):HTTP 改 MQ 时序图、删除 §6.1 innerapi - [05](docs/requirements/lucky_rewards/05_slot_console_邀请助力与弹窗方案.md) §3:接收方式改为 console_bus - [00](docs/requirements/lucky_rewards/00_整体技术方案.md) §3.5 时序图:Agent→Console 改为 MQ - [lucky_reward_deploy.md](slot_console/doc/lucky_reward_deploy.md):去掉 `consoleApiHost`(agent 调 console)与 innerapi 冒烟项;补充 console `event:bus` 需运行 --- ## 7. 部署注意 - **无需** agent 配置 `consoleApiHost`(仅此回调) - **必须** slot_console `php webman event:bus` 消费 `console_bus`(与邮件、注册等共用进程) - 发版顺序建议:**console 先上消费** → **agent 再切 MQ 生产**,避免短暂消息无人消费(旧 agent HTTP + 新 console 无 innerapi 窗口) --- ## 涉及文件摘要 **改**:`slot_agent` Gateway + MQBusEntity + Config;`slot_console` EventBus + MQBusEntity **删**:`slot_console/app/innerapi/controller/LuckyRewardController.php`;slot_sdk 3 个 invite callback 文件 **不动**:`LuckyRewardInviteLogic` 核心判定、C 端 `/api/*`