Appearance
11 · 返佣推广系统
0. 文档说明
| 项 | 内容 |
|---|---|
| 版本 | V1.0 |
「赚钱」板块的引擎。绑定发生在 05 注册(
?ref=静默携带,无邀请码输入);佣金入账走 02;反套利归 14。一租户 = 一「本位币站」,站内单币种(→ 00 架构总纲)。下级贡献、佣金计提、佣金池、提取到账口径恒为本位币
wallet.baseCurrency;佣金池是单站单池·本位币口径。
一、定位与职责
- 定义推广关系(推广短链、绑定规则、层级/代理树);
- 定义佣金计算(基数/档位/分层率)、日结入佣金池(单站单池·本位币)与提取;
- 定义赚钱面板的展示契约(邀请物料、下级数据、佣金记录)。
层级模型(V1 与 V1.1):租户配 affiliate.maxDepth(1|2|3,默认 1)。maxDepth=1 即 V1 单层返佣(本篇 §二~§八 主线,一切规则的默认形态);maxDepth≥2 启用 V1.1 多级代理(§十一,ADDITIVE:V1 单层为不变默认,不改变任何 V1 语义)。
边界:注册绑定动作在 05;下级流水事实来自 12/03;佣金成本报表归 17。
二、核心概念与数据模型
2.1 推广关系 AffiliateRelation
| 字段 | 说明 |
|---|---|
userId / inviterId(= 直属上级 uplineId)/ tenantId | 下级、直属上级(一次绑定终身不可改);inviterId 即该用户的直属上级 uplineId,V1/V1.1 同字段 |
refSlug | 每用户一个推广短链归因码(生成即有,构成短链 域名/i/{slug};slug 即归因,不设邀请码概念) |
depth | 相对层深(多级模式用):某上级对某下级的层深 = 二者在代理树上的距离(直属下级 depth=1,下级的下级 depth=2…);V1(maxDepth=1)恒为 1 |
代理树(V1/V1.1 共用结构):每个被邀请用户记直属上级 uplineId(= 绑定时的 inviterId),形成闭环有向树——根为无上级的自然获客用户,边由 uplineId 指向上。约束:禁自邀(uplineId≠userId)、禁回环(下级不得成为其任一上级的上级,即建边时校验目标不在自身的祖先/后代闭包中);一次绑定终身不可改(树结构不可事后改接)。V1 只沿直属一层计佣,树深度对计佣无意义(depth 恒 1);V1.1 沿树上溯至多 maxDepth 层计佣(→ §十一)。
绑定规则:注册完成时从落地参数(?ref=<slug>)绑定;自邀、环路、同设备批量注册由 14 拦截;归因全程由落地链接 slug 静默携带,无手动输入邀请码入口。
2.2 佣金账 CommissionAccount(用户,单币种)
accrued(可提佣金,本位币)+ 提取记录。佣金池独立于钱包余额,单站单池(本位币),提取动作才入钱包(REWARD_CREDIT(source=AFFILIATE),入本位币钱包)。
2.3 计算模型
下级当期贡献 ──基数 basis──► 贡献额(本位币)
basis 可配:turnover(有效投注)| ngr(净输赢)| rakebackShare(下级返水分成)
贡献额 × rate(V1:档位 tier;V1.1:按层深 depth 取 `levelRates`,depth=1 取 tiers、depth≥2 取 `ratePct`) ──日结 T+1──► 上级佣金池 accrued +=(本位币)下级流水/贡献均为本位币值(场馆 CNY 映射链路的注单由通道适配层 1:1 重标本位币,→ 02),计佣零特判。
档位 tier:由有效会员数阶梯决定,Global 实例三档 = 0–9 人 10% / 10–29 人 18% / 30+ 人 25%(即 §四配置 activeInvitees 门槛 0 / 10 / 30,费率 0.10 / 0.18 / 0.25;封顶率 25% 即宣传位「最高 25%」的来源)。V1(maxDepth=1)单层即取当前档位率;多级模式(V1.1)各层费率由 levelRates 定义(level 1 沿用本档位表,level≥2 用固定 override,→ §四/§十一)。
basis=rakebackShare 口径:分成基数 = 下级实际领取的返水净额(下级 RewardClaimed(source=RAKEBACK) 的领取额,已含取消冲正抵扣后的真实到手值),数据源 = 08 rakeback_claims 按 inviter 聚合当期值;取「已领取」而非「已入池 accrued」或冲正前流水,确保与 08 返水成本口径一致、不双计(→ 08 §九、17 §2.3 NGR)。三种 basis 口径均明确:turnover=下级有效投注、ngr=下级净输赢、rakebackShare=下级已领返水净额。
三、业务规则
- 日结 T+1:按租户时区日切,聚合下级前一日贡献计佣;结算幂等键 V1 =
(inviterId, downlineId, statDate)(V1 每下级到直属上级恒 depth=1);V1.1 加depth分量 =(inviterId, downlineId, depth, statDate)(→ §十一)。本位币单口径不变。 - 单币种单池:下级流水计入上级唯一佣金池(本位币),站内单口径直入、无换算(→ 02)。
- 提取:
claim(claimId)→ 风控前置(14)→REWARD_CREDIT入available(本位币钱包)→ 池清零(提取范围);门槛minClaim(本位币)。 - 负贡献:
basis=ngr时下级赢钱产生负贡献 —— 当期佣金下限为 0(不倒扣池),负额结转次期抵扣(可配)。 - 数据可见性:上级只能看到下级的聚合脱敏数据(人数/流水/贡献),不可见明细身份信息。
- 变更生效:档位/率表改配置,自下一结算日生效,不追溯。
四、★ 租户可配置项(affiliate 命名空间)
jsonc
"affiliate": {
"enabled": true,
"basis": "ngr", // turnover(下级有效投注)| ngr(下级净输赢)| rakebackShare(下级已领返水净额,→ §2.3)
"maxDepth": 1, // 代理层深上限 1|2|3,默认 1(=V1 单层,不变);≥2 启用 V1.1 多级(→ §十一)
"levels": [ { "depth": 1, "rateScale": 1.0 } ], // V1 一级形态;多级另由 levelRates 定义(→ §十一)
"levelRates": [ // 分层费率(V1.1;maxDepth=1 时仅 level 1 生效,即等价 V1)
{ "level": 1, "tiers": "→ 下方 tiers" }, // level 1 沿用现有档位 tiers(按有效会员数档)
{ "level": 2, "ratePct": 0.05 }, // level≥2 用固定 override 费率(小数),超 maxDepth 的层不配/不计
{ "level": 3, "ratePct": 0.02 }
],
"tiers": [ // 档位(封顶率即宣传「最高 25%」;仅作用于 level 1)
{ "when": { "activeInvitees": 0 }, "rate": 0.10 }, // 青铜 0–9 人
{ "when": { "activeInvitees": 10 }, "rate": 0.18 }, // 白银 10–29 人
{ "when": { "activeInvitees": 30 }, "rate": 0.25 } // 黄金 30+ 人(封顶)
],
"settle": "daily", // 日结 T+1
"negativeCarryover": true, // ngr 负贡献结转
"minClaim": "100", // 提取门槛(本位币单值;站内单币种,单一口径)
"inviteMilestones": [ // 邀请里程碑(有效好友数 → 一次性奖励,本位币,终身一次)
{ "n": 5, "amount": "58" }, { "n": 20, "amount": "288" },
{ "n": 50, "amount": "888" }, { "n": 100, "amount": "2888" }
],
"assets": { "poster": true, "landing": "?ref=" }
}Schema 校验:率 ≤ 平台风控上限(含 levelRates[].ratePct);basis/tiers/levels 互洽;minClaim/里程碑金额为本位币单值(单位 wallet.baseCurrency,校验其存在)。 maxDepth:枚举 1|2|3,默认 1;compliance 可按 region 收紧上限(超限强制回落,→ §十一)。 levelRates:level 连续覆盖 1..maxDepth;level=1 项以 tiers 为费率源(按有效会员数取档),level≥2 项必含 ratePct(0~平台上限的小数);level>maxDepth 的配置项忽略、对应层不计佣。maxDepth=1 时 levelRates 退化为仅 level 1、与 V1 完全等价(向后兼容:旧配置无 maxDepth/levelRates 视同 maxDepth=1)。
五、与其他系统的关系 / 接口
| 接口 | 调用方 | 幂等键 | 说明 |
|---|---|---|---|
getReferPanel(userId) | 展示层 | — | 邀请短链(域名/i/{slug},slug 即归因,不设邀请码概念)、佣金池(可提/今日新增/累计已提/累计佣金,本位币)、直属/有效人数、档位与升档进度、里程碑状态 |
listInvitees(userId, filter) | 展示层 | — | 下级脱敏列表(ID/注册日/有效态/累计流水/我的佣金,本位币);V1.1 filter 可含 depth(1..maxDepth),按层返回代理树下级(→ §十一) |
listCommissions(userId) | 展示层 | — | 佣金流水(日结入池/提取,本位币单流) |
claim(userId) | 展示层 | claimId | 提取佣金 → 本位币钱包 |
消费 UserRegistered | ← 05 | userId | 建立绑定(含 refSlug 校验) |
消费 BetSettled / DepositSucceeded | ← 12/03 | betId/orderId | 归集当期贡献(日结物化) |
产 RewardClaimed(source=AFFILIATE) | → 02/13/16 | claimId | 提取入账(本位币) |
六、运营后台能力(→ 15)
| 侧 | 能力 |
|---|---|
| 平台控制台 | 佣金方案模板、率上限风控线 |
| 商户控制台 | 本站方案配置(基数/档位/层级,含 maxDepth/levelRates);推广关系查询(团伙树,配合 14);代理管理:我的代理树(按层)+ 各层佣金分列(脱敏聚合,超 maxDepth 不显示,→ §十一.4);佣金结算单审计;成本报表(→17);异常代理冻结佣金(工单) |
七、展示契约(→ 原型映射)
| UI 元素 | 数据 | 原型载体 | 系统契约 |
|---|---|---|---|
| 赚钱面板 | 邀请短链复制、海报 | 赚钱 tab(顶部无余额胶囊 body.no-topbal) | getReferPanel;短链=租户主域+/i/{slug} |
| 收益卡 | 可提佣金(本位币) | 「提取佣金 · ¥214.80」按钮 | 展示可提额(本位币);claim 幂等 |
| 宣传位 | 封顶率 | 首页轮播「邀请好友 · 最高赚 25% 佣金」 | 文案取 tiers 封顶率渲染,不写死 |
| 下级/佣金记录 | 聚合统计与流水 | 下级列表/佣金记录区 | listInvitees + 13 领取记录(source=AFFILIATE);金额恒本位币 |
八、数据库设计(全表含 tenant_id;金额 DECIMAL(32,8))
| 表 | 关键字段 | 约束/索引 |
|---|---|---|
affiliate_relations | tenant_id, user_id, inviter_id, ref_slug_used, bound_at | UK(tenant_id,user_id);IDX(tenant_id,inviter_id) |
user_ref_slugs | tenant_id, user_id, ref_slug | UK(tenant_id,ref_slug) |
commission_daily | id PK, tenant_id, inviter_id, downline_id, stat_date, basis(turnover/ngr/rakebackShare 快照), basis_amount(本位币;rakebackShare 时=下级当期已领返水净额聚合,→ §2.3), rate, depth(层深 1..maxDepth;V1/maxDepth=1 恒 1), commission, carryover | UK(tenant_id,inviter_id,downline_id,depth,stat_date);IDX(tenant_id,inviter_id,stat_date) |
commission_accounts | tenant_id, user_id, accrued(本位币) | UK(tenant_id,user_id) |
commission_claims | claim_id PK, tenant_id, user_id, amount(本位币), created_at | UK(tenant_id,claim_id) |
(日结/账/提取表金额列恒为本位币口径——站内单币种,单站单池,键内无 currency 分量。)
commission_daily 行粒度:每 (inviter_id, downline_id, depth, stat_date) 一行——即「某上级从某个直/间接下级、在该层深、该日」的一条计佣。V1(maxDepth=1):depth 恒 1、每上级每下级每日恰一行,按 inviter_id 聚合即得该上级当日佣金(与 V1.0 语义完全一致,仅显式化 downline_id 维度)。V1.1(maxDepth≥2):同一下级可对其至多 maxDepth 个上级各产生一行(不同 inviter_id/depth),depth 可 >1;结算幂等键 = UK(tenant_id,inviter_id,downline_id,depth,stat_date),重跑不重复(→ §十一)。上级当日总佣金 = 其名下所有行 commission 之和 − 结转。
九、扩展点与代理平面路线图
V1 范围:单层返佣(maxDepth=1,levels=[{depth:1}])、静默 slug 绑定、按有效会员数档位、日结 T+1、单站单池提取。
代理平面路线图:
| 节点 | 交付物 | 落地要点 | 合规钩子 |
|---|---|---|---|
| V1(现·默认) | 一级返佣 | maxDepth=1;levels 恒 depth=1;commission_daily depth=1 | compliance 可强制 maxDepth=1 |
| V1.1(已定义 → §十一) | 多级代理(depth 1..maxDepth) | affiliate.maxDepth(1 | 2 |
| V1.1(已定义 → §十一) | 代理树后台(团队长)受限数据平面 | 商户控制台内「代理管理」角色视图(非独立系统):代理后台可见「我的代理树(按层)」+ 各层佣金分列、直属+下级树脱敏聚合报表(人数/流水/贡献/佣金,身份掩码)、子代理业绩排名;只读、不可见跨代理明细身份(→ §三.5 数据可见性);超出 maxDepth 层不显示 | 跨代理只回聚合、不回传下级身份;导出受 console.dataExport(→ 15)控 |
| V1.1 | 用户端 refer 多层树展示 | 用户端 refer 板「我的代理团队(按层)」:直属/2级/3级 多层下级树 + 各层费率与佣金分列(→ refer.md);maxDepth=1 时降级单层 | 用户端只回本人代理树的脱敏聚合,超 maxDepth 层不展示 |
| V1.2(待运营诉求) | 代理自设下级分成 / CPA 混合计酬 | 大代理在封顶率内自定义子代理率;CPA=按有效新增人头一次性计酬,与流水分成并存 | 自设率 ≤ 平台风控上限;CPA 反刷号并入 14 |
其余开放项:
- 佣金池计息/过期:长期不提取是否过期,默认不过期,待定。
- 代理层级树重构:绑定关系一次终身不可改;若运营要「代理转移/团队合并」属高危工单,须平台审批 + 审计,V1 不做。
十、验收要点
- [ ] 带
?ref=<slug>注册必绑定且终身不可改;自邀/环路被拒; - [ ] 日结幂等:同一
(上级,下级,层深,日期)重跑不重复计佣; - [ ] 佣金单站单池(本位币),下级贡献→计提→提取全链路单口径、无换算;
- [ ]
ngr负贡献期佣金为 0 且结转正确(V1.1 按 inviter 汇总结转); - [ ] 档位门槛/费率正文 = §四
tiers配置 = refer.md 三处一致(0/10/30 人 → 10%/18%/25%),前端试算取当前档位率、不写死; - [ ]
basis=rakebackShare时basis_amount= 下级当期已领返水净额(源 08rakeback_claims),与返水成本不双计; - [ ]
maxDepth=1(默认)时行为等价 V1:depth恒 1、单层计佣、幂等/结转/展示与 V1.0 无差异;提取幂等入本位币钱包,佣金池与钱包账变对得上; - [ ] V1.1(
maxDepth≥2):计佣沿代理树上溯至多maxDepth层;超maxDepth的层不计佣;level=1用tiers档、level≥2用levelRates[].ratePct;每 (inviter,downline,depth,date) 一行且幂等键含 depth;后台代理树按层可见、各层佣金分列,超maxDepth不显示; - [ ] 宣传位封顶率随
tiers配置变化,无写死「25%」。
十一、多级代理 V1.1(ADDITIVE;maxDepth=1 为不变默认)
本节为 V1 之上的加法:
affiliate.maxDepth=1(默认)时,以下全部退化为 §二~§十 描述的 V1 单层返佣,语义、口径、幂等、结转、展示均不变。maxDepth≥2才启用多级;仍 T+1 日结、本位币单口径、单站单池。
11.1 配置
affiliate.maxDepth:1|2|3,默认 1。商户可配;compliance 按 region 设上限(超限maxDepth截断)。=1即 V1。affiliate.levelRates:分层费率数组,level连续覆盖1..maxDepth——level=1:沿用现有tiers(按有效会员数档:0/10/30 人 → 10%/18%/25%,封顶 25%),与 V1 完全一致;level≥2:固定 override 费率ratePct(0~平台上限的小数),不吃 tiers 档;level>maxDepth的项忽略、对应层不计佣。
- 分成基数沿用
basis(turnover|ngr|rakebackShare,默认ngr,口径同 §2.3),各层同基数、仅费率按层取。
11.2 代理树与层深
- 每个被邀请用户记直属上级
uplineId(= 绑定inviterId),构成闭环有向树(→ §2.1)。 - 层深 depth = 上级到下级在树上的距离:直属下级 depth=1,下级的下级 depth=2,……;超过
maxDepth的层不计佣(截断)。 - 建树校验:禁自邀(
uplineId≠userId)、禁回环(下级不得成为其任一上级的上级——建边时校验目标不在自身祖先/后代闭包内);一次绑定终身不可改。
11.3 计佣
对每个下级当期的 basis_amount(本位币),沿其代理树向上,对每个距离 depth ≤ maxDepth 的上级 inviter:
该 (inviter, downline) 层佣金 = downline.basis_amount(当期,本位币)
× rateOf(depth) // depth=1 取 tiers 当前档;depth≥2 取 levelRates[depth].ratePct
落 commission_daily 一行:(tenant, inviter, downline, depth, stat_date, basis, basis_amount, rate, commission, carryover)- 多上级并发:同一下级可同时贡献给其 depth=1..maxDepth 的各上级,各层独立入各自上级池(不是把一份佣金拆分,而是每层按该层费率各自计一份成本)。
- 负贡献结转:
basis=ngr下级赢钱产生负贡献时,当期该上级佣金下限为 0(不倒扣池);负额按 inviter 汇总结转次期抵扣(沿用negativeCarryover,口径同 §三.4)。 - 幂等:结算幂等键 = (tenant, inviter, downline, depth, date);同键重跑不重复计佣(=
commission_dailyUK)。 - 结算节奏/口径:仍 T+1 日结、按租户时区日切、本位币单口径、单站单池;提取(§三.3)不变。
11.4 展示 / 后台
- 代理后台(商户控制台「代理管理」视图,→ §九、15):新增「我的代理树(按层)」+ 各层佣金分列(depth=1/2/3 分列小计);脱敏聚合(人数/流水/贡献/佣金,身份掩码,→ §三.5);超出
maxDepth的层不显示。 - 用户端 refer 板:「我的代理团队(按层)」呈现多层下级树 + 各层费率与佣金分列(直属/2级/3级,→ refer.md);计佣与数据契约见本篇,UI 细节见 refer.md。
maxDepth=1时用户端与 V1 视图一致。
11.5 防滥用
- 建树时闭环校验 + 自邀拒绝(→ §2.1、14);
maxDepth截断:超上限的层不建计佣、不入池、不显示;- 结算幂等键 (tenant, inviter, downline, depth, date) 保证重跑/补算不双计;
- 层深上限由 compliance 按 region 强制(「拉人头」判定收紧时可下调
maxDepth,超限层即时回落不计,→ §九合规钩子)。