6.2 KiB
6.2 KiB
name, overview, todos, isProject
| name | overview | todos | isProject | |||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 注册奖励随机游戏 | 在 slot_console 注册活动(type=7)领取成功响应中,从活动 ext_config.game_ids 配置的候选池里,按当前渠道 game_model_id 过滤已上架游戏后随机返回 game_id,供前端直接进游戏。 |
|
false |
注册奖励领取后随机返回 game_id
背景与范围
- 入口:
POST /api/gift/receive→ActivityConfigEntity::receive()中ACTIVITY_TYPE_REG(type=7)。 - 不在范围:注册自动到账(
UserRegisterEventService)、后台 Vue 配置页、前端进游戏逻辑。 - 配置来源(已确认):活动表
s_recharge_gift_config.ext_config.game_ids。
当前领取成功仅返回金额:
return ['gift_coin' => CommonFn::getNumberFormat($giftAmount), 'gift_bonus' => CommonFn::getNumberFormat($giftBonus)];
game_id 语义与大厅一致:s_game_api.game_id = game.id,前端用该 ID 调 POST /api/game/login 的 gameId 或 napi 搜索同款字段。
配置契约
在对应注册活动(type=7)的 ext_config 中增加:
{
"game_ids": [101, 205, 308]
}
game_ids:int[],运营在 DB/后台 JSON 中维护;本任务不实现 admin UI。- 未配置、空数组、或过滤后无有效游戏:不阻断领取,响应中 省略
game_id字段(与withdraw_guide用0不同,避免前端误开游戏)。
数据流
sequenceDiagram
Client->>GiftController: POST /api/gift/receive id=activityId
GiftController->>ActivityConfigEntity: receive()
ActivityConfigEntity->>WalletService: gift() 注册赠送入账
ActivityConfigEntity->>RegisterRewardLogic: pickRandomGameId(ext_config, gameModelId)
RegisterRewardLogic->>GameApiModel: 过滤 status=1 且已发布
RegisterRewardLogic-->>ActivityConfigEntity: game_id|null
ActivityConfigEntity-->>Client: gift_coin, gift_bonus, game_id?
实现要点
1. 新增 Logic:随机选游戏
新建 slot_console/app/api/logic/RegisterRewardLogic.php(参考 FreeCreditsLogic 的独立 Logic 拆分方式):
| 方法 | 职责 |
|---|---|
pickRandomGameId(array|null $extConfig, int $gameModelId): ?int |
解析 game_ids → 去重/转 int → 调 Model 过滤 → array_rand 返回一个 id |
解析规则:
- 支持
game_ids为 JSON 数组或逗号分隔字符串(防御性,与部分旧配置风格兼容)。 - 非法/非正整数丢弃。
2. Model:候选池与渠道上架交集
在 GameApiModel 增加查询方法,例如:
public static function publishedGameIds(int $gameModelId, array $gameIds): array
条件:game_id IN (...)、game_model_id = $gameModelId、status = STATUS_ON;返回可用 game_id 列表。
不在 Logic 里直接拼 SQL,符合分层规则。
3. 改动领取分支
在 ActivityConfigEntity::receive() 的 ACTIVITY_TYPE_REG case:
- 发奖逻辑保持不变(
WalletService::gift+sendRegisterGiftWagerTask+setActivityFinishById)。 - 仅在
$res非空(领取成功)后:- 用
$this->where('id', $activityId)->find()读取原始ext_config(getActivityByInfo()经getGiftItemsByActivity组装,不含 ext_config,与兑换码分支读库方式一致)。 $gameModelId = $this->_modelId(已由setSource设置)。- 调用
RegisterRewardLogic::pickRandomGameId()。
- 用
- 在方法末尾统一组装返回:有值则追加
'game_id' => $pickedId。
GiftController::receive() 补充 PHPDoc:data.game_id(int,可选,领取注册活动成功且配置了有效候选池时返回)。
4. 响应示例
成功且命中游戏:
{
"code": 0,
"data": {
"gift_coin": "10.00",
"gift_bonus": "0.00",
"game_id": 205
}
}
成功但无可用游戏:仅 gift_coin / gift_bonus(与现网兼容)。
单测
新建 slot_console/tests/Unit/RegisterRewardLogicTest.php:
game_ids为空 / 缺失 →null- 字符串
"1,2,3"解析 - Model 层可用 stub 或 sqlite/内存 mock(若项目已有 GameApi 测试惯例则对齐)
在 docker 内执行:
docker exec -w /app/www/slot/slot_console php82 ./vendor/bin/phpunit tests/Unit/RegisterRewardLogicTest.php
运维配置说明(无 UI)
对目标渠道 type=7 活动,更新 s_recharge_gift_config.ext_config:
-- 示例:在现有 ext_config 上合并 game_ids
UPDATE s_recharge_gift_config
SET ext_config = JSON_SET(COALESCE(ext_config, '{}'), '$.game_ids', JSON_ARRAY(101, 205))
WHERE id = <activity_id> AND type = 7;
game_ids 须为当前 model_id 下已在 s_game_api 上架的 game.id。
风险与边界
| 场景 | 行为 |
|---|---|
| 配置了已下架/未发布游戏 | 从池中剔除;池空则不下发 game_id |
| 重复领取 | 现有 Is Got 拦截,不会二次随机 |
| 多注册活动同渠道 | 按请求的 id 读对应活动 ext_config |
后续可选(本任务不做)
- slot_admin 活动编辑页 type=7 增加「推荐游戏」多选,写入
ext_config.game_ids getActivityList预展示候选游戏(非领取必需)