8.8 KiB
8.8 KiB
邀请码 / 分销规则说明
配置来源: 数据库 system_config.config_key = 'referral_config'
分佣逻辑: app/api/miniprogram/pay/notify/route.ts 中 processReferralCommission
📌 流程图:绑定与分销的完整流程(谁推荐谁、下单怎么写推荐人、分佣怎么算)见 → 分销与绑定流程图
一、分销规则(当前实现)
1. 分成比例
- 推广者分成: 默认 90%(
referral_config.distributorShare = 90) - 平台: 10%
- 可在管理后台或
system_config.referral_config中修改
2. 绑定规则
- 绑定有效期: 默认 30 天(
referral_config.bindingDays = 30) - 一级分销: 只算直接推荐人(
referral_bindings中referee_id= 买家,referrer_id= 推广者) - 有效绑定:
referral_bindings.status = 'active'且expiry_date > NOW()
3. 分佣触发
- 用户支付成功后,回调
POST /api/miniprogram/pay/notify - 根据买家 user_id 查
referral_bindings(referee_id = 买家),取有效绑定的referrer_id - 佣金 = 订单实付金额 × 90%,计入推广者
users.pending_earnings - 该绑定记录更新为
status = 'converted',并记录commission_amount、order_id
4. 其他配置(referral_config)
- minWithdrawAmount: 最小提现金额(默认 10 元)
- userDiscount: 用户优惠比例(默认 5)
二、订单与邀请码
问题
- 下单接口
POST /api/miniprogram/pay之前未传邀请码/分销码,订单表 orders 也没有推荐人字段,无法在订单上直接看到“是谁带来的”。
处理方式(已实现)
-
orders 表增加字段
referrer_id(VARCHAR(50) NULL):下单时若存在有效绑定或邀请码,则写入推荐人 user_id。referral_code(VARCHAR(20) NULL):下单时使用的邀请码,直接记录在订单上便于对账与后台展示。- 迁移脚本:
python scripts/add_orders_referrer_id.py、python scripts/add_orders_referral_code.py(表已存在时各执行一次)。
-
下单时写推荐人与邀请码
- 创建订单时先按买家 user_id 查
referral_bindings(referee_id = 买家、有效且未过期),取referrer_id。 - 若未查到且请求体带了
referralCode,则用users.referral_code = referralCode解析出推荐人 id,写入orders.referrer_id。 - 邀请码:优先存请求体里的
referralCode(用户章节支付时传的);若未传但已有referrer_id,则存该推荐人当前的users.referral_code,保证订单上有一份当时使用的邀请码记录。
- 创建订单时先按买家 user_id 查
-
小程序传参
- 支付请求会传
referralCode:来自wx.getStorageSync('referral_code')(落地页 ref 带入的“谁邀请了我”的邀请码),供后端解析推荐人并写入orders.referrer_id与orders.referral_code。 - 同步约定:
app.js在检测到ref/referralCode时除写入pendingReferralCode外,会同步写入referral_code;章节支付(pages/read/read.js)与找伙伴支付(pages/match/match.js)创建订单时都会带上referralCode,保证两类订单都会记录邀请码。
- 支付请求会传
三、订单表与分销逻辑(已实现)
- 下单时(
POST /api/miniprogram/pay):- 根据买家 user_id 查
referral_bindings(有效且未过期)取referrer_id; - 若无绑定且请求带
referralCode,用users.referral_code解析出推荐人 id; - 插入
orders时写入referrer_id(需表已执行scripts/add_orders_referrer_id.py)。
- 根据买家 user_id 查
- 支付成功回调(
POST /api/miniprogram/pay/notify):- 仍按
referral_bindings查推荐人并发放佣金(90%),不依赖订单上的 referrer_id; - 订单上的
referrer_id用于统计、对账和展示。
- 仍按
四、相关表与字段
| 表 / 配置 | 说明 |
|---|---|
| users | referral_code(自己的邀请码), referred_by(可选), pending_earnings, earnings |
| referral_bindings | referrer_id, referee_id, status(active/converted/expired), expiry_date, commission_amount, order_id |
| orders | referrer_id(推荐人用户ID), referral_code(下单时使用的邀请码,便于对账与展示) |
| system_config | config_key = 'referral_config',含 distributorShare、bindingDays 等 |
五、流程简述
- 用户 A 分享邀请码 / 带 ref 的链接,用户 B 通过该链接进入并完成绑定(写入
referral_bindings,referee_id=B,referrer_id=A)。 - 用户 B 下单支付:调用
POST /api/miniprogram/pay,后端根据 B 的 user_id 查有效绑定得到 A,写入orders.referrer_id = A。 - 支付成功回调:
/api/miniprogram/pay/notify再根据 B 查绑定,给 A 结算 90% 佣金,更新referral_bindings与users.pending_earnings。
这样订单上就有邀请/分销关系(referrer_id),且分佣规则不变。
六、推荐人 vs 邀请码:会不会乱?
结论:不会乱。 全局只认「推荐人 = 用户ID」,邀请码只用于解析出这个 ID。
概念区分
| 概念 | 含义 | 存储位置 | 用途 |
|---|---|---|---|
| 邀请码 | 一串码(如 SOULABC123) | users.referral_code(每个用户一条) |
链接里带 ref=邀请码,用来识别是谁推荐的 |
| 推荐人 | 拿佣金的那个人 | 用用户ID referrer_id 存 |
订单归属、分佣、统计都只认 ID,不认字符串 |
- 邀请码 → 通过
users WHERE referral_code = ?可唯一解析出 → 推荐人用户ID。 - 订单表、绑定表里存的都是 referrer_id,从不存邀请码字符串;展示时再用 referrer_id 去查昵称/邀请码即可。
绑定与订单归属的优先级(唯一权威)
-
下单时(
/api/miniprogram/pay)- 先查
referral_bindings:当前买家是否有有效绑定 → 得到referrer_id。 - 仅当没有绑定时,才用请求体里的
referralCode去users表解析出referrer_id。 - 最终写入订单的只有
orders.referrer_id(用户ID),不会写邀请码。
- 先查
-
分佣时(支付成功回调)
- 只查
referral_bindings(买家 → 有效绑定的推荐人),不看订单上的 referrer_id,也不看邀请码。 - 佣金发给绑定表里的
referrer_id。
- 只查
因此:
- 绑定表 = 权威的「谁推荐了谁」;
- 订单上的 referrer_id = 下单时根据「绑定表 + 兜底邀请码」算出来的结果,只用于展示/对账;
- 邀请码 = 仅作为入口参数,解析成 referrer_id 后就不再参与逻辑,不会和推荐人 ID 混用。
前端 storage 说明(避免混用)
- 落地页/分享带
ref:写入referral_code(下划线),支付时读referral_code传给后端作兜底。 - App 层待绑定:
pendingReferralCode;绑定成功后可选写boundReferralCode。 - 绑定接口、支付接口请求体里统一用 referralCode(驼峰)。
只要后端始终用「绑定表优先、邀请码兜底」且只落库 referrer_id,全局绑定逻辑就不会乱。
七、文章/章节分销
结论:和全局分销是同一套逻辑,没有单独的「按文章维度」分销。
当前实现
- 分享首页:链接形如
https://xxx/?ref=邀请码,点击后 ref 写入 storage,绑定与订单归属按上文规则。 - 分享某篇文章/章节:
- 小程序:
/pages/read/read?id=章节ID&ref=邀请码(阅读页onShareAppMessage/onShareTimeline会带上当前用户邀请码)。 - Web:
/view/read/章节ID?ref=邀请码。
- 小程序:
- 访客从任意带 ref 的链接进入(首页或某篇文章),都会:
- 用 ref 解析出推荐人并完成绑定(
referral_bindings); - 之后该用户下单,订单归属与分佣都按同一套「绑定表优先、邀请码兜底」规则,与从哪篇文章点进来无关。
- 用 ref 解析出推荐人并完成绑定(
也就是说:文章/章节只决定落地页内容,不改变绑定与分佣规则。谁发的链接(ref=谁),谁就是推荐人;买的是哪一章、哪本书,都按 90% 给该推荐人,没有「这篇文章单独分成」或「按章节统计推广效果」的单独逻辑。
未实现的部分(若以后要做)
- 按文章/章节维度的统计:例如「通过《1.2 某某章》链接带来的访问/绑定/订单数」—— 当前未记录分享时的章节 id,无法区分。
- 按文章的分成策略:例如某章单独 95%、其他 90% —— 当前未实现,所有订单统一 90%。
- 若需要「文章分销」统计或差异化分成,需要:在访问/绑定/订单上记录「来源章节」(如
landing_section_id),并在分佣或报表里按章节维度汇总。