|
@@ -14,6 +14,7 @@ import com.kym.common.exception.BusinessException;
|
|
|
import com.kym.common.utils.CommUtil;
|
|
import com.kym.common.utils.CommUtil;
|
|
|
import com.kym.common.utils.LambadaTools;
|
|
import com.kym.common.utils.LambadaTools;
|
|
|
import com.kym.common.utils.OrderUtils;
|
|
import com.kym.common.utils.OrderUtils;
|
|
|
|
|
+import com.kym.entity.common.RedisKeys;
|
|
|
import com.kym.entity.miniapp.Account;
|
|
import com.kym.entity.miniapp.Account;
|
|
|
import com.kym.entity.miniapp.*;
|
|
import com.kym.entity.miniapp.*;
|
|
|
import com.kym.service.admin.ActivityService;
|
|
import com.kym.service.admin.ActivityService;
|
|
@@ -46,6 +47,7 @@ import lombok.SneakyThrows;
|
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.core.io.ClassPathResource;
|
|
import org.springframework.core.io.ClassPathResource;
|
|
|
|
|
+import org.springframework.data.redis.core.StringRedisTemplate;
|
|
|
import org.springframework.http.HttpStatus;
|
|
import org.springframework.http.HttpStatus;
|
|
|
import org.springframework.http.ResponseEntity;
|
|
import org.springframework.http.ResponseEntity;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
@@ -62,6 +64,7 @@ import java.time.LocalDateTime;
|
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
|
|
|
|
|
|
|
|
@@ -101,11 +104,14 @@ public class WxPayServiceImpl implements WxPayService {
|
|
|
|
|
|
|
|
private final UserRechargeRightsService userRechargeRightsService;
|
|
private final UserRechargeRightsService userRechargeRightsService;
|
|
|
|
|
|
|
|
|
|
+ private final StringRedisTemplate stringRedisTemplate;
|
|
|
|
|
+
|
|
|
|
|
|
|
|
public WxPayServiceImpl(WxPayConfig conf, WalletDetailService walletDetailService,
|
|
public WxPayServiceImpl(WxPayConfig conf, WalletDetailService walletDetailService,
|
|
|
PayLogService payLogService, AccountService accountService, ChargeOrderService chargeOrderService,
|
|
PayLogService payLogService, AccountService accountService, ChargeOrderService chargeOrderService,
|
|
|
RefundLogService refundLogService,
|
|
RefundLogService refundLogService,
|
|
|
- PlatformApiService platformApiService, ActivityService activityService, UserRechargeRightsService userRechargeRightsService) {
|
|
|
|
|
|
|
+ PlatformApiService platformApiService, ActivityService activityService, UserRechargeRightsService userRechargeRightsService,
|
|
|
|
|
+ StringRedisTemplate stringRedisTemplate) {
|
|
|
this.conf = conf;
|
|
this.conf = conf;
|
|
|
this.walletDetailService = walletDetailService;
|
|
this.walletDetailService = walletDetailService;
|
|
|
this.payLogService = payLogService;
|
|
this.payLogService = payLogService;
|
|
@@ -115,6 +121,7 @@ public class WxPayServiceImpl implements WxPayService {
|
|
|
this.platformApiService = platformApiService;
|
|
this.platformApiService = platformApiService;
|
|
|
this.activityService = activityService;
|
|
this.activityService = activityService;
|
|
|
this.userRechargeRightsService = userRechargeRightsService;
|
|
this.userRechargeRightsService = userRechargeRightsService;
|
|
|
|
|
+ this.stringRedisTemplate = stringRedisTemplate;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -367,19 +374,36 @@ public class WxPayServiceImpl implements WxPayService {
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
public void applyWxRefund(String reason) {
|
|
public void applyWxRefund(String reason) {
|
|
|
var userId = StpUtil.getLoginIdAsLong();
|
|
var userId = StpUtil.getLoginIdAsLong();
|
|
|
- var chargeOrder = chargeOrderService.getChargingOrderByUserId(userId);
|
|
|
|
|
- if (chargeOrder != null) {
|
|
|
|
|
- throw new BusinessException("存在未完结的订单,请等待所有订单完结之后重试");
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- var account = accountService.getAccountByUserId(userId);
|
|
|
|
|
- if (account.getBalance() <= 0) {
|
|
|
|
|
- throw new BusinessException("账户余额不足,无需退款");
|
|
|
|
|
- }
|
|
|
|
|
- // 校验余额大于优惠金额
|
|
|
|
|
- if (account.getBalance() <= account.getDiscountAmount()) {
|
|
|
|
|
- throw new BusinessException("不可退金额高于钱包余额,不支持退款");
|
|
|
|
|
|
|
+ // 防重复提交:Redis分布式锁,同一用户10秒内只能提交一次退款申请
|
|
|
|
|
+ String lockKey = RedisKeys.REFUND_LOCK + userId;
|
|
|
|
|
+ Boolean locked = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS);
|
|
|
|
|
+ if (Boolean.FALSE.equals(locked)) {
|
|
|
|
|
+ throw new BusinessException("退款申请正在处理中,请勿重复提交");
|
|
|
}
|
|
}
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 防重复提交:检查是否已有处理中的退款申请
|
|
|
|
|
+ var existingRefund = refundLogService.lambdaQuery()
|
|
|
|
|
+ .eq(RefundLog::getUserId, userId)
|
|
|
|
|
+ .in(RefundLog::getStatus, RefundLog.STATUS_退款已申请, RefundLog.STATUS_退款处理中)
|
|
|
|
|
+ .one();
|
|
|
|
|
+ if (existingRefund != null) {
|
|
|
|
|
+ throw new BusinessException("您已有退款申请正在处理中,请勿重复提交");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ var chargeOrder = chargeOrderService.getChargingOrderByUserId(userId);
|
|
|
|
|
+ if (chargeOrder != null) {
|
|
|
|
|
+ throw new BusinessException("存在未完结的订单,请等待所有订单完结之后重试");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ var account = accountService.getAccountByUserId(userId);
|
|
|
|
|
+ if (account.getBalance() <= 0) {
|
|
|
|
|
+ throw new BusinessException("账户余额不足,无需退款");
|
|
|
|
|
+ }
|
|
|
|
|
+ // 校验余额大于优惠金额
|
|
|
|
|
+ if (account.getBalance() <= account.getDiscountAmount()) {
|
|
|
|
|
+ throw new BusinessException("不可退金额高于钱包余额,不支持退款");
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// 将余额转移至冻结余额
|
|
// 将余额转移至冻结余额
|
|
|
accountService.lambdaUpdate().setSql(" frozen_amount = (frozen_amount + balance) ,balance = 0").eq(Account::getUserId, userId).update();
|
|
accountService.lambdaUpdate().setSql(" frozen_amount = (frozen_amount + balance) ,balance = 0").eq(Account::getUserId, userId).update();
|
|
@@ -467,6 +491,9 @@ public class WxPayServiceImpl implements WxPayService {
|
|
|
LOGGER.error("退款异常:userId:{},退款金额:{},payLogs:{}", userId, originalRefundAmount, payLogs);
|
|
LOGGER.error("退款异常:userId:{},退款金额:{},payLogs:{}", userId, originalRefundAmount, payLogs);
|
|
|
throw new BusinessException("退款异常");
|
|
throw new BusinessException("退款异常");
|
|
|
}
|
|
}
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ stringRedisTemplate.delete(lockKey);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|