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,178 @@
---
name: 转盘与Agent分享归因
overview: 实现「转盘分享双计agent + 转盘、agent 分享仅计 agent」wheel 与 user_agent 各一条 share_url 短码MQ 的 share_origin 直接来自 invite_code 查表console 仅 share_origin=wheel 时发转盘助力。
todos:
- id: console-origin
content: "slot_console: wheel 独立落库 origin=wheelLogic 仅 wheel 计助力invite-link/createShareUrl 走 wheel 短码"
status: completed
- id: user-mq
content: "slot_user: shouldNotifyAgentByInviteOrigin 含 wheelMQ share_origin 来自 share_url.origin"
status: completed
- id: agent-filter
content: "slot_agent建议: console 回调粗筛 share_origin=wheel"
status: completed
- id: tests-docs
content: 单测/集成测 + 需求文档/YApi/deploy 对齐(撤销 wheel→user_agent 映射说明)
status: completed
isProject: false
---
# 转盘分享 vs Agent 分享单向归因方案share_origin 双短码)
## 产品规则SSOT
| 分享入口 | share_url.origin | Agent 邀请 | Lucky Rewards 助力 |
| --- | --- | --- | --- |
| 转盘分享(`from=wheel` / invite-link | `wheel` | 算 | 算 |
| Agent 分享(`from=user_agent` | `user_agent` | 算 | **不算** |
## 方案选型(已确认)
**方案 A两条短码**`wheel``user_agent``share_url` 各存一行,同一邀请人可有 **两个** `short_code`
- MQ `share_origin` 由注册时 `invite_code``share_url.origin` 得到,**无需** `landing_scene`、**无需** FE 注册透传额外字段。
- 撤销当前 [`ShareService::resolvePersistOrigin()`](slot_console/app/service/ShareService.php) 把 `wheel → user_agent` 的映射。
```mermaid
sequenceDiagram
participant Inviter
participant Console as slot_console
participant User as slot_user
participant Agent as slot_agent
alt WheelShare
Inviter->>Console: createShareUrl from=wheel
Console->>Console: share_url origin=wheel 短码W
Note over Inviter: 分享短码W
User->>User: register invite_code=W
User->>Agent: MQ share_origin=wheel
Agent->>Console: callback share_origin=wheel
Console->>Console: success发Spin
else AgentShare
Inviter->>Console: createShareUrl from=user_agent
Console->>Console: share_url origin=user_agent 短码A
User->>User: register invite_code=A
User->>Agent: MQ share_origin=user_agent
Agent->>Console: callback share_origin=user_agent
Console->>Console: skipped_not_wheel
Note over Agent: agent关系照常
end
```
---
## 为何之前不能「只改 MQ 不改落库」
当前实现把 `from=wheel` **映射成** `user_agent` 落库(复用一条短码)。此时代码查表得到的 `origin` 永远是 `user_agent`MQ 无法出现 `share_origin=wheel`,除非 FE 在注册时强行覆盖 —— 那与 `landing_scene` 同类,且语义与 DB 不一致。
**双短码**后:`invite_code` 本身即归因,链路最简。
---
## 实现步骤
### 1. slot_consolewheel 独立短码 + 助力判定
**[`ShareService`](slot_console/app/service/ShareService.php)**
- **删除或停用** `resolvePersistOrigin()` 对 wheel 的 `user_agent` 映射;`SHARE_FROM_WHEEL` 直接作为 `createUrl()``$from` / `ShareUrlModel.origin`
- `isAgentShareFrom()` 保持 `user_agent` + `wheel`agent 文案接口仍适用)。
- 更新/替换 [`ShareServiceWheelFromTest`](slot_console/tests/Unit/ShareServiceWheelFromTest.php):断言 wheel 创建后 `origin=wheel`,且与 `user_agent` 为**不同** `short_code`(同一 uid 两行)。
**[`GiftController::createShareUrl()`](slot_console/app/api/controller/GiftController.php)**
- `from=wheel``createUrl(ShareService::SHARE_FROM_WHEEL)`,不再经 `resolvePersistOrigin`
**[`LuckyRewardInviteLogic::buildInviteLink()`](slot_console/app/api/logic/LuckyRewardInviteLogic.php)**
- 同上,直接 `createUrl(SHARE_FROM_WHEEL)`
- PHPDoc 更新:不再写「落库复用 user_agent 短码」。
**[`LuckyRewardInviteLogic::handleInviteBind()`](slot_console/app/api/logic/LuckyRewardInviteLogic.php)**
- 将现有「必须 `share_origin=user_agent`」改为 **必须 `share_origin=wheel`**
```php
if ($callbackDto->shareOrigin !== ShareService::SHARE_FROM_WHEEL) {
return $this->buildInviteBindResult(
InviteBindResultEntity::STATUS_SKIPPED_NOT_WHEEL,
'Invite code origin is not wheel'
);
}
```
**[`InviteBindResultEntity`](slot_console/app/entity/luckyReward/InviteBindResultEntity.php)**
- 新增 `STATUS_SKIPPED_NOT_WHEEL = 'skipped_not_wheel'`(保留旧 `skipped_not_user_agent` 常量亦可,新逻辑用新 status
- **不需要** `landing_scene` / `skipped_no_landing`(除非后续另有用途)。
**[`InviteBindCallbackDTO`](slot_console/app/dto/luckyReward/InviteBindCallbackDTO.php)**
- 已有 `shareOrigin`,无需新增 `landingScene`agent/SDK 侧 landing_scene 字段可留空,不读)。
### 2. slot_user发 MQ + agent 资格
**[`AbstractRegisterService::shouldNotifyAgentByInviteOrigin()`](slot_user/app/service/register/AbstractRegisterService.php)**
```php
return in_array($origin, ['user_agent', 'wheel'], true);
```
**[`notifyAgentInviteBind()`](slot_user/app/service/register/AbstractRegisterService.php)**
- `share_origin` 继续写 `$this->invite_share_origin`(来自 `share_url.origin`wheel 注册自然为 `wheel`
- **无需**新增 `landing_scene` 属性或 MQ 字段(与 agent 侧已有 `landing_scene` 字段兼容即可,留空)。
**[`resolveInviteUidByInviteCode()`](slot_user/app/service/register/AbstractRegisterService.php)** — 已读 `shareRow->origin`,双短码下无需改逻辑。
### 3. slot_agentconsole 回调粗筛(建议)
[`LuckyRewardInviteCallbackGatewayService::canNotifyInviteBind()`](slot_agent/app/service/LuckyRewardInviteCallbackGatewayService.php) 增加:
-`share_origin === 'wheel'` 时 HTTP 调 consoleagent 绑定、奖励、关系同步**不受影响**,仍处理全部 invite_bind MQ
- `user_agent` 绑定不再打 console减少无效请求。
### 4. 前端 / 产品说明
- 转盘页 Copy Link / 社媒分享:使用 **invite-link****create-share-url `from=wheel`** 返回的 `code`wheel 短码)。
- Agent 中心分享:继续使用 **`from=user_agent`** 返回的 `code`(另一条短码)。
- **不要混用**:用 agent 短码进转盘页,只计 agent、不计转盘 —— 符合产品规则。
### 5. 测试
| 仓库 | 用例 |
| --- | --- |
| slot_console | `ShareServiceWheelFromTest`:同 uid 存在 wheel + user_agent 两行、短码不同 |
| slot_console | `LuckyRewardInviteLogicUnitTest``share_origin=user_agent``skipped_not_wheel``wheel` + 新注册 → success |
| slot_console | `LuckyRewardInviteBindIntegrationTest``buildValidInviteBindPayload()``share_origin``wheel` |
| slot_user | `shouldNotifyAgentByInviteOrigin`wheel / user_agent 为 true其它为 false |
### 6. 文档与 YApi
- 更新 [`05_slot_console_邀请助力与弹窗方案.md`](docs/requirements/lucky_rewards/05_slot_console_邀请助力与弹窗方案.md) §2有效助力 = **新注册** + **`share_origin=wheel`**(双短码,非 landing_scene
- 更新 [`00_整体技术方案.md`](docs/requirements/lucky_rewards/00_整体技术方案.md) 归因段落。
- [`lucky_reward_deploy.md`](slot_console/doc/lucky_reward_deploy.md)、YApi **81** / invite-link说明 wheel 与 user_agent **不同 code**;撤销「复用 user_agent 短码」描述。
- innerapi 回调文档:`skipped_not_wheel``landing_scene` 标注为可选/未使用。
---
## 判定优先级console 更新后)
1. invalid_params
2. skipped_self_invite
3. skipped_old_user
4. **skipped_not_wheel**(原 skipped_not_user_agent 逻辑替换)
5. activity_closed
6. already_processed
7. success
---
## 风险与边界
- **历史已发出的 wheel 链接**:若当时用的是映射后的 `user_agent` 短码,升级后只计 agent、不计转盘新 wheel 链接需走 invite-link / `from=wheel` 拿新短码。可在发版说明中写清。
- **同一用户两条码**:运营/客服需知 wheel 与 agent 链接不可互换。
- **手工绑码**`share_url.origin` 决定 MQ `share_origin`;绑 agent 码不计转盘。
- **slot_sdk / agent** `landing_scene` 字段保留兼容,本期不参与判定。
---
## 涉及仓库
- **必改**`slot_console``slot_user`
- **建议改**`slot_agent`HTTP 粗筛 `share_origin=wheel`
- **不改**`slot_sdk`(已有 share_origin 转发)
- **FE**:使用正确短码即可,无 register 额外字段