推一反三商城小程序开发方案与分销逻辑:裂变引擎与资金闭环的Java实现

发布时间:2026/10/27 18:17:06
推一反三商城小程序开发方案与分销逻辑:裂变引擎与资金闭环的Java实现

推一反三商城小程序开发方案与分销逻辑:裂变引擎与资金闭环的Java实现

“推一反三”表面是“推荐3人返1单”,底层是一套高并发关系链锁定、循环计数、合规二级分佣、退款冲正的资金闭环系统。真正难的不是画海报,而是:并发报名不超发、关系绑定防篡改、返现到账可回滚、层级不碰传销红线。

一、业务模型与系统边界

核心角色:平台、推广者(老用户)、被推荐人(新客)。

裂变主链路:

  1. 用户 A 购买“资格商品”获得推广位
  2. A 分享带 inviterCode 的卡片
  3. B/C/D 通过卡片下单支付
  4. 系统校验“有效新客订单”计数
  5. 满 3 单自动触发返现(余额/红包/权益)
  6. 售后期无退款 → 佣金解冻;有退款 → 计数回撤+返现追回

技术栈:

  • 前端:uni-app / 微信原生(分享参数透传)
    • 后端:Spring Boot + MyBatis-Plus

• 存储:MySQL 5.7(分表)+ Redis 7(计数/锁/关系缓存)

• 异步:RabbitMQ(返现、分佣、退款冲正)

• 支付:微信支付

二、关系链绑定:首次锁定,防抢客

小程序启动/分享进入时带 scene=inviter_123,后端做首次绑定:
public void bindRelation(Long userId, Long inviterId) {
if (inviterId == null || inviterId.equals(userId)) return;
String lock = “rel🔒” + userId;
if (!redisLock.tryLock(lock, 5)) return;
try {
// 已绑定不再覆盖(防刷单抢客)
if (relationMapper.selectByUserId(userId) != null) return;

Relation r = new Relation(); r.setUserId(userId); r.setParentId(inviterId); // 冗余二级,便于O(1)分佣 Relation p = relationMapper.selectByUserId(inviterId); r.setGrandId(p != null ? p.getParentId() : null); r.setBindTime(LocalDateTime.now()); relationMapper.insert(r); // 缓存预热 redisTemplate.opsForValue().set("rel:" + userId, JSON.toJSONString(r), 30, TimeUnit.DAYS); } finally { redisLock.release(lock); }

}

规则底线:

• 一个用户只能有一条有效上级(唯一索引兜底)

• 老用户不可以被新推广员“劫持”

• 关系链可深存,但分佣只取一级、二级

三、推一反三计数引擎:循环轮次不超发

核心不是“分销层级”,是“有效推荐计数”。要区分:

• 有效订单:新客首单、已支付、未退款、指定活动商品

• 无效订单:自购、老客复购(视规则)、退款单

计数用 Redis 原子自增 + DB 落账:
public void onPaid(OrderPaidEvent e) {
Activity act = activityMapper.valid(e.getActivityId());
if (act == null) return;

// 判断被推荐人是否新客 if (!isNewBuyer(e.getBuyerId(), act)) return; String counterKey = "push:cnt:" + e.getInviterId() + ":" + act.getId(); Long n = redisTemplate.opsForValue().increment(counterKey); // 写计数流水(审计) pushLogMapper.insert(new PushLog(e.getInviterId(), e.getBuyerId(), n)); // 满N人触发返现(推三返一) if (n % act.getNeedCount() == 0) { mqSender.sendRewardEvent(new RewardEvent(e.getInviterId(), act.getId(), n)); }

}

返现发放(MQ 消费,幂等):
@RabbitListener(queues = “reward.queue”)
public void grantReward(RewardEvent evt) {
String idem = “reward:done:” + evt.getInviterId()
+ “:” + evt.getActivityId() + “:” + evt.getRound();
if (Boolean.TRUE.equals(redisTemplate.hasKey(idem))) return;

try { BigDecimal amount = activityMapper.rewardAmount(evt.getActivityId()); // 冻结入账,售后期后解冻 accountService.freezeGrant(evt.getInviterId(), amount, evt.getOrderNo()); redisTemplate.opsForValue().set(idem, "1", 30, TimeUnit.DAYS); } catch (DuplicateKeyException ignore) {}

}

循环机制:本轮满 3 人发奖后,计数进入下一轮,不清零历史,只开新轮次。

四、二级分佣:合规优先,钱算准

推一反三之外,日常下单还有“直推/间推”佣金,但层级严格控死两级。

佣金试算:
public List calc(Order order) {
List list = new ArrayList<>();
// 基数:实付金额(扣运费、扣券平台承担部分)
BigDecimal base = order.getPayAmount()
.subtract(order.getFreight())
.subtract(order.getPlatCoupon());

Relation rel = relationMapper.selectByUserId(order.getBuyerId()); if (rel == null) return list; // 一级 if (rel.getParentId() != null) { BigDecimal l1 = base.multiply(rateConfig.level1(rel.getParentId())) .setScale(2, RoundingMode.HALF_UP); list.add(new CommissionDetail(rel.getParentId(), 1, l1, FROZEN)); } // 二级(到此为止) if (rel.getGrandId() != null) { BigDecimal l2 = base.multiply(rateConfig.level2(rel.getGrandId())) .setScale(2, RoundingMode.HALF_UP); list.add(new CommissionDetail(rel.getGrandId(), 2, l2, FROZEN)); } return list;

}

状态机:
public enum CommStatus {
FROZEN, // 待结算(售后期内)
SETTLED, // 可提现
WITHDRAWN, // 已提现
INVALID; // 退款作废

public boolean allow(CommStatus next) { return switch (this) { case FROZEN -> next == SETTLED || INVALID; case SETTLED -> next == WITHDRAWN; default -> false; }; }

}

五、退款冲正:最容易被漏掉的资损口

用户退款后,推一反三计数和佣金都要回撤:
@Transactional
public void onRefund(RefundEvent e) {
// 1. 订单级佣金回滚
List cs = commissionMapper.byOrder(e.getOrderNo());
for (CommissionDetail c : cs) {
if (c.getStatus() == FROZEN) {
c.setStatus(INVALID);
} else if (c.getStatus() == SETTLED) {
// 已解冻:负向流水冲抵
accountService.negativeDeduct(c.getUserId(), c.getAmount(), e.getOrderNo());
}
commissionMapper.updateById©;
}

// 2. 推一反三计数回撤 PushLog log = pushLogMapper.lastValid(e.getBuyerId(), e.getActivityId()); if (log != null) { String key = "push:cnt:" + log.getInviterId() + ":" + e.getActivityId(); redisTemplate.opsForValue().decrement(key); // 若已发奖,回收返现 if (alreadyRewarded(log)) { accountService.rollbackFreeze(log.getInviterId(), e.getOrderNo()); } }

}

冲正三档:冻结作废、余额扣回、提现拦截。追不回进坏账台账+告警。

六、防超卖与高并发细节

6.1 资格商品库存

UPDATE sku SET stock = stock - 1, version = version + 1 WHERE sku_id = #{skuId} AND stock > 0

下单前 Redis 预扣,支付失败回滚。

6.2 返现幂等

• MQ 消费前查 reward:done:{inviter}:{act}:{round}

• DB 唯一索引 uk_reward (inviter_id, activity_id, round)

  • 分布式锁防并发轮次切换

6.3 风控

• 同设备/IP批量注册 → 标记风险单

• 自推自返(自己扫自己码)→ 直接拦截

• 短期高频分享不支付 → 降权推广位

• 活动独立台账:参与人数、达标率、返现支出、裂变获客成本

七、小程序端关键页面

用户端:

• 商品详情“邀3人返本单”进度条

• 我的推广:还差 N 人、已返金额、轮次记录

• 佣金中心:冻结/可提现/已提现分离

• 专属海报(带 inviterCode 小程序码)

运营后台:

• 活动规则配置(推N返一、循环开关、售后期)

• 分佣比例灰度(按商品/用户等级)

• 异常单复核、返现追回、关系审计日志

八、合规红线(必须写进系统约束)

• 分佣层级:最多二级,三级及以上在代码里直接拦截

• 无入门费:不卖“推广资格包”作为唯一标的

• 佣金来源:仅来自真实交易订单,退款必回吐

• 规则透明:佣金比例、返现条件在前端协议明示

  • 实名提现:微信实名+绑卡,打款走企业付款API
    • 关系不可随意改:绑定后保护期锁定,运营后台改关系留审计

别把“团队无限代”写进配置项。合规不是运营自觉,是系统里没有这个按钮。

九、落地节奏

  1. MVP:资格商品下单 → 分享绑定 → 满3返1(先手动解冻)
  2. 增强:二级分佣、退款冲正、轮次循环、风控黑名单
  3. 规模化:多活动并行、分账自动化、数据大屏、私域SCRM

推一反三商城的技术含量,不在“分享按钮”,而在把裂变当成金融事务:每一次点击都对应一条可回滚的资金承诺。关系链锁死、计数原子化、佣金状态机、冲正闭环,这四根柱子立住,活动才能放心放量。