ソースを参照

新增订单超时自动完成逻辑

zhangchen 6 日 前
コミット
8696247142

+ 28 - 0
alien-lawyer/src/main/java/shop/alien/lawyer/controller/LawyerClientConsultationOrderController.java

@@ -174,5 +174,33 @@ public class LawyerClientConsultationOrderController {
     public R<Boolean> refundApplyProcess(@RequestBody LawyerConsultationOrder lawyerConsultationOrder) {
         return lawyerClientConsultationOrderService.refundApplyProcess(lawyerConsultationOrder);
     }
+
+    /**
+     * 订单开始计时(律师端)
+     * <p>
+     * 订单开始计时:
+     * 1. 当订单为按时收费,订单状态为进行中时,订单开始计时
+     * </p>
+     *
+     * @param id        订单ID
+     * @return 操作结果
+     */
+    @ApiOperation("订单开始计时(律师端)")
+    @ApiOperationSupport(order = 5)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "订单ID", dataType = "String", paramType = "query", required = true)
+    })
+    @PutMapping("/orderStartTiming")
+    public R<Boolean> orderStartTiming(@RequestParam(value = "id", required = true) String id) {
+        log.info("订单开始计时,订单ID={}", id);
+
+        // 参数校验
+        if (id == null || id.trim().isEmpty()) {
+            log.warn("订单开始计时失败:订单ID为空");
+            return R.fail("订单ID不能为空");
+        }
+
+        return lawyerClientConsultationOrderService.orderStartTiming(id);
+    }
 }
 

+ 13 - 0
alien-lawyer/src/main/java/shop/alien/lawyer/service/LawyerClientConsultationOrderService.java

@@ -58,6 +58,19 @@ public interface LawyerClientConsultationOrderService extends IService<LawyerCon
      */
     R<Boolean> confirmOrder(String id, String actionType);
 
+
+    /**
+     * 订单开始计时(律师端)
+     * <p>
+     * 订单开始计时:
+     * 1. 当订单为按时收费,订单状态为进行中时,订单开始计时
+     * </p>
+     *
+     * @param id        订单ID
+     * @return R<Boolean> 是否成功
+     */
+    R<Boolean> orderStartTiming(String id);
+
     /**
      * 申请退款
      *

+ 15 - 0
alien-lawyer/src/main/java/shop/alien/lawyer/service/OrderExpirationService.java

@@ -22,6 +22,13 @@ public interface OrderExpirationService {
     void handleRefundOrderKey(String expiredKey);
 
     /**
+     * 處理訂單支付超時
+     *
+     * @param orderNum 訂單no
+     */
+    void handleTimeOutCompleteOrder(String orderNum);
+
+    /**
      * 設置訂單支付超時監聽
      * 
      * @param orderNumber 訂單NO
@@ -46,6 +53,14 @@ public interface OrderExpirationService {
     void setOrderRefundTimeout(String orderNumber, long timeoutSeconds);
 
     /**
+     * 设置订单超时完成监听
+     *
+     * @param orderNumber 订单NO
+     * @param timeoutSeconds 超时时间(秒),默認30分鐘
+     */
+    void setOrderCompleteTimeout(String orderNumber, long timeoutSeconds);
+
+    /**
      * 取消訂單支付超時監聽(當訂單已支付時調用)
      * 
      * @param orderNumber 訂單NO

+ 5 - 0
alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/LawyerClientConsultationOrderServiceImpl.java

@@ -793,6 +793,11 @@ public class LawyerClientConsultationOrderServiceImpl extends ServiceImpl<Lawyer
         }
     }
 
+    @Override
+    public R<Boolean> orderStartTiming(String id) {
+        return null;
+    }
+
     /**
      * 申请退款
      * <p>

+ 85 - 0
alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/OrderExpirationServiceImpl.java

@@ -75,6 +75,11 @@ public class OrderExpirationServiceImpl implements OrderExpirationService, Comma
     private static final String ORDER_REFUND_TIMEOUT_PREFIX = "lawyer:order:refund:timeout:";
 
     /**
+     * Redis key前綴:订单超时完成
+     */
+    private static final String ORDER_COMPLETE_TIMEOUT_PREFIX = "lawyer:order:complete:timeout:";
+
+    /**
      * 默認超時時間:30分鐘
      */
     private static final long DEFAULT_TIMEOUT_SECONDS = 30 * 60;
@@ -100,6 +105,10 @@ public class OrderExpirationServiceImpl implements OrderExpirationService, Comma
         // 註冊訂單退款超時處理器
         expirationHandler.registerHandler(ORDER_REFUND_TIMEOUT_PREFIX, this::handleRefundOrderKey);
         log.info("訂單退款超時處理器註冊完成,前綴: {}", ORDER_REFUND_TIMEOUT_PREFIX);
+
+        // 订单超时完成处理器
+        expirationHandler.registerHandler(ORDER_COMPLETE_TIMEOUT_PREFIX, this::handleTimeOutCompleteOrderKey);
+        log.info("订单已经完成,前綴: {}", ORDER_COMPLETE_TIMEOUT_PREFIX);
     }
 
     @Override
@@ -244,6 +253,25 @@ public class OrderExpirationServiceImpl implements OrderExpirationService, Comma
         }
     }
 
+    /**
+     * 处理订单超时完成key
+     *
+     * @param expiredKey 過期的key,格式:lawyer:order:complete:timeout:{orderId}
+     */
+    private void handleTimeOutCompleteOrderKey(String expiredKey) {
+        try {
+            // 從key中提取訂單ID
+            String orderNo = expiredKey.replace(ORDER_COMPLETE_TIMEOUT_PREFIX, "");
+
+            log.info("订单超时已完成,订单no: {}", orderNo);
+
+            // 處理訂單支付超時
+            handleTimeOutCompleteOrder(orderNo);
+        } catch (Exception e) {
+            log.error("處理過期訂單key失敗,key: {}", expiredKey, e);
+        }
+    }
+
     private void refundParam(Map<String,String> paramMap,LawyerConsultationOrder order,String refundReason){
         //支付宝
         if ("1".equals(order.getPayType())) {
@@ -303,6 +331,46 @@ public class OrderExpirationServiceImpl implements OrderExpirationService, Comma
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void handleTimeOutCompleteOrder(String orderNum) {
+        log.info("开始处理订单完成,订单no: {}", orderNum);
+
+        try {
+            // 查詢訂單
+            LambdaQueryWrapper<LawyerConsultationOrder> queryWrapper = new LambdaQueryWrapper<>();
+            queryWrapper.eq(LawyerConsultationOrder::getOrderNumber, orderNum).last("LIMIT 1");
+            LawyerConsultationOrder order = orderMapper.selectOne(queryWrapper);
+            if (order == null) {
+                log.warn("订单不存在,订单no: {}", orderNum);
+                return;
+            }
+
+            // 只处理进行中的订单
+            if (order.getOrderStatus() != null && order.getOrderStatus() == 0) {
+                log.info("订单为进行中状态,开始完成订单,订单no: {}", orderNum);
+
+                LawyerConsultationOrder lawyerConsultationOrder = new LawyerConsultationOrder();
+                // 更新订单状态为已完成
+                lawyerConsultationOrder.setOrderStatus(3); // 3:已完成
+                lawyerConsultationOrder.setId(order.getId());
+                lawyerConsultationOrder.setUpdatedTime(new java.util.Date());
+
+                int updated = orderMapper.updateById(lawyerConsultationOrder);
+                if (updated > 0) {
+                    log.info("订单已经超时,已经自动完成,订单no: {}", orderNum);
+                } else {
+                    log.error("订单自动完成失败,订单no: {}", orderNum);
+                }
+            } else {
+                log.info("订单不是进行中,无需处理,订单no: {}, 当前状态: {}", orderNum, order.getOrderStatus());
+            }
+        } catch (Exception e) {
+            log.error("处理订单状态完成异常,订单no: {}", orderNum, e);
+            throw e;
+        }
+    }
+
+    @Override
     public void setOrderPaymentTimeout(String orderNumber, long timeoutSeconds) {
         if (orderNumber == null) {
             log.warn("訂單ID為null,無法設置支付超時監聽");
@@ -353,6 +421,23 @@ public class OrderExpirationServiceImpl implements OrderExpirationService, Comma
         log.info("設置訂單退款超時監聽,訂單NO: {}, 超時時間: {}秒, key: {}", orderNumber, timeout, key);
     }
 
+    @Override
+    public void setOrderCompleteTimeout(String orderNumber, long timeoutSeconds) {
+        if (orderNumber == null) {
+            log.warn("订单NO为null,无法设置订单超时完成监听");
+            return;
+        }
+
+        String key = ORDER_COMPLETE_TIMEOUT_PREFIX + orderNumber;
+        long timeout = timeoutSeconds > 0 ? timeoutSeconds : 60 * Long.parseLong(coefficients);
+
+        // 设置Redis key,带过期时间
+        // 当key过期时,会触发RedisKeyExpirationListener
+        redisService.setString(key, String.valueOf(orderNumber), timeout);
+
+        log.info("设置订单超时完成监听,订单: {}, 超时时间: {}秒, key: {}", orderNumber, timeout, key);
+    }
+
     /**
      * 取消訂單支付超時監聽(當訂單已支付時調用)
      *