JooLun Plus 百科 ⬇ 源码下载

08.04 商城分销功能

102353 于 2026-10-17 14:14:33 +08:00 修改了此页面

分销逻辑:https://www.joolun.com/h-nd-127.html#_np=104_1162

推广关系绑定

  • 商城端:用户在分享页面、生成海报给好友的时候,系统会在url后自动加上当前用户的用户编码(userCode):sharer_user_code;例如pages\goods\goods-detail\index.vue
onShareAppMessage: function() {
    let goodsSpu = this.goodsSpu;
    let title = goodsSpu.name;
    let imageUrl = goodsSpu.picUrls[0];

    const userInfo = uni.getStorageSync('user_info')
    let userCode = userInfo ? '&sharer_user_code='+userInfo.userCode : ''
    let path = 'pages/goods/goods-detail/index?id=' + goodsSpu.id + userCode;
    return {
        title: title,
        path: path,
        imageUrl: imageUrl,
        success: function(res) {
            if (res.errMsg == 'shareAppMessage:ok') {
                console.log(res.errMsg);
            }
        },
        fail: function(res) { // 转发失败
        }
    };
},
  • 商城端:被分享用户通过分享进入商城后,系统会自动将传来的分享人用户编码(sharer_user_code)保存在本地;例如pages\goods\goods-detail\index.vue
onLoad(options) {
    // 保存别人分享来的 userCode
    util.saveSharerUserCode(options);
    let id;
    if (options.scene) {
        //接受二维码中参数
        let scenes = decodeURIComponent(options.scene).split('&');
        id = scenes[0];
    } else {
        id = options.id;
    }
    this.id = id;
    app.initPage().then(res => {
        this.goodsGet(id);
        this.couponInfoPage(id);
        this.shoppingCartCountFun();
        this.goodsAppraisesPage();
        this.listEnsureBySpuId(id);
    });
},
  • 商城端:被分享人注册或登录商城时,如被分享人此前已登录商城则不会触发绑定机制,系统会自动将分享人用户编码传入接口;\utils\api.js
loginWxMa: data => {
    //如果有分享人则带上分享人的user_code
    data = util.dataAddSharerUserCode(data)
    //微信小程序登录接口
    return request('/mallapi/wxuser/loginma', 'post', data, false);
},
loginWxMp: data => {
    //如果有分享人则带上分享人的user_code
    data = util.dataAddSharerUserCode(data)
    //微信公众号登录接口
    return request('/mallapi/wxuser/loginmp', 'post', data, false);
},
loginByPhoneMa: data => {
    //如果有分享人则带上分享人的user_code
    data = util.dataAddSharerUserCode(data)
    //商城通过小程序授权手机号一键登录商城
    return request('/mallapi/userinfo/ma/phone/login', 'post', data, true);
},
loginByPhone: data => {
    //如果有分享人则带上分享人的user_code
    data = util.dataAddSharerUserCode(data)
    //商城手机验证码登录商城
    return request('/mallapi/userinfo/phone/login', 'post', data, true);
},
login: data => {
    //如果有分享人则带上分享人的user_code
    data = util.dataAddSharerUserCode(data)
    //商城账号登录
    return request('/mallapi/userinfo/login', 'post', data, true);
},
register: data => {
    //如果有分享人则带上分享人的user_code
    data = util.dataAddSharerUserCode(data)
    //账号注册
    return request('/mallapi/userinfo/register', 'post', data, true);
},
  • 后端:上述接口调用”分销关系上级绑定“方法,判断是否满足绑定条件进行上下级关系绑定;com\joolun\cloud\mall\api\service\impl\DistributionConfigServiceImpl.javaparentBind方法
//分销关系上级绑定
userInfo.setSharerUserCode(sharerUserCode);
distributionConfigService.parentBind(userType,userInfo);

普通订单参与分销返利

  • 当普通订单支付完成,系统收到支付回调时处理分销逻辑;com\joolun\cloud\mall\api\service\impl\OrderInfoServiceImpl.javanotifyOrder方法
if(MallConstants.ORDER_TYPE_0.equals(orderInfo.getOrderType())){//普通订单才参与分销
    //分销逻辑
    DistributionConfig distributionConfig = distributionConfigService.getOne(Wrappers.emptyWrapper());
    if(CommonConstants.YES.equals(distributionConfig.getEnable())){//判断是否已开启分销
        //获取订单用户信息
        UserInfo userInfo = userInfoService.getById(orderInfo.getUserId());
        //如果分销模式为满额分销,在此判断当前用户是否能成为分销员
        if(MallConstants.DISTRIBUTION_MODEL_3.equals(distributionConfig.getDistributionModel())){
            //先判断当前用户是否已经成为分销员
            DistributionUser distributionUser = distributionUserService.getById(userInfo.getId());
            if(distributionUser == null){
                //还不是分销员,获取用户的消费记录
                UserRecord userRecord1 = userRecordService.getById(userInfo.getId());
                if(userRecord1 != null){
                    //判断用户总计消费金额是否大于等于指定额度
                    if(userRecord1.getTotalAmount().compareTo(distributionConfig.getFullAmount()) >= 0){
                        //用户总计消费金额大于等于指定额度,则将当前用户设为分销员
                        distributionUser = new DistributionUser();
                        distributionUser.setUserId(userInfo.getId());
                        distributionUserService.save(distributionUser);
                    }
                }
            }
        }
        //判断订单用户是否有上级
        if(StrUtil.isNotBlank(userInfo.getParentId())){
            DistributionUser distributionUser1 = distributionUserService.getById(userInfo.getParentId());
            //判断订单用户上级是否是分销员
            if(distributionUser1 != null){
                //一级返利
                DistributionOrder distributionOrder1 = new DistributionOrder();
                distributionOrder1.setDistributionLevel(MallConstants.DISTRIBUTION_LEVEL_1);
                distributionOrder1.setDistributionUserId(distributionUser1.getUserId());
                distributionOrder1.setUserId(userInfo.getId());
                distributionOrder1.setOrderId(orderInfo.getId());
                distributionOrder1.setShopId(orderInfo.getShopId());
                distributionOrder1.setCommissionStatus(MallConstants.DISTRIBUTION_COMMISSION_STATUS_1);
                distributionOrder1.setCommission(BigDecimal.ZERO);
                List<DistributionOrderItem> listDistributionOrderItem1 = new ArrayList<>();
                listOrderItem.forEach(orderItem1 -> {
                    //获取sku信息
                    GoodsSku goodsSku1 = goodsSkuService.getById(orderItem1.getSkuId());
                    //计算此订单明细的返利金额
                    BigDecimal commission1 = BigDecimal.valueOf(goodsSku1.getFirstRebate()).divide(BigDecimal.valueOf(100)).multiply(orderItem1.getPaymentPrice());
                    if(commission1.compareTo(BigDecimal.ZERO) == 1){//返利金额大于0才入库
                        DistributionOrderItem distributionOrderItem1 = new DistributionOrderItem();
                        distributionOrderItem1.setDistributionOrderId(distributionOrder1.getId());
                        distributionOrderItem1.setOrderId(orderItem1.getOrderId());
                        distributionOrderItem1.setOrderItemId(orderItem1.getId());
                        distributionOrderItem1.setCommission(commission1);
                        listDistributionOrderItem1.add(distributionOrderItem1);
                        distributionOrder1.setCommission(distributionOrder1.getCommission().add(commission1));
                    }
                });
                if(distributionOrder1.getCommission().compareTo(BigDecimal.ZERO) == 1){//返利金额大于0才入库
                    //新增分销订单
                    distributionOrderService.save(distributionOrder1);
                    //批量新增分销订单明细
                    listDistributionOrderItem1.forEach(distributionOrderItem1 -> {
                        distributionOrderItem1.setDistributionOrderId(distributionOrder1.getId());
                    });
                    distributionOrderItemService.saveBatch(listDistributionOrderItem1);
                    //更新分销员累计佣金金额
                    distributionUserService.updateCommissionTotal(distributionUser1.getUserId(),distributionOrder1.getCommission());

                    //加入redis,冻结时间自动解冻
                    String keyRedis = String.valueOf(StrUtil.format("{}{}:{}",MallConstants.REDIS_DISTRIBUTION_ORDER_THAW, TenantContextHolder.getTenantId(), distributionOrder1.getId()));
                    redisTemplate.opsForValue().set(keyRedis, distributionOrder1.getId() , distributionConfig.getFrozenTime() , TimeUnit.HOURS);//设置过期时间
                }
            }
            //获取一级用户信息
            UserInfo userInfo1 = userInfoService.getById(userInfo.getParentId());
            //判断一级用户是否有上级
            if(StrUtil.isNotBlank(userInfo1.getParentId())){
                DistributionUser distributionUser2 = distributionUserService.getById(userInfo1.getParentId());
                //判断一级用户上级是否是分销员
                if(distributionUser2 != null){
                    //二级返利
                    DistributionOrder distributionOrder2 = new DistributionOrder();
                    distributionOrder2.setDistributionLevel(MallConstants.DISTRIBUTION_LEVEL_2);
                    distributionOrder2.setDistributionUserId(distributionUser2.getUserId());
                    distributionOrder2.setUserId(userInfo.getId());
                    distributionOrder2.setOrderId(orderInfo.getId());
                    distributionOrder2.setShopId(orderInfo.getShopId());
                    distributionOrder2.setCommissionStatus(MallConstants.DISTRIBUTION_COMMISSION_STATUS_1);
                    distributionOrder2.setCommission(BigDecimal.ZERO);
                    List<DistributionOrderItem> listDistributionOrderItem2 = new ArrayList<>();
                    listOrderItem.forEach(orderItem2 -> {
                        //获取sku信息
                        GoodsSku goodsSku2 = goodsSkuService.getById(orderItem2.getSkuId());
                        //计算此订单明细的返利金额
                        BigDecimal commission2 = BigDecimal.valueOf(goodsSku2.getSecondRebate()).divide(BigDecimal.valueOf(100)).multiply(orderItem2.getPaymentPrice());
                        if(commission2.compareTo(BigDecimal.ZERO) == 1) {//返利金额大于0才入库
                            DistributionOrderItem distributionOrderItem2 = new DistributionOrderItem();
                            distributionOrderItem2.setDistributionOrderId(distributionOrder2.getId());
                            distributionOrderItem2.setOrderId(orderItem2.getOrderId());
                            distributionOrderItem2.setOrderItemId(orderItem2.getId());
                            distributionOrderItem2.setCommission(commission2);
                            listDistributionOrderItem2.add(distributionOrderItem2);
                            distributionOrder2.setCommission(distributionOrder2.getCommission().add(commission2));
                        }
                    });
                    if(distributionOrder2.getCommission().compareTo(BigDecimal.ZERO) == 1){//返利金额大于0才入库
                        //新增分销订单
                        distributionOrderService.save(distributionOrder2);
                        //批量新增分销订单明细
                        listDistributionOrderItem2.forEach(distributionOrderItem2 -> {
                            distributionOrderItem2.setDistributionOrderId(distributionOrder2.getId());
                        });
                        distributionOrderItemService.saveBatch(listDistributionOrderItem2);
                        //更新分销员累计佣金金额
                        distributionUserService.updateCommissionTotal(distributionUser2.getUserId(),distributionOrder2.getCommission());

                        //加入redis,冻结时间自动解冻
                        String keyRedis = String.valueOf(StrUtil.format("{}{}:{}",MallConstants.REDIS_DISTRIBUTION_ORDER_THAW, TenantContextHolder.getTenantId(), distributionOrder2.getId()));
                        redisTemplate.opsForValue().set(keyRedis, distributionOrder2.getId() , distributionConfig.getFrozenTime() , TimeUnit.HOURS);//设置过期时间
                    }
                }
            }
        }
    }
}

佣金解冻

  • 分销返利后,佣金会被冻结,由redis过期机制控制,监听redis过期解冻冻结金额;com\joolun\cloud\mall\api\listener\RedisKeyExpirationListener.java
//分销佣金自动解冻
if(body.contains(MallConstants.REDIS_DISTRIBUTION_ORDER_THAW)) {
    body = body.replace(MallConstants.REDIS_DISTRIBUTION_ORDER_THAW, "");
    String[] str = body.split(":");
    String distributionOrderId = str[1];
    TenantContextHolder.setTenantId(str[0]);
    DistributionOrder distributionOrder = distributionOrderService.getById(distributionOrderId);
    if(distributionOrder != null && MallConstants.DISTRIBUTION_COMMISSION_STATUS_1.equals(distributionOrder.getCommissionStatus())){//只有冻结状态的订单才能解冻
        distributionOrder.setCommissionStatus(MallConstants.DISTRIBUTION_COMMISSION_STATUS_2);
        distributionOrderService.updateById(distributionOrder);
    }
}

佣金提现

  • 用户提交佣金提现申请,后台商城管理员人工转账处理提现申请

佣金结算承担口径

  • 分销佣金默认由订单所属店铺承担,属于店铺营销成本。
  • 佣金结算对象为分销员;供应商货款不因分销佣金被压缩。
  • 普通商户收款、服务商收款、无外部收款只影响资金入口和部分结算关系,不改变分销佣金由店铺承担的口径。