Administrator
2025-05-09 320e9165ac6cc6d90978fbef3074a8ed9add1790
src/main/java/com/taoke/autopay/manager/UserCreditExchangeManager.java
@@ -1,10 +1,12 @@
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;
@@ -36,6 +38,9 @@
    @Resource
    private UserCreditRecordService userCreditRecordService;
    @Resource
    private UserCreditManager userCreditManager;
    /**
     * 用户积分兑换
     *
@@ -46,15 +51,16 @@
    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,"只支持红包兑换");
        if (exchangeType != CreditExchangeRecord.ExchangeType.FUND_EXCHANGE) {
            throw new UserCreditExchangeException(UserCreditExchangeException.CODE_COMMON, "只支持红包兑换");
        }
        // 检查用户积分余额是否足够
        UserCreditBalance balance = userCreditBalanceService.getCreditBalanceByUserId(userId);
        if (balance == null || balance.getCreditBalance() <request.getConsumedCredits()) {
        if (balance == null || balance.getCreditBalance() < request.getConsumedCredits()) {
            throw new UserCreditExchangeException(UserCreditExchangeException.CODE_BALANCE_NOT_ENOUGH, "用户积分不足");
        }
        // 如果是红包兑换,判断用户兑换频率
        if (exchangeType == CreditExchangeRecord.ExchangeType.FUND_EXCHANGE) {
@@ -63,7 +69,7 @@
        // 查询用户绑定的支付宝账户
        List<UserAlipayBinding> alipayBindings = userAlipayBindingService.getBindingsByUid(userId);
        if (alipayBindings == null|| alipayBindings.isEmpty()) {
        if (alipayBindings == null || alipayBindings.isEmpty()) {
            throw new UserCreditExchangeException(UserCreditExchangeException.CODE_NOT_BIND_ALIPAY_ACCOUNT, "用户未绑定支付宝账户");
        }
@@ -71,23 +77,33 @@
        if (exchangeType == CreditExchangeRecord.ExchangeType.FUND_EXCHANGE) {
            // 计算可兑换金额(如果是红包兑换)
            BigDecimal exchangeAmount = calculateExchangeAmount(request.getUid(), request.getConsumedCredits());
            BigDecimal exchangeAmount = calculateExchangeAmount(request.getUid(), request.getConsumedCredits(), true);
            exchangeRecord.setExchangeValue(exchangeAmount);
        }
        // 扣减用户积分
        userCreditBalanceService.decreaseCreditBalance(userId, request.getConsumedCredits());
        // 记录兑换记录
        exchangeRecord.setUid(userId);
        exchangeRecord.setExchangeType(exchangeType);
        exchangeRecord.setConsumedCredits(request.getConsumedCredits());
        exchangeRecord.setCreditBalance(balance.getCreditBalance()-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());
        return userCreditExchangeRecordService.addExchangeRecord(exchangeRecord);
        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();
    }
    /**
@@ -96,24 +112,36 @@
     * @param exchangeRecordId 兑换记录ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void approveExchange(Long exchangeRecordId) throws UserCreditExchangeException{
    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) {
            // TODO: 调用通过兑换逻辑
            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())
                .id(exchangeRecordId)
                .exchangeStatus(CreditExchangeRecord.STATUS_PASSED)
                .exchangeStatusDescription("兑换已通过")
                .updateTime(new Date())
                .build());
    }
    /**
@@ -122,11 +150,16 @@
     * @param exchangeRecordId 兑换记录ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void rejectExchange(Long exchangeRecordId) throws UserCreditExchangeException{
    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());
@@ -138,7 +171,7 @@
                .identifierId(exchangeRecord.getId().toString())
                .acquisitionMethod(UserCreditRecord.AcquisitionMethod.EXCHANGE_RETURN)
                .description("兑换退回")
               .createTime(new Date())
                .createTime(new Date())
                .updateTime(new Date()).build());
        userCreditExchangeRecordService.updateExchangeRecord(CreditExchangeRecord.builder()
                .id(exchangeRecordId)
@@ -153,59 +186,68 @@
     *
     * @param userId 用户ID
     */
    private void checkRedPacketExchangeFrequency(Long userId) throws UserCreditExchangeException{
    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))
        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,"兑换频率未设置");
        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())){
        if (count >= Integer.parseInt(setting.getValue())) {
            throw new UserCreditExchangeException(UserCreditExchangeException.CODE_EXCHANGE_FREQUENCY_LIMIT, String.format("每天只能兑换%s次", setting.getValue()));
        }
    }
    /**
     * 计算兑换金额
     *
     * @param uid
     * @param credit
     * @return
     */
    private BigDecimal calculateExchangeAmount(Long uid, int credit) throws UserCreditExchangeException{
        long count =  userCreditExchangeRecordService.countExchangeRecords(CreditExchangeRecordMapper.DaoQuery.builder()
    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"));
        Date nowDate = new Date(TimeUtil.convertToTimeTemp(TimeUtil.getGernalTime(System.currentTimeMillis(), "yyyyMMddHHmm"), "yyyyMMddHHmm"));
        BigDecimal money =null;
        if(count<=0){
        BigDecimal money = null;
        if (count <= 0) {
            // 新人兑换
            List<ExchangeRate>  rates =  exchangeRateService.listExchangeRates(ExchangeRateMapper.DaoQuery.builder()
                            .exchangeType(ExchangeRate.ExchangeType.NEW_USER_EXCHANGE)
                            .minStartTime(nowDate)
                            .maxEndTime(nowDate)
            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,"新人兑换汇率未设置");
            if (rates.isEmpty()) {
                throw new UserCreditExchangeException(UserCreditExchangeException.CODE_COMMON, "新人兑换汇率未设置");
            }
            money = new BigDecimal(credit).multiply(rates.get(0).getRate()).setScale(2, RoundingMode.HALF_UP);
        }else{
        } else {
            // 老用户兑换
            List<ExchangeRate>  rates =  exchangeRateService.listExchangeRates(ExchangeRateMapper.DaoQuery.builder()
                    .exchangeType(ExchangeRate.ExchangeType.GENERAL_EXCHANGE)
                    .minStartTime(nowDate)
                    .maxEndTime(nowDate)
            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,"老用户兑换汇率未设置");
            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;
    }
}