- 还原 /v1/public/user/invite_sales 接口及 /invite/sales 别名(与 invite_records 并存) 逻辑/handler/types 与197fed7d删除前版本完全一致,按fefbd4f5新 routes 结构注册 - 新增迁移 02155_promo_schema_fix: 幂等修复 subscribe_promo / order 列类型与索引偏差 - 同步 etc/ppanel.yaml 数据库连接配置 - 补齐相关需求与设计文档
12 KiB
App 邀请列表与商品套餐折扣需求梳理
本文基于当前 ppanel-server 代码现状,对以下两个需求做整理:
- App 需要一个“邀请列表/邀请记录”接口。
- 商品套餐需要补充“折扣信息”,当存在折扣时,App 需要做样式展示,并支持用户继续下单购买。
目标是帮助产品、前端、后端快速统一口径,明确:
- 现在已有哪些接口可以复用
- 哪些地方确实需要新增
- “接口增加三个字段”更适合加在哪一层
1. 需求结论
1.1 邀请列表
当前公开侧已经有一部分邀请能力,但没有一个完全匹配“App 邀请记录列表”语义的公开接口。
现状:
- 已有
GET /v1/public/user/affiliate/list- 能返回“我邀请了哪些用户”
- 但字段较少,只包含基础信息
- 已有
GET /v1/public/user/invite_sales- 返回的是“被邀请用户的成交订单记录”
- 不是“邀请用户记录列表”
- 已有
GET /v1/public/user/invite_stats- 返回邀请统计
- 不是列表
结论:
- 如果 App 只是要展示“我邀请了哪些人”,
/affiliate/list可以复用。 - 如果 App 需要展示“邀请时间、是否购买、购买次数、带来的佣金/赠送天数”等完整邀请记录,则建议新增一个公开接口。
1.2 商品套餐折扣
当前公开侧套餐列表接口 GET /v1/public/subscribe/list 已经返回 discount 字段,下单预览接口 POST /v1/public/order/pre 也已经支持折扣计算。
现状:
- 套餐列表已有折扣规则数组
discount - 预下单接口已有:
- 原价
price - 实付
amount - 折扣金额
discount - 活动优惠
promo_discount - 优惠券减免
coupon_discount - 手续费
fee_amount
- 原价
结论:
- 后端不是完全没有折扣能力,而是“已经有计算能力,但 App 展示层使用起来不够直接”。
- 如果需求明确要求“接口增加三个字段”,更推荐补在套餐列表返回的
discount[]子项里,而不是直接加在下单接口里。
2. 当前代码现状
2.1 邀请相关
2.1.1 已有公开接口
A. 邀请基础列表
接口:
GET /v1/public/user/affiliate/list
请求:
pagesize
返回结构:
totallist[]identifieravatarregistered_atenable
特点:
- 能表达“我邀请了谁”
- 不能表达“是否购买 / 购买次数 / 给我带来多少收益”
对应代码:
apis/public/user.apiinternal/logic/public/user/queryUserAffiliateListLogic.go
B. 邀请成交记录
接口:
GET /v1/public/user/invite_sales
返回结构:
totallist[]amountupdated_atuser_hashproduct_name
特点:
- 更像“邀请带来的订单流水”
- 不是邀请用户列表
对应代码:
internal/logic/public/user/getInviteSalesLogic.go
C. 邀请统计
接口:
GET /v1/public/user/invite_stats
返回结构:
friendly_counthistory_count
特点:
- 只适合头部统计卡片
- 不适合列表页
对应代码:
internal/logic/public/user/getUserInviteStatsLogic.go
2.1.2 已有后台接口
后台已经有更完整的邀请记录能力,可以直接参考:
GetAdminUserInviteListGetInviteManageList
这些接口已经能返回:
- 邀请时间
- 是否购买
- 购买次数
- 邀请人佣金
- 邀请人赠送天数
- 被邀请人赠送天数
对应代码:
internal/logic/admin/user/getAdminUserInviteListLogic.gointernal/logic/admin/invite/getInviteManageListLogic.go
结论:
- 邀请记录的统计逻辑后端已经有现成实现思路。
- 新增 App 公开接口时,建议复用这部分逻辑,不要从零再写一套。
2.2 套餐折扣相关
2.2.1 套餐列表接口已有折扣规则
接口:
GET /v1/public/subscribe/list
当前返回的套餐结构 Subscribe 中已包含:
unit_pricediscount []SubscribeDiscount
其中 SubscribeDiscount 当前字段为:
quantitydiscountnew_user_onlymap_applepromo
对应代码:
apis/public/subscribe.apiinternal/logic/public/subscribe/querySubscribeListLogic.gointernal/types/types.go
说明:
discount是按购买数量quantity生效的阶梯折扣- 不是单个套餐固定只有一个折扣值
2.2.2 预下单接口已有价格计算结果
接口:
POST /v1/public/order/pre
当前已返回:
price:原价amount:最终应付discount:折扣减免金额promo_discount:活动优惠金额gift_amount:礼品余额抵扣coupon_discount:优惠券减免fee_amount:手续费
对应代码:
apis/public/order.apiinternal/logic/public/order/preCreateOrderLogic.go
说明:
- 只要 App 知道
subscribe_id + quantity [+ coupon] [+ payment],就已经能拿到准确的下单金额 - 所以“下单购买”这件事本身,后端主链路已经具备
3. 差距分析
3.1 邀请列表的真实缺口
如果产品要的是“邀请记录页”,通常至少会关心以下内容:
- 被邀请用户
- 邀请时间
- 是否已购买
- 购买次数
- 给邀请人带来的佣金
- 双方赠送天数
而当前:
/affiliate/list只有基础用户列表/invite_sales是订单成交记录/invite_stats是统计值
所以当前公开侧缺一个“邀请关系维度的邀请记录列表”。
3.2 套餐折扣的真实缺口
后端目前的主要问题不是“不会算折扣”,而是:
discount[]更偏规则定义- App 如果只想直接展示“折后价 / 优惠金额 / 折扣标签”,还需要自己再算一层
- 这会增加前端理解成本,也容易和后端口径不一致
所以当前更合理的改法是:
- 保留现有折扣规则
- 再额外补充几个面向展示的字段
4. 推荐方案
4.1 邀请记录接口
方案建议
新增一个公开接口,例如:
GET /v1/public/user/invite_records
说明:
- 从登录态中取当前用户 ID
- 不从前端传
user_id - 只查“当前用户邀请的记录”
请求参数建议
{
"page": 1,
"size": 10
}
返回字段建议
{
"total": 2,
"list": [
{
"invitee_id": 1001,
"invitee_identifier": "138****8888",
"invitee_avatar": "https://...",
"invitee_enable": true,
"invited_at": 1716800000,
"order_count": 3,
"has_purchased": true,
"inviter_commission": 1200,
"inviter_gift_days": 30,
"invitee_gift_days": 7
}
]
}
字段说明
invitee_id:被邀请用户 IDinvitee_identifier:被邀请用户展示账号invitee_avatar:头像invitee_enable:是否启用invited_at:邀请时间order_count:该被邀请用户产生的有效订单数has_purchased:是否已购买inviter_commission:给邀请人带来的佣金,单位建议继续沿用分inviter_gift_days:邀请人获赠天数invitee_gift_days:被邀请人获赠天数
实现建议
优先复用现有后台逻辑思路:
- 参考
internal/logic/admin/user/getAdminUserInviteListLogic.go - 或参考
internal/logic/admin/invite/getInviteManageListLogic.go
公开接口与后台接口的主要差异只有两点:
- 公开接口不允许前端指定
user_id - 公开接口按当前登录用户本人维度返回
是否可以不新增接口
可以,但前提是 App 接受以下拆分:
- 列表页用
/affiliate/list - 顶部统计用
/invite_stats - 订单流水页用
/invite_sales
如果产品要的是一个完整“邀请记录页”,不建议这样拆三次请求,前端维护成本偏高。
4.2 套餐折扣字段建议
核心建议
“接口增加三个字段”建议加在 SubscribeDiscount 子项里,不要直接加在 Subscribe 顶层。
原因:
- 折扣是按
quantity生效的 - 一个套餐可能有多个折扣档位
- 如果加在套餐顶层,很难表达“买 1 个月”和“买 12 个月”对应不同折扣
推荐新增字段
建议在 SubscribeDiscount 中增加以下三个展示字段:
discount_pricediscount_amountdiscount_desc
推荐结构如下:
{
"quantity": 12,
"discount": 80,
"new_user_only": false,
"map_apple": "",
"promo": null,
"discount_price": 9600,
"discount_amount": 2400,
"discount_desc": "年付8折"
}
三个字段的含义
1. discount_price
- 含义:该档位折后总价
- 计算建议:
unit_price * quantity * discount / 100 - 单位:分
作用:
- App 可直接展示“折后价”
- 下单时直接把该项的
quantity带入/order/pre或/order/purchase
2. discount_amount
- 含义:该档位比原价便宜多少钱
- 计算建议:
unit_price * quantity - discount_price - 单位:分
作用:
- App 可直接展示“立省 xx”
3. discount_desc
- 含义:折扣展示文案
- 示例:
年付8折季付9折新用户首单8折
作用:
- App 可直接做角标、标签、促销文案展示
为什么不推荐这三个字段加在下单接口
因为下单接口本来就是“结果型接口”,它已经能返回:
- 原价
- 折扣金额
- 实付金额
如果只是为了 App 卡片展示,再去每个套餐都调一次 /order/pre,成本会比较高:
- 请求次数多
- 页面首屏会更慢
- 前端链路更复杂
更合适的做法是:
- 套餐列表接口负责“展示友好”
- 预下单接口负责“结算准确”
5. 推荐改动清单
5.1 邀请列表
建议新增:
- 新接口:
GET /v1/public/user/invite_records
建议新增类型:
GetUserInviteRecordsRequestUserInviteRecordGetUserInviteRecordsResponse
建议实现位置:
apis/public/user.apiinternal/types/types.gointernal/handler/public/user/internal/logic/public/user/
5.2 套餐折扣
建议调整:
SubscribeDiscount增加 3 个字段:discount_pricediscount_amountdiscount_desc
建议实现位置:
apis/types.apiinternal/types/types.gointernal/logic/public/subscribe/querySubscribeListLogic.go
6. 前后端协作建议
6.1 App 侧调用建议
邀请页建议:
- 头部统计:
/v1/public/user/invite_stats - 邀请记录列表:
/v1/public/user/invite_records - 如果还要看成交流水:
/v1/public/user/invite_sales
套餐页建议:
- 先调
/v1/public/subscribe/list渲染套餐和折扣标签 - 用户点某个折扣档位时,带
subscribe_id + quantity调/v1/public/order/pre - 用户确认后再调
/v1/public/order/purchase
6.2 单位口径建议
建议继续保持后端金额统一为“分”:
unit_pricediscount_pricediscount_amountamountcoupon_discount
这样可以避免前后端出现小数精度问题。
7. 最终建议
建议一
如果你们只是要“邀请用户名单”,可直接复用:
GET /v1/public/user/affiliate/list
建议二
如果你们要的是完整“邀请记录”,建议新增:
GET /v1/public/user/invite_records
这是本次需求里更合理的新增接口。
建议三
商品套餐“折扣信息”不建议重新设计一整套下单逻辑。
当前后端已经具备:
- 套餐折扣规则
- 预下单价格计算
- 正式下单购买
更推荐做法是:
- 在
SubscribeDiscount里补 3 个展示字段:discount_pricediscount_amountdiscount_desc
这样改动最小,也最贴近 App 展示场景。
8. 相关代码位置
internal/logic/public/user/queryUserAffiliateListLogic.gointernal/logic/public/user/getInviteSalesLogic.gointernal/logic/public/user/getUserInviteStatsLogic.gointernal/logic/admin/user/getAdminUserInviteListLogic.gointernal/logic/admin/invite/getInviteManageListLogic.gointernal/logic/public/subscribe/querySubscribeListLogic.gointernal/logic/public/order/preCreateOrderLogic.gointernal/logic/public/order/purchaseLogic.gointernal/types/types.goapis/public/user.apiapis/public/subscribe.apiapis/public/order.api