admin
2025-08-08 035edfa382d349ba66240fbfef68c14c7cfc95d1
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;
@@ -12,6 +14,7 @@
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
@@ -49,16 +52,15 @@
    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, "用户积分不足");
        }
        // 如果是红包兑换,判断用户兑换频率
@@ -68,7 +70,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, "用户未绑定支付宝账户");
        }
@@ -76,7 +78,7 @@
        if (exchangeType == CreditExchangeRecord.ExchangeType.FUND_EXCHANGE) {
            // 计算可兑换金额(如果是红包兑换)
            BigDecimal exchangeAmount = calculateExchangeAmount(request.getUid(), request.getConsumedCredits());
            BigDecimal exchangeAmount = calculateExchangeAmount(request.getUid(), request.getConsumedCredits(), true);
            exchangeRecord.setExchangeValue(exchangeAmount);
        }
@@ -84,7 +86,7 @@
        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()); // 设置支付宝账户
@@ -98,7 +100,7 @@
                .creditAmount(request.getConsumedCredits())
                .consumptionMethod(UserCreditRecord.ConsumptionMethod.EXCHANGE_RED_PACKET)
                .direction(UserCreditRecord.DIRECTION_CONSUME)
                .identifierId(exchangeRecord.getId()+"")
                .identifierId(exchangeRecord.getId() + "")
                .uid(exchangeRecord.getUid())
                .description("红包兑换")
                .build());
@@ -111,28 +113,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){
        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());
    }
    /**
@@ -141,13 +151,13 @@
     * @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){
        if (exchangeRecord.getExchangeStatus() != CreditExchangeRecord.STATUS_NOT_VERIFY) {
            throw new UserCreditExchangeException(UserCreditExchangeException.CODE_COMMON, "兑换已处理");
        }
@@ -162,7 +172,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)
@@ -177,65 +187,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
     */
    public BigDecimal calculateExchangeAmount(Long uid, int credit) throws UserCreditExchangeException{
        long count =  userCreditExchangeRecordService.countExchangeRecords(CreditExchangeRecordMapper.DaoQuery.builder()
                .uid(uid).build());
        Date nowDate =  new Date(TimeUtil.convertToTimeTemp(TimeUtil.getGernalTime(System.currentTimeMillis(),"yyyyMMddHHmm"),"yyyyMMddHHmm"));
    public BigDecimal calculateExchangeAmount(Long uid, int credit, boolean forExchange) throws UserCreditExchangeException {
        long count = userCreditExchangeRecordService.countExchangeRecords(CreditExchangeRecordMapper.DaoQuery.builder()
                        .exchangeStatusList(Arrays.asList(new Integer[]{CreditExchangeRecord.STATUS_PASSED, CreditExchangeRecord.STATUS_NOT_VERIFY}))
                        .uid(uid).build());
        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.ExchangeRateType.NEW_USER_EXCHANGE)
                            .maxStartTime(nowDate)
                            .minEndTime(nowDate)
                            .count(Integer.MAX_VALUE)
            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()
            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);
        }
        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()));
        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;
    }