推广关系绑定
- 商城端:用户在分享页面、生成海报给好友的时候,系统会在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);
}
}
佣金提现
- 用户提交佣金提现申请,后台商城管理员人工转账处理提现申请
佣金结算承担口径
- 分销佣金默认由订单所属店铺承担,属于店铺营销成本。
- 佣金结算对象为分销员;供应商货款不因分销佣金被压缩。
- 普通商户收款、服务商收款、无外部收款只影响资金入口和部分结算关系,不改变分销佣金由店铺承担的口径。