15044148858 2 weeks ago
parent
commit
508fdfac3b
1 changed files with 65 additions and 21 deletions
  1. 65 21
      qmjszx-pay/src/main/java/beilv/wx/pay/service/IWxPayService.java

+ 65 - 21
qmjszx-pay/src/main/java/beilv/wx/pay/service/IWxPayService.java

@@ -253,24 +253,46 @@ public class IWxPayService {
      */
     private void processOrderPayment(String orderId) {
         log.info("开始处理订单支付完成逻辑,订单号: {}", orderId);
-        StoreOrder order = storeOrderMapper.selectStoreOrderByOrderId(orderId);
-        if (order != null) {
-            // 检查订单是否已经处理过
-            if (order.getPaid() == null || order.getPaid() != 1) {
-                log.info("更新订单状态为已支付,订单号: {}", orderId);
-                // 更新订单状态
-                order.setPaid(1); // 设置为已支付
-                order.setStatus(1); // 设置订单状态为已支付
-                order.setPayTime(new Date()); // 设置支付时间
-                storeOrderMapper.updateStoreOrder(order);
-                // 从延迟队列中移除订单
-                removeOrderFromDelayQueue(orderId);
-                log.info("订单状态更新完成,订单号: {}", orderId);
+        
+        // 使用Redis分布式锁防止并发处理
+        String lockKey = "payment:lock:" + orderId;
+        Boolean lockAcquired = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", java.time.Duration.ofSeconds(30));
+        
+        if (Boolean.FALSE.equals(lockAcquired)) {
+            log.warn("订单正在被其他线程处理,订单号: {}", orderId);
+            return;
+        }
+        
+        try {
+            StoreOrder order = storeOrderMapper.selectStoreOrderByOrderId(orderId);
+            if (order != null) {
+                // 检查订单是否已被取消
+                if (order.getStatus() != null && order.getStatus() == 3) {
+                    log.warn("订单已超时取消,支付回调到达,订单号: {}", orderId);
+                    // TODO: 这里应该调用退款接口,将钱退回给用户
+                    return;
+                }
+                
+                // 检查订单是否已经处理过
+                if (order.getPaid() == null || order.getPaid() != 1) {
+                    log.info("更新订单状态为已支付,订单号: {}", orderId);
+                    // 更新订单状态
+                    order.setPaid(1); // 设置为已支付
+                    order.setStatus(1); // 设置订单状态为已支付
+                    order.setPayTime(new Date()); // 设置支付时间
+                    storeOrderMapper.updateStoreOrder(order);
+                    // 从延迟队列中移除订单
+                    removeOrderFromDelayQueue(orderId);
+                    log.info("订单状态更新完成,订单号: {}", orderId);
+                } else {
+                    log.info("订单已处理过,无需重复处理,订单号: {}", orderId);
+                }
             } else {
-                log.info("订单已处理过,无需重复处理,订单号: {}", orderId);
+                log.warn("订单不存在,订单号: {}", orderId);
             }
-        } else {
-            log.warn("订单不存在,订单号: {}", orderId);
+        } finally {
+            // 释放锁
+            redisTemplate.delete(lockKey);
         }
     }
 
@@ -313,7 +335,7 @@ public class IWxPayService {
         request.setReason(param.getReason());
         WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount();
         //原订单实际支付金额(单位:分)
-        amount.setTotal(yuanToFen(param.getRefundAmount()));
+        amount.setTotal(yuanToFen(param.getTotalPrice()));
         //退款金额(单位:分)
         amount.setRefund(yuanToFen(param.getRefundAmount()));
         //货币类型,默认 "CNY"
@@ -321,15 +343,25 @@ public class IWxPayService {
         request.setAmount(amount);
         request.setNotifyUrl(wxPayProperties.getRefundNotifyUrl());
         param.setSysMember(getSysMember(param.getUserId()));
+        
         // 检查是否已存在退款记录
         StoreRefund existingRefund = storeRefundMapper.selectStoreRefundByOrderId(param.getOrderId());
-        if (existingRefund == null) {
-            log.info("创建退款记录,订单号: {}", param.getOrderId());
-            refundOrder(param);
+        if (existingRefund != null && "2".equals(existingRefund.getRefundStatus())) {
+            log.warn("退款失败,退款记录已存在且已完成,订单号: {}", param.getOrderId());
+            throw new WxPayException("该订单已退款");
         }
+        
+        // 先调用微信退款接口
         log.info("调用微信退款接口,订单号: {}", param.getOrderId());
         WxPayRefundV3Result result = this.wxService.refundV3(request);
-        log.info("微信退款接口调用完成,订单号: {}", param.getOrderId());
+        log.info("微信退款接口调用成功,订单号: {}", param.getOrderId());
+        
+        // 微信退款成功后,再创建本地退款记录
+        if (existingRefund == null) {
+            log.info("微信退款成功,创建本地退款记录,订单号: {}", param.getOrderId());
+            refundOrder(param);
+        }
+        
         return result;
     }
 
@@ -458,6 +490,15 @@ public class IWxPayService {
         // 从Redis有序集合中获取所有已超时的订单(score小于当前时间的元素)
         redisTemplate.opsForZSet().rangeByScore(ORDER_DELAY_QUEUE_PREFIX + "orders", 0, currentTime)
                 .forEach(orderId -> {
+                    // 使用分布式锁防止与支付回调冲突
+                    String lockKey = "payment:lock:" + orderId;
+                    Boolean lockAcquired = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", java.time.Duration.ofSeconds(30));
+                    
+                    if (Boolean.FALSE.equals(lockAcquired)) {
+                        log.warn("订单正在被处理,跳过超时处理,订单号: {}", orderId);
+                        return;
+                    }
+                    
                     try {
                         log.info("处理超时订单: {}", orderId);
                         // 查询订单信息
@@ -480,6 +521,9 @@ public class IWxPayService {
                         log.info("超时订单 {} 处理完成", orderId);
                     } catch (Exception e) {
                         log.error("处理超时订单 {} 时发生错误", orderId, e);
+                    } finally {
+                        // 释放锁
+                        redisTemplate.delete(lockKey);
                     }
                 });
 //        log.info("超时订单处理完成");