feat: add invite rewards and redeem codes
This commit is contained in:
@@ -0,0 +1,254 @@
|
||||
# 恢复邀请体系并新增兑换卡密系统
|
||||
|
||||
## 1. 目标
|
||||
|
||||
在现有积分与支付体系上,恢复“我的邀请”业务闭环,并新增面向运营发放的卡密兑换体系。该任务覆盖协议、后端、web 前端、数据库迁移、运营脚本与审计留痕。
|
||||
|
||||
## 2. 当前现状(已确认)
|
||||
|
||||
### 2.1 邀请体系
|
||||
|
||||
- 后端当前只有 `GET /api/v1/invite/me`,返回 `{ code, used_count }`。
|
||||
- `web/` 当前没有邀请页或卡密兑换入口,但已有 `SettingsPage`、`StorePage`、`api.ts`、`resources.ts` 等可复用页面与资源层。
|
||||
- 注册时数据库 trigger `initialize_profile_and_invite_code_on_signup()` 会:
|
||||
- 为新用户生成自己的邀请码;
|
||||
- 若 `auth.users.raw_user_meta_data.invite_code` 合法,则给对应 `invite_codes.used_count + 1`;
|
||||
- 将 `profiles.referred_by` 写成邀请人的 `profiles.id`。
|
||||
- 当前邀请只记录“被使用次数”,不记录逐个受邀人的充值达成状态,也没有邀请奖励发放逻辑。
|
||||
|
||||
### 2.2 积分与支付体系
|
||||
|
||||
- 当前积分账本 `points_ledger` / `points_audit_ledger` 支持 `register / consume / adjust / purchase / refund`。
|
||||
- 支付套餐当前定义在 `backend/src/core/config/static/packages/mapping.yaml`:
|
||||
- `new_user_pack`(starter)
|
||||
- `starter_pack`
|
||||
- `popular_pack`
|
||||
- `premium_pack`
|
||||
- Apple IAP 与 Creem 支付成功后,现有代码会写入积分账本与积分审计账本。
|
||||
|
||||
### 2.3 审计与卡密
|
||||
|
||||
- 当前仓库没有通用 `audit_logs` 或同类系统审计表落地实现。
|
||||
- 当前没有卡密表、卡密生成脚本、卡密兑换接口或兑换 UI。
|
||||
|
||||
## 3. 用户要求(原始需求整理)
|
||||
|
||||
### 3.1 邀请恢复
|
||||
|
||||
- 恢复此前“藏起来”的邀请能力。
|
||||
- 允许用户绑定别人的邀请码。
|
||||
- 绑定后不可解绑。
|
||||
- 每个账号只能绑定一次。
|
||||
- 受邀人绑定邀请码后第一次 Creem 充值成功后:
|
||||
- 邀请人获得奖励积分;
|
||||
- 被邀请人获得奖励积分。
|
||||
- 奖励积分值必须通过环境变量配置,当前目标值为 `40`。
|
||||
|
||||
### 3.2 我的邀请页展示
|
||||
|
||||
- 能看到邀请人数。
|
||||
- 能看到每个受邀关系对应奖励是否到账。
|
||||
- 用户给出的目标示例是:页面应区分“已邀请人数”“已达成绑定后充值人数”“未达成绑定后充值人数”,以及奖励到账情况。
|
||||
|
||||
### 3.3 卡密系统
|
||||
|
||||
- 覆盖除“新手专享包”以外的三个套餐。
|
||||
- 按价格从低到高生成卡密数量:
|
||||
- 最低价套餐:100 张
|
||||
- 中间套餐:40 张
|
||||
- 最高价套餐:20 张
|
||||
- 生成脚本放在 `infra/scripts` 下,由触发脚本执行。
|
||||
- 生成一份 Excel,包含每个卡密及其对应套餐信息。
|
||||
- 数据库允许新增表,用于分析卡密、套餐与激活状态。
|
||||
- 在“我的邀请”页面下新增“兑换卡密”入口,点击弹窗输入卡密。
|
||||
- 兑换成功后,显示“已激活某某套餐,获得 xx 积分”。
|
||||
- 积分流水表与系统审计表都要记录卡密兑换链路。
|
||||
|
||||
## 4. 需求拆解
|
||||
|
||||
### 4.1 邀请业务数据补全
|
||||
|
||||
现有 `profiles.referred_by` 只能表示“我被谁邀请”,`invite_codes.used_count` 只能表示“邀请码被使用几次”,都不足以支撑:
|
||||
|
||||
- 单次绑定约束;
|
||||
- 绑定后 Creem 充值达成判断;
|
||||
- 奖励幂等发放;
|
||||
- 页面按受邀人维度展示达成状态。
|
||||
|
||||
本任务需要新增显式邀请关系表,至少能表达:
|
||||
|
||||
- 邀请人用户 ID;
|
||||
- 受邀人用户 ID;
|
||||
- 绑定时使用的邀请码;
|
||||
- 绑定时间;
|
||||
- 是否已完成绑定后 Creem 充值;
|
||||
- 绑定后 Creem 充值对应支付流水 ID;
|
||||
- 邀请人奖励是否已发放;
|
||||
- 受邀人奖励是否已发放;
|
||||
- 对应账本 event_id / 审计事件 ID;
|
||||
- 幂等字段与唯一约束。
|
||||
|
||||
### 4.2 邀请奖励触发
|
||||
|
||||
触发点应绑定在“绑定邀请码后第一次 Creem 充值成功”这个业务事件,而不是注册时:
|
||||
|
||||
- Apple IAP 成功入账;
|
||||
- Creem 支付成功入账;
|
||||
- 绑定后 Creem 充值成功判定必须以 `creem` 交易表中的成功记录为准。
|
||||
|
||||
已确认规则:
|
||||
|
||||
- “绑定邀请码后第一次 Creem 充值成功”仅指真实付费购买成功;
|
||||
- 必须在 `creem` 交易表存在成功记录,才算邀请绑定奖励达成;
|
||||
- 卡密兑换不算作邀请绑定奖励达成;
|
||||
- 邀请奖励只发一次,且邀请双方各一次。
|
||||
|
||||
### 4.3 邀请绑定入口
|
||||
|
||||
当前注册 trigger 支持“注册时带邀请码”,但需求要求恢复“绑定别人的代码”,且绑定后不可解绑、只能绑定一次。因此需要新增应用层接口,而不是只依赖注册 trigger:
|
||||
|
||||
- 绑定邀请码接口;
|
||||
- 查询我的邀请详情接口;
|
||||
- 接口错误码与前端文案;
|
||||
- 明确禁止重复绑定、禁止绑定自己的码、禁止绑定不存在或失效的邀请码。
|
||||
|
||||
### 4.4 卡密体系
|
||||
|
||||
需要新增面向运营的可追踪卡密:
|
||||
|
||||
- 卡密主表;
|
||||
- 套餐快照字段;
|
||||
- 激活状态、激活人、激活时间;
|
||||
- 生成批次;
|
||||
- 导出字段;
|
||||
- 幂等兑换保护。
|
||||
|
||||
建议卡密兑换本质上走“积分入账 + 审计 + 系统操作日志”一条完整链路,不直接绕过现有积分服务。
|
||||
|
||||
## 5. 协议与实现范围
|
||||
|
||||
### 5.1 协议文档(代码前必须更新)
|
||||
|
||||
以下协议需要先更新,再改实现:
|
||||
|
||||
- `docs/protocols/invite/invite-protocol.md`
|
||||
- `docs/protocols/common/user-points-chat-data-protocol.md`
|
||||
- `docs/protocols/common/http-error-codes.md`
|
||||
- 如新增兑换接口,补充 `docs/protocols/points/points-balance-protocol.md` 或新增兑换协议文档
|
||||
|
||||
### 5.2 后端
|
||||
|
||||
- Alembic 迁移:
|
||||
- 邀请关系表
|
||||
- 卡密表
|
||||
- 如采用通用系统审计表,则新增审计表
|
||||
- `core.config.settings`:
|
||||
- 新增邀请奖励积分环境变量配置
|
||||
- 邀请服务:
|
||||
- 绑定邀请码
|
||||
- 查询我的邀请详情(不仅仅是 `used_count`)
|
||||
- 绑定后 Creem 充值奖励发放
|
||||
- 支付服务:
|
||||
- Creem 绑定后 Creem 充值成功时触发邀请奖励检查
|
||||
- 卡密服务:
|
||||
- 兑换接口
|
||||
- 幂等、校验、入账、审计
|
||||
- 审计:
|
||||
- 积分审计账本落地卡密兑换
|
||||
- 系统审计表落地邀请绑定、邀请奖励发放、卡密生成、卡密兑换
|
||||
|
||||
### 5.3 前端(Web)
|
||||
|
||||
- 在现有 `web` 设置体系中新增“我的邀请”入口或子页面:
|
||||
- 绑定邀请码
|
||||
- 展示我的邀请码
|
||||
- 展示邀请人数 / 达成绑定后充值人数 / 待达成人数
|
||||
- 展示逐个受邀人的奖励状态
|
||||
- 在“我的邀请”下新增“兑换卡密”
|
||||
- 点击弹窗输入
|
||||
- 成功后提示并刷新余额 / 邀请数据
|
||||
- 更新 web 端本地化文案、API 调用与资源失效逻辑
|
||||
|
||||
### 5.4 Infra / 运营
|
||||
|
||||
- 新建 `infra/scripts` 下卡密生成脚本
|
||||
- 支持一键生成三档卡密
|
||||
- 导出 Excel
|
||||
- Excel 至少包含:
|
||||
- 卡密
|
||||
- 套餐编码
|
||||
- 套餐名称/档位
|
||||
- 对应积分
|
||||
- 生成批次
|
||||
- 是否已兑换
|
||||
- 兑换人
|
||||
- 兑换时间
|
||||
|
||||
## 6. 约束与实现原则
|
||||
|
||||
- 不加兜底分支,不用静默降级来掩盖绑定失败、绑定后 Creem 充值奖励失败或卡密兑换失败。
|
||||
- 绑定邀请码必须是强约束:
|
||||
- 一人最多绑定一次;
|
||||
- 绑定后不可解绑;
|
||||
- 禁止自绑定。
|
||||
- 邀请奖励与卡密兑换都必须走幂等事件 ID。
|
||||
- 积分账本与审计账本必须保持一致。
|
||||
- 若新增系统审计表,不能替代 `points_audit_ledger`,而应补充业务操作审计。
|
||||
|
||||
## 7. 已确认口径
|
||||
|
||||
### 7.1 邀请页展示口径
|
||||
|
||||
用户已确认示例应为:
|
||||
|
||||
- 邀请了 `3` 个人;
|
||||
- 奖励到账进度为 `80/120`;
|
||||
- 表示其中 `2` 个人已完成绑定后 Creem 充值,`1` 个人未完成。
|
||||
|
||||
因此页面至少需要稳定表达:
|
||||
|
||||
- 已邀请人数;
|
||||
- 已达成绑定后充值人数;
|
||||
- 未达成绑定后充值人数;
|
||||
- 已到账邀请奖励 / 总可达邀请奖励。
|
||||
|
||||
按当前确认,若奖励环境变量值为 `40`,则:
|
||||
|
||||
- 已到账邀请奖励 = `已达成绑定后充值人数 * 40`
|
||||
- 总可达邀请奖励 = `已邀请人数 * 40`
|
||||
|
||||
### 7.2 绑定后 Creem 充值与卡密口径
|
||||
|
||||
- 卡密兑换不算充值成功。
|
||||
- 邀请绑定奖励达成必须以 `creem` 成功交易记录为准。
|
||||
|
||||
## 8. 实施清单
|
||||
|
||||
- [ ] 更新邀请 / 积分 / 错误码协议文档
|
||||
- [ ] 设计邀请关系表、卡密表、系统审计表
|
||||
- [ ] 增加邀请奖励积分环境变量配置
|
||||
- [ ] 实现邀请码绑定接口与查询接口
|
||||
- [ ] 在 Creem 成功支付链路接入绑定后 Creem 充值邀请奖励
|
||||
- [ ] 实现卡密生成脚本与 Excel 导出
|
||||
- [ ] 实现卡密兑换接口与账本/审计入库
|
||||
- [ ] 完成 web 邀请页与兑换弹窗改造
|
||||
- [ ] 增加后端 / web 回归测试
|
||||
|
||||
## 9. 建议的相关文件
|
||||
|
||||
- 后端:
|
||||
- `backend/src/v1/invite/**`
|
||||
- `backend/src/v1/points/**`
|
||||
- `backend/src/v1/payments/**`
|
||||
- `backend/src/core/config/settings.py`
|
||||
- `backend/alembic/versions/*`
|
||||
- Web:
|
||||
- `web/src/components/SettingsPage.tsx`
|
||||
- `web/src/lib/api.ts`
|
||||
- `web/src/lib/api-routes.ts`
|
||||
- `web/src/lib/resources.ts`
|
||||
- `web/src/i18n/utils.ts`
|
||||
- 协议:
|
||||
- `docs/protocols/invite/invite-protocol.md`
|
||||
- `docs/protocols/common/user-points-chat-data-protocol.md`
|
||||
- `docs/protocols/common/http-error-codes.md`
|
||||
Reference in New Issue
Block a user