124 lines
7.6 KiB
Markdown
124 lines
7.6 KiB
Markdown
# Aslan 礼物挑战活动接口
|
||
|
||
## 接入约定
|
||
|
||
- H5 基础路径:`/activity/gift-challenge/aslan`
|
||
- WebConsole 基础路径:`/activity/gift-challenge`
|
||
- H5 请求必须经过网关并携带 `Authorization: Bearer ...`、`Req-Sys-Origin: ATYOU`、
|
||
`Req-Client` 和 `Req-App-Intel`。用户 ID 与来源由网关注入,接口不接收客户端 userId。
|
||
- 时间均为毫秒时间戳;日榜日期是活动 `timeZone` 下的 `yyyy-MM-dd`。
|
||
- 单个活动最多覆盖 366 个活动时区自然日;首次启用会批量幂等预建全部 DAILY 结算门闩,
|
||
因此没有任何参与者的日期也会按时冻结为空榜。
|
||
- 启用会冻结任务、排名区间所引用资源组的完整奖励配置(发放字段和 H5 展示字段),最多
|
||
5000 个奖励项。总榜结算开始前,即使活动已经进入或走完时间窗,WebConsole 仍可修改
|
||
时间、时区、任务、榜单和奖励;新配置只影响之后的事件和尚未物化/冻结的数据。
|
||
- 已生成用户任务、已冻结日榜、榜奖 parent 和 delivery item 永不回写;这些记录引用的
|
||
奖励组快照始终保留。同一已引用资源组不会刷新,修改奖励内容必须选择新的资源组。
|
||
- `dailySettlementDelayMinutes` 与 `overallSettlementDelayMinutes` 是有界迟到窗口,不是无限
|
||
追溯。结算门闩开始后对应榜单不再接受迟到写入;执行自动或人工结算前必须监控
|
||
`ASLAN_GIFT_CHALLENGE_GIFT` consumer group lag,确认落后量已进入可接受范围。
|
||
- 积分直接消费原始送礼事件:仅 `ATYOU + GOLD + 非背包 + amount > 0`,强制排除
|
||
`LUCKY_GIFT` 与 `MAGIC`,并且事件时间满足 `[startTime, endTime)`。金额固定使用
|
||
`GiveAwayGiftBatchEvent.countConsumAmountTotal()`,与礼物主流水口径一致。
|
||
|
||
## H5 接口
|
||
|
||
### 1. 活动详情
|
||
|
||
`GET /activity/gift-challenge/aslan/detail?activityId={id}`
|
||
|
||
- `activityId` 可选;缺省时返回当前进行中、最近待开始或最近结束的已启用活动。
|
||
- 返回 `activity`、三个任务配置、`DAILY/OVERALL` 排名奖励、活动状态和服务端时间。
|
||
- 本接口不修改任务;H5 打开页面后必须调用 `/enter`。
|
||
|
||
### 2. 每日进入并读取用户状态
|
||
|
||
`POST /activity/gift-challenge/aslan/enter`
|
||
|
||
```json
|
||
{
|
||
"activityId": "1234567890123456789"
|
||
}
|
||
```
|
||
|
||
- 服务端按活动时区创建当天三个任务快照,并幂等完成所有 `ENTER_PAGE` 任务。
|
||
- 返回 `activityId`、`statDate`、总积分、今日积分、日榜/总榜名次以及三个任务状态。
|
||
- 重复进入不会重复累计,也不会改变 `SEND_GIFT_GOLD` 任务进度。
|
||
|
||
### 3. 排行榜
|
||
|
||
`GET /activity/gift-challenge/aslan/ranking?activityId={id}&period={DAILY|OVERALL}&statDate={yyyy-MM-dd}&limit=100`
|
||
|
||
- `period` 缺省为 `DAILY`。
|
||
- `statDate` 只对 `DAILY` 生效;缺省时自动选择活动窗口内的当前、首日或末日。
|
||
- `limit` 最终受活动 `displayTopN` 和服务端最大值 500 双重限制。
|
||
- 返回 `entries`、`my`、`settled`;排序固定为积分降序、达到当前积分时间升序、userId 升序。
|
||
- 神秘人能力用户不出现在其他用户看到的公开榜单中,但本人仍可看到自己的排名。
|
||
|
||
### 4. 领取每日任务奖励
|
||
|
||
`POST /activity/gift-challenge/aslan/tasks/{taskCode}/claim`
|
||
|
||
```json
|
||
{
|
||
"activityId": "1234567890123456789",
|
||
"requestId": "h5-generated-request-id"
|
||
}
|
||
```
|
||
|
||
- 任务必须属于当前活动日并且已完成。
|
||
- `taskCode` 只允许 `A-Z/a-z/0-9/_/-`,长度 1 到 64,保证它可安全作为 URL 路径段。
|
||
- 活动日任务行和逐奖励项 delivery item 是幂等边界;重复请求不会重复发放成功项。
|
||
- 首次成功抢占领取状态的 `requestId` 会写入任务日快照作为审计号;它不替代服务端任务行
|
||
和 delivery item 的发奖幂等边界。
|
||
- 发奖结果不确定时任务进入 `UNKNOWN`,H5 不会自动重发,需运营在后台核账。
|
||
- 返回最新的完整用户状态。
|
||
|
||
## WebConsole 接口
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
| --- | --- | --- |
|
||
| GET | `/activity/gift-challenge/list` | 活动列表 |
|
||
| GET | `/activity/gift-challenge/detail/{id}` | 活动、任务、排名奖励详情 |
|
||
| POST | `/activity/gift-challenge/save` | 新增或按 version 乐观锁更新活动 |
|
||
| PUT | `/activity/gift-challenge/enable/{id}?enabled=true` | 启停活动 |
|
||
| GET/PUT | `/activity/gift-challenge/tasks/{id}` | 查询或保存恰好三个任务槽 |
|
||
| GET/PUT | `/activity/gift-challenge/rank-rewards/{id}` | 查询或保存日榜/总榜奖励区间 |
|
||
| GET | `/activity/gift-challenge/ranking/{id}` | 查询实时或冻结榜单 |
|
||
| GET | `/activity/gift-challenge/settlement-records/{id}` | 查询结算及逐项发奖状态 |
|
||
| POST | `/activity/gift-challenge/settlement/{id}` | 手动执行到期 DAILY/OVERALL 结算;period 必填,DAILY 还必须传 statDate |
|
||
| POST | `/activity/gift-challenge/delivery-item/resolve/{itemId}` | 核账确认 UNKNOWN 已到账或未到账 |
|
||
|
||
任务配置必须恰好三条:一条 `ENTER_PAGE` 和两条 `SEND_GIFT_GOLD`;两档送礼任务可分别
|
||
配置金币门槛和奖励,并且金币门槛必须按 `sortOrder` 严格递增。活动启用前必须同时配置 DAILY 和 OVERALL 奖励,
|
||
同一周期排名区间不得重叠。启用后的 H5 奖励展示、每日任务发奖和榜单结算发奖均只读取
|
||
该活动自己的冻结快照;共享资源组之后改名、改奖励或下架都不会改变本期用户所得。
|
||
|
||
| 活动状态 | 核心配置 | 启停约束 |
|
||
| --- | --- | --- |
|
||
| 未启用 + `NOT_STARTED`(包括旧开始时间已过) | 时间、任务、榜单和奖励全部可编辑 | 启用前必须改为未来开始时间 |
|
||
| 已启用 + `NOT_STARTED`(开始前、进行中或已过结束时间) | 全部可编辑 | 历史事实保留,新配置向后生效;已有业务事实后禁止停用 |
|
||
| 任意已进入结算的状态 | 仅活动名称和说明可编辑 | 核心配置始终锁定,不受时间字段影响 |
|
||
|
||
三个任务的 `taskCode/taskType/sortOrder` 固定为 `daily_enter/ENTER_PAGE/1`、
|
||
`daily_gift_1/SEND_GIFT_GOLD/2`、`daily_gift_2/SEND_GIFT_GOLD/3`;活动中仅可修改文案、
|
||
门槛和奖励组。修改时区或时间窗后,旧日期已完成但未成功发放的任务仍可通过原 taskCode
|
||
继续领取,旧日榜也以实际保留的 period header 为准继续查询和结算。
|
||
|
||
## 礼物事件与发奖
|
||
|
||
活动使用独立 consumer group `ASLAN_GIFT_CHALLENGE_GIFT` 直接订阅原始
|
||
`GiveGiftSink.TAG`,与主礼物消费者形成 RocketMQ fan-out,不依赖主消费者完成 Mongo
|
||
落库后再派生消息。对于 broker 已接收的消息,本 consumer 依靠 RocketMQ 重投和业务
|
||
唯一键实现 at-least-once;原 tag 发送失败沿用既有 `GiftMqRetryTask` 全局补偿,活动内
|
||
不再新增第二套 retry tag。活动服务会再次校验完整资格,并通过
|
||
`(activity_id, source_event_track_id)` 唯一键保证 RocketMQ 重投不会重复加分。
|
||
|
||
本活动不新增 IM 消息。奖励复用活动资源组发送器;启用时先形成活动级不可变奖励快照,
|
||
实际领取和结算再把快照中的每个资源配置物化为独立 delivery item 并抢占。超时或
|
||
进程中断统一转为 `UNKNOWN`,避免在下游到账结果不明时盲目重发。系统不设普通失败
|
||
重试分支;运营核账确认未到账后,该单项才会回到 `PENDING` 并补发。排行榜冻结与奖励
|
||
物化分属两个提交事务:门闩和获奖 parent 先提交,奖励项物化或发送短暂失败只会让
|
||
parent 保持 `PENDING`、周期保持 `PROCESSING`;调度器会从活动快照幂等物化并继续发放,
|
||
不会读取已经变化的共享资源组,也不会把已经冻结的榜单重新开放。
|