package com.taoke.autopay.manager;
|
|
import com.alipay.api.AlipayApiException;
|
import com.taoke.autopay.dao.credit.CreditExchangeRecordMapper;
|
import com.taoke.autopay.dao.credit.ExchangeRateMapper;
|
import com.taoke.autopay.entity.credit.*;
|
import com.taoke.autopay.exception.UserCreditExchangeException;
|
import com.taoke.autopay.service.credit.*;
|
import com.taoke.autopay.utils.AlipayUtil;
|
import com.taoke.autopay.utils.TimeUtil;
|
import org.springframework.stereotype.Component;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import javax.annotation.Resource;
|
import java.math.BigDecimal;
|
import java.math.RoundingMode;
|
import java.util.Date;
|
import java.util.List;
|
|
@Component
|
public class UserCreditExchangeManager {
|
|
@Resource
|
private UserCreditBalanceService userCreditBalanceService;
|
|
@Resource
|
private CreditExchangeRecordService userCreditExchangeRecordService;
|
|
@Resource
|
private UserAlipayBindingService userAlipayBindingService;
|
|
@Resource
|
private ExchangeRateService exchangeRateService;
|
|
@Resource
|
private CreditSettingService creditSettingService;
|
|
@Resource
|
private UserCreditRecordService userCreditRecordService;
|
|
@Resource
|
private UserCreditManager userCreditManager;
|
|
/**
|
* 用户积分兑换
|
*
|
* @param request 兑换请求实体
|
* @return 兑换记录ID
|
*/
|
@Transactional(rollbackFor = Exception.class)
|
public Long exchangeCredit(CreditExchangeRecord request) throws UserCreditExchangeException {
|
Long userId = request.getUid();
|
CreditExchangeRecord.ExchangeType exchangeType = request.getExchangeType();
|
if (exchangeType != CreditExchangeRecord.ExchangeType.FUND_EXCHANGE) {
|
throw new UserCreditExchangeException(UserCreditExchangeException.CODE_COMMON, "只支持红包兑换");
|
}
|
|
// 检查用户积分余额是否足够
|
UserCreditBalance balance = userCreditBalanceService.getCreditBalanceByUserId(userId);
|
if (balance == null || balance.getCreditBalance() < request.getConsumedCredits()) {
|
throw new UserCreditExchangeException(UserCreditExchangeException.CODE_BALANCE_NOT_ENOUGH, "用户积分不足");
|
}
|
|
|
// 如果是红包兑换,判断用户兑换频率
|
if (exchangeType == CreditExchangeRecord.ExchangeType.FUND_EXCHANGE) {
|
checkRedPacketExchangeFrequency(userId);
|
}
|
|
// 查询用户绑定的支付宝账户
|
List<UserAlipayBinding> alipayBindings = userAlipayBindingService.getBindingsByUid(userId);
|
if (alipayBindings == null || alipayBindings.isEmpty()) {
|
throw new UserCreditExchangeException(UserCreditExchangeException.CODE_NOT_BIND_ALIPAY_ACCOUNT, "用户未绑定支付宝账户");
|
}
|
|
CreditExchangeRecord exchangeRecord = new CreditExchangeRecord();
|
|
if (exchangeType == CreditExchangeRecord.ExchangeType.FUND_EXCHANGE) {
|
// 计算可兑换金额(如果是红包兑换)
|
BigDecimal exchangeAmount = calculateExchangeAmount(request.getUid(), request.getConsumedCredits(), true);
|
exchangeRecord.setExchangeValue(exchangeAmount);
|
}
|
|
// 记录兑换记录
|
exchangeRecord.setUid(userId);
|
exchangeRecord.setExchangeType(exchangeType);
|
exchangeRecord.setConsumedCredits(request.getConsumedCredits());
|
exchangeRecord.setCreditBalance(balance.getCreditBalance() - request.getConsumedCredits());
|
exchangeRecord.setExchangeStatus(CreditExchangeRecord.STATUS_NOT_VERIFY);
|
exchangeRecord.setExchangeStatusDescription("未审核");
|
exchangeRecord.setExchangeInfo1(alipayBindings.get(0).getAlipayName()); // 设置支付宝账户
|
exchangeRecord.setExchangeInfo2(alipayBindings.get(0).getAlipayAccount());
|
exchangeRecord.setCreateTime(new Date());
|
exchangeRecord.setUpdateTime(new Date());
|
userCreditExchangeRecordService.addExchangeRecord(exchangeRecord);
|
|
// 扣减用户积分
|
userCreditManager.decreaseCredit(UserCreditRecord.builder()
|
.creditAmount(request.getConsumedCredits())
|
.consumptionMethod(UserCreditRecord.ConsumptionMethod.EXCHANGE_RED_PACKET)
|
.direction(UserCreditRecord.DIRECTION_CONSUME)
|
.identifierId(exchangeRecord.getId() + "")
|
.uid(exchangeRecord.getUid())
|
.description("红包兑换")
|
.build());
|
return exchangeRecord.getId();
|
}
|
|
/**
|
* 通过兑换
|
*
|
* @param exchangeRecordId 兑换记录ID
|
*/
|
@Transactional(rollbackFor = Exception.class)
|
public void approveExchange(Long exchangeRecordId) throws UserCreditExchangeException {
|
CreditExchangeRecord exchangeRecord = userCreditExchangeRecordService.getExchangeRecordByIdForUpdate(exchangeRecordId);
|
if (exchangeRecord == null) {
|
throw new UserCreditExchangeException(UserCreditExchangeException.CODE_NOT_BIND_ALIPAY_ACCOUNT, "兑换记录不存在");
|
}
|
|
if (exchangeRecord.getExchangeStatus() != CreditExchangeRecord.STATUS_NOT_VERIFY) {
|
throw new UserCreditExchangeException(UserCreditExchangeException.CODE_COMMON, "兑换已处理");
|
}
|
|
|
// 如果是红包兑换,调用通过兑换逻辑(TODO)
|
if (exchangeRecord.getExchangeType() == CreditExchangeRecord.ExchangeType.FUND_EXCHANGE) {
|
try {
|
AlipayUtil.transfer("credit_exchange_" + exchangeRecordId, exchangeRecord.getExchangeInfo2(), exchangeRecord.getExchangeInfo1(), exchangeRecord.getExchangeValue(), "红包兑换", "红包兑换");
|
} catch (AlipayApiException e) {
|
throw new UserCreditExchangeException(UserCreditExchangeException.CODE_ALIPAY_TRANSFER_FAILED, e.getErrCode() + ":" + e.getErrMsg());
|
} catch (AlipayUtil.AlipayTransferException e) {
|
throw new UserCreditExchangeException(UserCreditExchangeException.CODE_ALIPAY_TRANSFER_FAILED, e.getMessage());
|
}
|
}
|
|
// 改变兑换记录状态
|
userCreditExchangeRecordService.updateExchangeRecord(CreditExchangeRecord.builder()
|
.id(exchangeRecordId)
|
.exchangeStatus(CreditExchangeRecord.STATUS_PASSED)
|
.exchangeStatusDescription("兑换已通过")
|
.updateTime(new Date())
|
.build());
|
|
}
|
|
/**
|
* 驳回兑换
|
*
|
* @param exchangeRecordId 兑换记录ID
|
*/
|
@Transactional(rollbackFor = Exception.class)
|
public void rejectExchange(Long exchangeRecordId) throws UserCreditExchangeException {
|
CreditExchangeRecord exchangeRecord = userCreditExchangeRecordService.getExchangeRecordByIdForUpdate(exchangeRecordId);
|
if (exchangeRecord == null) {
|
throw new UserCreditExchangeException(UserCreditExchangeException.CODE_NOT_BIND_ALIPAY_ACCOUNT, "兑换记录不存在");
|
}
|
|
if (exchangeRecord.getExchangeStatus() != CreditExchangeRecord.STATUS_NOT_VERIFY) {
|
throw new UserCreditExchangeException(UserCreditExchangeException.CODE_COMMON, "兑换已处理");
|
}
|
|
|
// 退回用户积分余额
|
userCreditBalanceService.increaseCreditBalance(exchangeRecord.getUid(), exchangeRecord.getConsumedCredits());
|
// 添加积分记录
|
userCreditRecordService.addCreditRecord(UserCreditRecord.builder()
|
.uid(exchangeRecord.getUid())
|
.creditAmount(exchangeRecord.getConsumedCredits())
|
.direction(UserCreditRecord.DIRECTION_GAIN)
|
.identifierId(exchangeRecord.getId().toString())
|
.acquisitionMethod(UserCreditRecord.AcquisitionMethod.EXCHANGE_RETURN)
|
.description("兑换退回")
|
.createTime(new Date())
|
.updateTime(new Date()).build());
|
userCreditExchangeRecordService.updateExchangeRecord(CreditExchangeRecord.builder()
|
.id(exchangeRecordId)
|
.exchangeStatus(CreditExchangeRecord.STATUS_REJECT)
|
.exchangeStatusDescription("兑换已驳回")
|
.updateTime(new Date())
|
.build());
|
}
|
|
/**
|
* 检查红包兑换频率
|
*
|
* @param userId 用户ID
|
*/
|
private void checkRedPacketExchangeFrequency(Long userId) throws UserCreditExchangeException {
|
//实现红包兑换频率检查逻辑
|
// 获取今日兑换的次数
|
long nowTimeStamp = System.currentTimeMillis();
|
long count = userCreditExchangeRecordService.countExchangeRecords(CreditExchangeRecordMapper.DaoQuery.builder()
|
.uid(userId)
|
.minCreateTime(new Date(TimeUtil.convertToTimeTemp(TimeUtil.getGernalTime(nowTimeStamp, "yyyyMMdd"), "yyyyMMdd")))
|
.maxCreateTime(new Date(nowTimeStamp))
|
.build());
|
CreditSetting setting = creditSettingService.getSettingCacheByType(CreditSetting.CreditSettingType.DAILY_EXCHANGE_LIMIT, new Date(TimeUtil.convertToTimeTemp(TimeUtil.getGernalTime(nowTimeStamp, "yyyyMMddHHmm"), "yyyyMMddHHmm")));
|
if (setting == null) {
|
throw new UserCreditExchangeException(UserCreditExchangeException.CODE_EXCHANGE_FREQUENCY_LIMIT, "兑换频率未设置");
|
}
|
if (count >= Integer.parseInt(setting.getValue())) {
|
throw new UserCreditExchangeException(UserCreditExchangeException.CODE_EXCHANGE_FREQUENCY_LIMIT, String.format("每天只能兑换%s次", setting.getValue()));
|
}
|
}
|
|
/**
|
* 计算兑换金额
|
*
|
* @param uid
|
* @param credit
|
* @return
|
*/
|
public BigDecimal calculateExchangeAmount(Long uid, int credit, boolean forExchange) throws UserCreditExchangeException {
|
long count = userCreditExchangeRecordService.countExchangeRecords(CreditExchangeRecordMapper.DaoQuery.builder()
|
.uid(uid).build());
|
Date nowDate = new Date(TimeUtil.convertToTimeTemp(TimeUtil.getGernalTime(System.currentTimeMillis(), "yyyyMMddHHmm"), "yyyyMMddHHmm"));
|
|
BigDecimal money = null;
|
if (count <= 0) {
|
// 新人兑换
|
List<ExchangeRate> rates = exchangeRateService.listExchangeRates(ExchangeRateMapper.DaoQuery.builder()
|
.exchangeType(ExchangeRate.ExchangeRateType.NEW_USER_EXCHANGE)
|
.maxStartTime(nowDate)
|
.minEndTime(nowDate)
|
.count(Integer.MAX_VALUE)
|
.build());
|
if (rates.isEmpty()) {
|
throw new UserCreditExchangeException(UserCreditExchangeException.CODE_COMMON, "新人兑换汇率未设置");
|
}
|
money = new BigDecimal(credit).multiply(rates.get(0).getRate()).setScale(2, RoundingMode.HALF_UP);
|
} else {
|
// 老用户兑换
|
List<ExchangeRate> rates = exchangeRateService.listExchangeRates(ExchangeRateMapper.DaoQuery.builder()
|
.exchangeType(ExchangeRate.ExchangeRateType.GENERAL_EXCHANGE)
|
.maxStartTime(nowDate)
|
.minEndTime(nowDate)
|
.count(Integer.MAX_VALUE)
|
.build());
|
if (rates.isEmpty()) {
|
throw new UserCreditExchangeException(UserCreditExchangeException.CODE_COMMON, "老用户兑换汇率未设置");
|
}
|
money = new BigDecimal(credit).multiply(rates.get(0).getRate()).setScale(2, RoundingMode.HALF_UP);
|
}
|
if (forExchange) {
|
CreditSetting setting = creditSettingService.getSettingCacheByType(CreditSetting.CreditSettingType.MINIMUM_EXCHANGE_AMOUNT, nowDate);
|
if (setting != null && new BigDecimal(setting.getValue()).compareTo(money) > 0) {
|
throw new UserCreditExchangeException(UserCreditExchangeException.CODE_COMMON, String.format("兑换金额不能低于%s元", setting.getValue()));
|
}
|
}
|
return money;
|
}
|
}
|