拉新奖励逻辑更新

This commit is contained in:
tianfeng 2026-03-06 11:31:10 +08:00
parent 7cbcef2772
commit e2849d2cca
5 changed files with 228 additions and 79 deletions

View File

@ -1,5 +1,6 @@
package com.red.circle.other.domain.gateway.user.ability; package com.red.circle.other.domain.gateway.user.ability;
import com.red.circle.other.domain.model.user.RechargeCommissionResult;
import java.math.BigDecimal; import java.math.BigDecimal;
/** /**
@ -15,9 +16,9 @@ public interface InviteUserGateway {
* @param rechargeAmount 充值金额 * @param rechargeAmount 充值金额
* @param sysOrigin 系统 * @param sysOrigin 系统
* @param inviteUserId 被邀请人(充值人) * @param inviteUserId 被邀请人(充值人)
* @return 佣金处理结果无邀请关系时返回null
*/ */
void getRechargeCommission(BigDecimal rechargeAmount, String sysOrigin, RechargeCommissionResult getRechargeCommission(BigDecimal rechargeAmount, String sysOrigin,
Long inviteUserId); Long inviteUserId);
} }

View File

@ -0,0 +1,29 @@
package com.red.circle.other.domain.model.user;
import java.math.BigDecimal;
import lombok.Data;
/**
* 邀请佣金处理结果.
*
* @author tf
*/
@Data
public class RechargeCommissionResult {
/** 邀请人(A)的userId. */
private Long inviterUserId;
/** 被邀请人(B)的userId. */
private Long inviteeUserId;
/** 被邀请人累计充值金额Redis累计用于档位判断. */
private BigDecimal inviteeTotalRecharge;
/** 系统来源. */
private String sysOrigin;
/** 被邀请人是否为7天内新用户. */
private boolean newUser;
}

View File

@ -13,7 +13,12 @@ public enum UserOneTimeTaskTypeEnum {
/** /**
* 首次充值. * 首次充值.
*/ */
FIRST_CHARGE; FIRST_CHARGE,
/**
* 邀请奖励.
*/
INVITE_REWARD;
} }

View File

@ -3,7 +3,9 @@ package com.red.circle.other.infra.gateway.user;
import com.alibaba.nacos.client.naming.utils.CollectionUtils; import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum; import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.component.redis.service.RedisService;
import com.red.circle.other.domain.gateway.user.UserProfileGateway; import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.domain.model.user.RechargeCommissionResult;
import com.red.circle.other.domain.model.user.UserProfile; import com.red.circle.other.domain.model.user.UserProfile;
import com.red.circle.other.domain.ranking.RankingActivityType; import com.red.circle.other.domain.ranking.RankingActivityType;
import com.red.circle.other.domain.ranking.RankingCycleType; import com.red.circle.other.domain.ranking.RankingCycleType;
@ -11,26 +13,13 @@ import com.red.circle.other.domain.ranking.RankingDimension;
import com.red.circle.other.infra.database.mongo.entity.activity.RankingActivityRecord; import com.red.circle.other.infra.database.mongo.entity.activity.RankingActivityRecord;
import com.red.circle.other.infra.database.rds.dao.user.user.UserInviteUserDAO; import com.red.circle.other.infra.database.rds.dao.user.user.UserInviteUserDAO;
import com.red.circle.other.infra.database.rds.entity.user.user.InviteUserRechargeCommission; import com.red.circle.other.infra.database.rds.entity.user.user.InviteUserRechargeCommission;
import com.red.circle.other.infra.database.rds.entity.user.user.OneTimeTask;
import com.red.circle.other.infra.database.rds.entity.user.user.UserInviteUser; import com.red.circle.other.infra.database.rds.entity.user.user.UserInviteUser;
import com.red.circle.other.infra.database.rds.service.user.user.OneTimeTaskService;
import com.red.circle.other.infra.gateway.RankingActivityGateway;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.other.domain.gateway.user.ability.InviteUserGateway;
import com.red.circle.other.infra.database.cache.service.user.UserInviteCacheService;
import com.red.circle.other.infra.database.rds.entity.user.user.InviteUserRegister;
import com.red.circle.other.infra.database.rds.service.user.user.InviteUserRechargeCommissionService; import com.red.circle.other.infra.database.rds.service.user.user.InviteUserRechargeCommissionService;
import com.red.circle.other.infra.database.rds.service.user.user.InviteUserRegisterService;
import com.red.circle.other.infra.database.rds.service.user.user.InviteUserSummaryService; import com.red.circle.other.infra.database.rds.service.user.user.InviteUserSummaryService;
import java.math.BigDecimal; import com.red.circle.other.infra.database.cache.service.user.UserInviteCacheService;
import java.math.RoundingMode; import com.red.circle.other.infra.gateway.RankingActivityGateway;
import java.sql.Timestamp; import com.red.circle.other.domain.gateway.user.ability.InviteUserGateway;
import java.time.Duration; import com.red.circle.tool.core.date.TimestampUtils;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils; import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient; import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd; import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
@ -39,6 +28,15 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Timestamp;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/** /**
* 被邀请的用户充值邀请人获得佣金处理 实现. * 被邀请的用户充值邀请人获得佣金处理 实现.
* *
@ -49,61 +47,57 @@ import org.springframework.stereotype.Component;
@RequiredArgsConstructor @RequiredArgsConstructor
public class InviteUserGatewayImpl implements InviteUserGateway { public class InviteUserGatewayImpl implements InviteUserGateway {
private static final String INVITE_RECHARGE_TOTAL_KEY = "invite:recharge:total:%d:%d";
private static final long INVITE_RECHARGE_TOTAL_EXPIRE_DAYS = 30L;
private final WalletGoldClient walletGoldClient; private final WalletGoldClient walletGoldClient;
private final UserInviteCacheService userInviteCacheService; private final UserInviteCacheService userInviteCacheService;
private final InviteUserSummaryService inviteUserSummaryService; private final InviteUserSummaryService inviteUserSummaryService;
private final UserInviteUserDAO userInviteUserDAO; private final UserInviteUserDAO userInviteUserDAO;
private final UserProfileGateway userProfileGateway; private final UserProfileGateway userProfileGateway;
private final InviteUserRechargeCommissionService inviteUserRechargeCommissionService; private final InviteUserRechargeCommissionService inviteUserRechargeCommissionService;
private final OneTimeTaskService oneTimeTaskService;
private final RankingActivityGateway rankingActivityGateway; private final RankingActivityGateway rankingActivityGateway;
private final RedisService redisService;
/**
* 被邀请人充值邀请人获得佣金
*
* @param rechargeAmount 充值金额
* @param sysOrigin 系统
* @param inviteUserId 被邀请人(充值人)
*/
@Override @Override
public void getRechargeCommission(BigDecimal rechargeAmount, String sysOrigin, public RechargeCommissionResult getRechargeCommission(BigDecimal rechargeAmount, String sysOrigin,
Long inviteUserId) { Long inviteUserId) {
//根据被邀请人获得邀请人 //根据被邀请人获得邀请人
UserInviteUser userInviteUser = getByInviteUserId(inviteUserId); UserInviteUser userInviteUser = getByInviteUserId(inviteUserId);
if (Objects.isNull(userInviteUser)) { if (Objects.isNull(userInviteUser)) {
return; return null;
} }
//能够赚取佣金的天数 //能够赚取佣金的天数
Integer commissionDays = getCommissionDays(sysOrigin); Integer commissionDays = getCommissionDays(sysOrigin);
if (Objects.isNull(commissionDays)) { if (Objects.isNull(commissionDays)) {
log.info("能够赚取佣金的天数 => null, inviteUserId:{}", inviteUserId); log.info("能够赚取佣金的天数 => null, inviteUserId:{}", inviteUserId);
return; return null;
} }
//邀请时间 + 有效天数 > 当前时间 则可以继续获得佣金
Timestamp limitedTime = getLimitedTime(userInviteUser, commissionDays); Timestamp limitedTime = getLimitedTime(userInviteUser, commissionDays);
if (limitedTime.compareTo(TimestampUtils.now()) < 0) { if (limitedTime.compareTo(TimestampUtils.now()) < 0) {
log.info("邀请时间 + 有效天数 < 当前时间, inviteUserId:{}", inviteUserId); log.info("邀请时间 + 有效天数 < 当前时间, inviteUserId:{}", inviteUserId);
return; return null;
} }
//获得佣金比例 Double commissionRate = getCommissionRate(sysOrigin);
Double commissionRate = getCommissionRate(sysOrigin, userInviteUser.getInviteUserId());
if (Objects.isNull(commissionRate)) { if (Objects.isNull(commissionRate)) {
log.info("获得佣金比例 => null, inviteUserId:{}", inviteUserId); log.info("获得佣金比例 => null, inviteUserId:{}", inviteUserId);
return; return null;
} }
//获得的佣金 = 糖果数 * 佣金比例 //获得的佣金 = 糖果数 * 佣金比例
BigDecimal commission = getCommission(rechargeAmount, commissionRate); BigDecimal commission = getCommission(rechargeAmount, commissionRate);
if (commission.compareTo(BigDecimal.ZERO) <= 0) { if (commission.compareTo(BigDecimal.ZERO) <= 0) {
log.info("糖果数 * 佣金比例 <= 0, inviteUserId:{}", inviteUserId); log.info("糖果数 * 佣金比例 <= 0, inviteUserId:{}", inviteUserId);
return; return null;
} }
inviteUserSummaryService.incrCommission(userInviteUser.getUserId(), commission); inviteUserSummaryService.incrCommission(userInviteUser.getUserId(), commission);
inviteUserRechargeCommissionService.add(sysOrigin, userInviteUser.getUserId(), userInviteUser.getInviteUserId(), commission); inviteUserRechargeCommissionService.add(sysOrigin, userInviteUser.getUserId(),
userInviteUser.getInviteUserId(), commission);
// 累计邀请人数判断inviteUserRechargeCommissionService里是否已有该被邀请人的记录 // 累计邀请人数判断inviteUserRechargeCommissionService里是否已有该被邀请人的记录
// 查询该被邀请人在此之前是否有充值记录 // 查询该被邀请人在此之前是否有充值记录
@ -114,7 +108,7 @@ public class InviteUserGatewayImpl implements InviteUserGateway {
// 如果记录数 < 1说明是首次充值当前这条刚插入才累计邀请人数+1 // 如果记录数 < 1说明是首次充值当前这条刚插入才累计邀请人数+1
if (recordCount < 1) { if (recordCount < 1) {
log.info("被邀请人首次充值,累计邀请人数+1, inviterUserId:{}, inviteUserId:{}", log.info("被邀请人首次充值,累计邀请人数+1, inviterUserId:{}, inviteeUserId:{}",
userInviteUser.getUserId(), userInviteUser.getInviteUserId()); userInviteUser.getUserId(), userInviteUser.getInviteUserId());
inviteUserSummaryService.incrUser(userInviteUser.getUserId(), 1); inviteUserSummaryService.incrUser(userInviteUser.getUserId(), 1);
} }
@ -122,21 +116,39 @@ public class InviteUserGatewayImpl implements InviteUserGateway {
awardCommission(sysOrigin, userInviteUser.getUserId(), commission, userInviteUser.getInviteUserId()); awardCommission(sysOrigin, userInviteUser.getUserId(), commission, userInviteUser.getInviteUserId());
recordRanking(userInviteUser.getUserId(), commission.longValue()); recordRanking(userInviteUser.getUserId(), commission.longValue());
BigDecimal totalRecharge = accumulateRecharge(userInviteUser.getUserId(), inviteUserId, rechargeAmount);
RechargeCommissionResult result = new RechargeCommissionResult();
result.setInviterUserId(userInviteUser.getUserId());
result.setInviteeUserId(inviteUserId);
result.setInviteeTotalRecharge(totalRecharge);
result.setSysOrigin(sysOrigin);
result.setNewUser(isNewUserWithinDays(inviteUserId, 7));
return result;
} }
private void recordRanking(Long userId, Long quantity) { private BigDecimal accumulateRecharge(Long inviterUserId, Long inviteeUserId, BigDecimal rechargeAmount) {
RankingActivityRecord record = new RankingActivityRecord(); String key = String.format(INVITE_RECHARGE_TOTAL_KEY, inviterUserId, inviteeUserId);
record.setSysOrigin(SysOriginPlatformEnum.LIKEI.name()); Long total = redisService.increment(key, rechargeAmount.longValue());
record.setUserId(userId); if (total != null && total <= rechargeAmount.longValue()) {
record.setUserSex(1); redisService.expire(key, INVITE_RECHARGE_TOTAL_EXPIRE_DAYS, TimeUnit.DAYS);
record.setActivityType(RankingActivityType.INVITE);
record.setCycleType(RankingCycleType.WEEKLY);
record.setCycleKey(ZonedDateTimeAsiaRiyadhUtils.nowWeekMondayToInt().toString());
record.setDimension(RankingDimension.CONSUME_AMOUNT);
record.setExpiredTime(new Timestamp(System.currentTimeMillis() + 30L * 24 * 60 * 60 * 1000));
// 累计数据
rankingActivityGateway.accumulateRankingData(record, quantity);
} }
return total != null ? BigDecimal.valueOf(total) : rechargeAmount;
}
private void recordRanking(Long userId, Long quantity) {
RankingActivityRecord record = new RankingActivityRecord();
record.setSysOrigin(SysOriginPlatformEnum.LIKEI.name());
record.setUserId(userId);
record.setUserSex(1);
record.setActivityType(RankingActivityType.INVITE);
record.setCycleType(RankingCycleType.WEEKLY);
record.setCycleKey(ZonedDateTimeAsiaRiyadhUtils.nowWeekMondayToInt().toString());
record.setDimension(RankingDimension.CONSUME_AMOUNT);
record.setExpiredTime(new Timestamp(System.currentTimeMillis() + 30L * 24 * 60 * 60 * 1000));
rankingActivityGateway.accumulateRankingData(record, quantity);
}
/** /**
* 奖励佣金 * 奖励佣金
@ -164,18 +176,15 @@ public class InviteUserGatewayImpl implements InviteUserGateway {
.setScale(0, RoundingMode.DOWN); .setScale(0, RoundingMode.DOWN);
} }
private Double getCommissionRate(String sysOrigin, Long userId) { private Double getCommissionRate(String sysOrigin) {
Double commissionRate = userInviteCacheService.getCommissionRate(SysOriginPlatformEnum.valueOf(sysOrigin)); return userInviteCacheService.getCommissionRate(SysOriginPlatformEnum.valueOf(sysOrigin));
}
UserProfile userProfile = userProfileGateway.getByUserId(userId); /** 判断用户是否为注册N天内的新用户 */
Duration duration = Duration.between(userProfile.getCreateTime().toLocalDateTime(), LocalDateTime.now()); private boolean isNewUserWithinDays(Long userId, int days) {
if (duration.toDays() < 7) { UserProfile userProfile = userProfileGateway.getByUserId(userId);
OneTimeTask oneTimeTask = oneTimeTaskService.queryCompletedFirstCharge(userId, sysOrigin); Duration duration = Duration.between(userProfile.getCreateTime().toLocalDateTime(), LocalDateTime.now());
if (Objects.isNull(oneTimeTask)) { return duration.toDays() < days;
commissionRate += 0.03;
}
}
return commissionRate;
} }
private UserInviteUser getByInviteUserId(Long inviteUserId) { private UserInviteUser getByInviteUserId(Long inviteUserId) {
@ -196,13 +205,11 @@ public class InviteUserGatewayImpl implements InviteUserGateway {
} }
private Integer getCommissionDays(String sysOrigin) { private Integer getCommissionDays(String sysOrigin) {
return userInviteCacheService return userInviteCacheService.getCommissionDays(SysOriginPlatformEnum.valueOf(sysOrigin));
.getCommissionDays(SysOriginPlatformEnum.valueOf(sysOrigin));
} }
private Timestamp getLimitedTime(UserInviteUser userInviteUser, Integer commissionDays) { private Timestamp getLimitedTime(UserInviteUser userInviteUser, Integer commissionDays) {
return TimestampUtils return TimestampUtils.dateTimestampPlusDays(userInviteUser.getCreateTime().toLocalDateTime(), commissionDays);
.dateTimestampPlusDays(userInviteUser.getCreateTime().toLocalDateTime(), commissionDays);
} }
} }

View File

@ -2,6 +2,8 @@ package com.red.circle.other.app.inner.service.user.user.impl;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum; import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.common.business.enums.SendPropsOrigin;
import com.red.circle.component.redis.service.RedisService;
import com.red.circle.framework.core.asserts.ResponseAssert; import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.core.response.CommonErrorCode; import com.red.circle.framework.core.response.CommonErrorCode;
import com.red.circle.framework.dto.PageResult; import com.red.circle.framework.dto.PageResult;
@ -9,14 +11,19 @@ import com.red.circle.framework.mybatis.convertor.MybatisConvertor;
import com.red.circle.other.app.inner.convertor.user.UserInviteInnerConvertor; import com.red.circle.other.app.inner.convertor.user.UserInviteInnerConvertor;
import com.red.circle.other.app.inner.service.user.user.InviteUserClientService; import com.red.circle.other.app.inner.service.user.user.InviteUserClientService;
import com.red.circle.other.domain.gateway.user.ability.InviteUserGateway; import com.red.circle.other.domain.gateway.user.ability.InviteUserGateway;
import com.red.circle.other.domain.model.user.RechargeCommissionResult;
import com.red.circle.other.infra.database.cache.service.user.UserInviteCacheService; import com.red.circle.other.infra.database.cache.service.user.UserInviteCacheService;
import com.red.circle.other.infra.database.rds.entity.user.user.OneTimeTask;
import com.red.circle.other.infra.database.rds.query.user.InviteUserQry; import com.red.circle.other.infra.database.rds.query.user.InviteUserQry;
import com.red.circle.other.infra.database.rds.service.user.user.InviteUserRechargeCommissionService; import com.red.circle.other.infra.database.rds.service.user.user.InviteUserRechargeCommissionService;
import com.red.circle.other.infra.database.rds.service.user.user.InviteUserRegisterService; import com.red.circle.other.infra.database.rds.service.user.user.InviteUserRegisterService;
import com.red.circle.other.infra.database.rds.service.user.user.InviteUserRewardRecordService; import com.red.circle.other.infra.database.rds.service.user.user.InviteUserRewardRecordService;
import com.red.circle.other.infra.database.rds.service.user.user.InviteUserSummaryService; import com.red.circle.other.infra.database.rds.service.user.user.InviteUserSummaryService;
import com.red.circle.tool.core.date.TimestampUtils; import com.red.circle.other.infra.database.rds.service.user.user.OneTimeTaskService;
import com.red.circle.tool.core.text.StringUtils; import com.red.circle.other.infra.enums.user.user.UserOneTimeTaskTypeEnum;
import com.red.circle.other.inner.endpoint.activity.PropsActivityClient;
import com.red.circle.other.inner.endpoint.sys.EnumConfigClient;
import com.red.circle.other.inner.model.cmd.activity.SendActivityRewardCmd;
import com.red.circle.other.inner.model.cmd.user.InviteUserQryCmd; import com.red.circle.other.inner.model.cmd.user.InviteUserQryCmd;
import com.red.circle.other.inner.model.cmd.user.SysInviteUserConfigCmd; import com.red.circle.other.inner.model.cmd.user.SysInviteUserConfigCmd;
import com.red.circle.other.inner.model.cmd.user.UserInviteRewardQryCmd; import com.red.circle.other.inner.model.cmd.user.UserInviteRewardQryCmd;
@ -26,13 +33,23 @@ import com.red.circle.other.inner.model.dto.user.InviteUserRewardRecordDTO;
import com.red.circle.other.inner.model.dto.user.InviteUserSummaryDTO; import com.red.circle.other.inner.model.dto.user.InviteUserSummaryDTO;
import com.red.circle.other.inner.model.dto.user.PageInviteUserRegisterDTO; import com.red.circle.other.inner.model.dto.user.PageInviteUserRegisterDTO;
import com.red.circle.other.inner.model.dto.user.SysInviteUserConfigDTO; import com.red.circle.other.inner.model.dto.user.SysInviteUserConfigDTO;
import java.math.BigDecimal; import com.red.circle.tool.core.date.TimestampUtils;
import java.util.List; import com.red.circle.tool.core.sequence.IdWorkerUtils;
import java.util.Objects; import com.red.circle.tool.core.text.StringUtils;
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/** /**
* 邀请用户. * 邀请用户.
* *
@ -43,6 +60,21 @@ import org.springframework.stereotype.Service;
@RequiredArgsConstructor @RequiredArgsConstructor
public class InviteUserClientServiceImpl implements InviteUserClientService { public class InviteUserClientServiceImpl implements InviteUserClientService {
// 档位阈值
private static final long TIER1_THRESHOLD = 10_000L;
private static final long TIER2_THRESHOLD = 50_000L;
private static final long TIER3_THRESHOLD = 100_000L;
// 档位道具id
private static final long TIER1_PROPS_ID = 2029448725407711234L;
private static final long TIER2_PROPS_ID = 2029449081176965121L;
private static final long TIER3_PROPS_ID = 2029449364032438273L;
// 档位金币奖励
private static final long TIER1_GOLD = 2000L;
private static final long TIER2_GOLD = 5000L;
private static final long TIER3_GOLD = 5000L;
private final InviteUserGateway inviteUserGateway; private final InviteUserGateway inviteUserGateway;
private final UserInviteCacheService userInviteCacheService; private final UserInviteCacheService userInviteCacheService;
private final UserInviteInnerConvertor userInviteInnerConvertor; private final UserInviteInnerConvertor userInviteInnerConvertor;
@ -50,17 +82,99 @@ public class InviteUserClientServiceImpl implements InviteUserClientService {
private final InviteUserRegisterService inviteUserRegisterService; private final InviteUserRegisterService inviteUserRegisterService;
private final InviteUserRewardRecordService inviteUserRewardRecordService; private final InviteUserRewardRecordService inviteUserRewardRecordService;
private final InviteUserRechargeCommissionService rechargeCommissionService; private final InviteUserRechargeCommissionService rechargeCommissionService;
private final PropsActivityClient propsActivityClient;
private final WalletGoldClient walletGoldClient;
private final OneTimeTaskService oneTimeTaskService;
@Override @Override
public void processRechargeCommission(BigDecimal rechargeAmount, String sysOrigin, public void processRechargeCommission(BigDecimal rechargeAmount, String sysOrigin,
Long inviteUserId) { Long inviteUserId) {
try { try {
inviteUserGateway.getRechargeCommission(rechargeAmount, sysOrigin, inviteUserId); RechargeCommissionResult result = inviteUserGateway.getRechargeCommission(rechargeAmount, sysOrigin, inviteUserId);
if (Objects.isNull(result)) {
return;
}
checkAndAwardTiers(result);
} catch (Exception e) { } catch (Exception e) {
log.error("被邀请人充值邀请人获得佣金累计错误: {}", Throwables.getStackTraceAsString(e)); log.error("被邀请人充值邀请人获得佣金累计错误: {}", Throwables.getStackTraceAsString(e));
} }
} }
/**
* 根据累计充值金额检查并发放档位奖励
*/
private void checkAndAwardTiers(RechargeCommissionResult result) {
if (!result.isNewUser()) {
return;
}
long total = result.getInviteeTotalRecharge().longValue();
if (total >= TIER3_THRESHOLD) {
tryAwardTier(result, 3, TIER3_PROPS_ID, TIER3_GOLD);
tryAwardTier(result, 2, TIER2_PROPS_ID, TIER2_GOLD);
tryAwardTier(result, 1, TIER1_PROPS_ID, TIER1_GOLD);
} else if (total >= TIER2_THRESHOLD) {
tryAwardTier(result, 2, TIER2_PROPS_ID, TIER2_GOLD);
tryAwardTier(result, 1, TIER1_PROPS_ID, TIER1_GOLD);
} else if (total >= TIER1_THRESHOLD) {
tryAwardTier(result, 1, TIER1_PROPS_ID, TIER1_GOLD);
}
}
/**
* 尝试发放指定档位奖励幂等
* 金币发给邀请人A道具发给被邀请人B
*/
private void tryAwardTier(RechargeCommissionResult result, int tier, long propsId, long gold) {
String taskType = UserOneTimeTaskTypeEnum.INVITE_REWARD.name() + "_" + tier;
OneTimeTask alreadyRewarded = oneTimeTaskService.query()
.eq(OneTimeTask::getUserId, result.getInviterUserId())
.eq(OneTimeTask::getSysOrigin, result.getSysOrigin())
.eq(OneTimeTask::getTaskType, taskType)
.last("LIMIT 1")
.getOne();
if (alreadyRewarded != null) {
return;
}
log.info("发放邀请奖励档位{}: inviterUserId={}, inviteeUserId={}", tier,
result.getInviterUserId(), result.getInviteeUserId());
// 写入记录幂等保证
oneTimeTaskService.save(new OneTimeTask()
.setUserId(result.getInviterUserId())
.setSysOrigin(result.getSysOrigin())
.setTaskType(taskType)
.setRewardQuantity(BigDecimal.valueOf(gold))
.setAwardStatus(Boolean.TRUE)
);
// 金币奖励发给邀请人A
walletGoldClient.changeBalance(GoldReceiptCmd.builder()
.appIncome()
.userId(result.getInviterUserId())
.eventId(result.getInviteeUserId())
.sysOrigin(result.getSysOrigin())
.origin(GoldOrigin.INVITE_USER_REWARDS)
.originDescribe(GoldOrigin.INVITE_USER_REWARDS.getDesc())
.amount(BigDecimal.valueOf(gold))
.build());
// 道具奖励发给被邀请人B
propsActivityClient.sendActivityReward(new SendActivityRewardCmd()
.setTrackId(IdWorkerUtils.getId())
.setSysOrigin(SysOriginPlatformEnum.LIKEI)
.setAcceptUserId(result.getInviteeUserId())
.setSourceGroupId(propsId)
.setOrigin(SendPropsOrigin.INVITE_USER_REWARDS)
);
}
@Override @Override
public List<InviteUserRegisterDTO> pageInviteUserRegister(Integer pageNumber, Long userId) { public List<InviteUserRegisterDTO> pageInviteUserRegister(Integer pageNumber, Long userId) {
return userInviteInnerConvertor.toListInviteUserRegisterDTO( return userInviteInnerConvertor.toListInviteUserRegisterDTO(
@ -107,10 +221,8 @@ public class InviteUserClientServiceImpl implements InviteUserClientService {
.convert(userInviteInnerConvertor::toInviteUserRewardRecordDTO); .convert(userInviteInnerConvertor::toInviteUserRewardRecordDTO);
} }
@Override @Override
public PageResult<PageInviteUserRegisterDTO> pageInviteUserRegisterAll(InviteUserQryCmd query) { public PageResult<PageInviteUserRegisterDTO> pageInviteUserRegisterAll(InviteUserQryCmd query) {
InviteUserQry inviteUserQry = new InviteUserQry(); InviteUserQry inviteUserQry = new InviteUserQry();
inviteUserQry.setSysOrigin(query.getSysOrigin()); inviteUserQry.setSysOrigin(query.getSysOrigin());
inviteUserQry.setUserId(query.getUserId()); inviteUserQry.setUserId(query.getUserId());
@ -128,7 +240,6 @@ public class InviteUserClientServiceImpl implements InviteUserClientService {
inviteUserQry).convert(userInviteInnerConvertor::toPageInviteUserRegisterDTO); inviteUserQry).convert(userInviteInnerConvertor::toPageInviteUserRegisterDTO);
} }
@Override @Override
public void updateConfig(SysInviteUserConfigCmd config) { public void updateConfig(SysInviteUserConfigCmd config) {
ResponseAssert.isFalse(CommonErrorCode.TYPE_IS_NOT_IN_SCOPE, ResponseAssert.isFalse(CommonErrorCode.TYPE_IS_NOT_IN_SCOPE,
@ -141,12 +252,8 @@ public class InviteUserClientServiceImpl implements InviteUserClientService {
} else { } else {
userInviteCacheService.setCommissionRate(sysOrigin, 0.0); userInviteCacheService.setCommissionRate(sysOrigin, 0.0);
} }
} }
/**
* 邀请用户规则
*/
@Override @Override
public SysInviteUserConfigDTO getConfig(String sysOrigin) { public SysInviteUserConfigDTO getConfig(String sysOrigin) {
SysInviteUserConfigDTO vo = new SysInviteUserConfigDTO(); SysInviteUserConfigDTO vo = new SysInviteUserConfigDTO();