Эх сурвалжийг харах

【功能优化】支付:查询支付订单时,增加 sync 主动轮询,解决支付宝、微信存在延迟的问题

YunaiV 8 сар өмнө
parent
commit
2c2e9fe87d

+ 10 - 0
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderStatusEnum.java

@@ -30,6 +30,16 @@ public enum PayOrderStatusEnum implements IntArrayValuable {
         return new int[0];
     }
 
+    /**
+     * 判断是否等待支付
+     *
+     * @param status 状态
+     * @return 是否等待支付
+     */
+    public static boolean isWaiting(Integer status) {
+        return Objects.equals(status, WAITING.getStatus());
+    }
+
     /**
      * 判断是否支付成功
      *

+ 17 - 3
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java

@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollectionUtil;
 import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
 import cn.iocoder.yudao.module.pay.controller.admin.order.vo.*;
@@ -11,12 +12,14 @@ import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert;
 import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO;
+import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
 import cn.iocoder.yudao.module.pay.framework.pay.core.WalletPayClient;
 import cn.iocoder.yudao.module.pay.service.app.PayAppService;
 import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
 import com.google.common.collect.Maps;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import jakarta.annotation.Resource;
 import jakarta.servlet.http.HttpServletResponse;
@@ -51,10 +54,21 @@ public class PayOrderController {
 
     @GetMapping("/get")
     @Operation(summary = "获得支付订单")
-    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @Parameters({
+            @Parameter(name = "id", description = "编号", required = true, example = "1024"),
+            @Parameter(name = "sync", description = "是否同步", example = "true")
+    })
     @PreAuthorize("@ss.hasPermission('pay:order:query')")
-    public CommonResult<PayOrderRespVO> getOrder(@RequestParam("id") Long id) {
-        return success(PayOrderConvert.INSTANCE.convert(orderService.getOrder(id)));
+    public CommonResult<PayOrderRespVO> getOrder(@RequestParam("id") Long id,
+                                                 @RequestParam(value = "sync", required = false) Boolean sync) {
+        PayOrderDO order = orderService.getOrder(id);
+        // sync 仅在等待支付
+        if (Boolean.TRUE.equals(sync) && PayOrderStatusEnum.isWaiting(order.getStatus())) {
+            orderService.syncOrderQuietly(order.getId());
+            // 重新查询,因为同步后,可能会有变化
+            order = orderService.getOrder(id);
+        }
+        return success(BeanUtils.toBean(order, PayOrderRespVO.class));
     }
 
     @GetMapping("/get-detail")

+ 18 - 4
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.java

@@ -1,17 +1,21 @@
 package cn.iocoder.yudao.module.pay.controller.app.order;
 
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
 import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderRespVO;
 import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderSubmitRespVO;
 import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitReqVO;
 import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitRespVO;
 import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert;
+import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
+import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
 import cn.iocoder.yudao.module.pay.framework.pay.core.WalletPayClient;
 import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
 import com.google.common.collect.Maps;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.validation.annotation.Validated;
@@ -37,12 +41,22 @@ public class AppPayOrderController {
     @Resource
     private PayOrderService payOrderService;
 
-    // TODO 芋艿:临时 demo,技术打样。
     @GetMapping("/get")
     @Operation(summary = "获得支付订单")
-    @Parameter(name = "id", description = "编号", required = true, example = "1024")
-    public CommonResult<PayOrderRespVO> getOrder(@RequestParam("id") Long id) {
-        return success(PayOrderConvert.INSTANCE.convert(payOrderService.getOrder(id)));
+    @Parameters({
+            @Parameter(name = "id", description = "编号", required = true, example = "1024"),
+            @Parameter(name = "sync", description = "是否同步", example = "true")
+    })
+    public CommonResult<PayOrderRespVO> getOrder(@RequestParam("id") Long id,
+                                                 @RequestParam(value = "sync", required = false) Boolean sync) {
+        PayOrderDO order = payOrderService.getOrder(id);
+        // sync 仅在等待支付
+        if (Boolean.TRUE.equals(sync) && PayOrderStatusEnum.isWaiting(order.getStatus())) {
+            payOrderService.syncOrderQuietly(order.getId());
+            // 重新查询,因为同步后,可能会有变化
+            order = payOrderService.getOrder(id);
+        }
+        return success(BeanUtils.toBean(order, PayOrderRespVO.class));
     }
 
     @PostMapping("/submit")

+ 5 - 0
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderExtensionMapper.java

@@ -24,6 +24,11 @@ public interface PayOrderExtensionMapper extends BaseMapperX<PayOrderExtensionDO
         return selectList(PayOrderExtensionDO::getOrderId, orderId);
     }
 
+    default List<PayOrderExtensionDO> selectListByOrderIdAndStatus(Long orderId, Integer status) {
+        return selectList(PayOrderExtensionDO::getOrderId, orderId,
+                PayOrderExtensionDO::getStatus, status);
+    }
+
     default List<PayOrderExtensionDO> selectListByStatusAndCreateTimeGe(Integer status, LocalDateTime minCreateTime) {
         return selectList(new LambdaQueryWrapper<PayOrderExtensionDO>()
                 .eq(PayOrderExtensionDO::getStatus, status)

+ 10 - 0
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java

@@ -139,6 +139,16 @@ public interface PayOrderService {
      */
     int syncOrder(LocalDateTime minCreateTime);
 
+    /**
+     * 同步订单的支付状态
+     *
+     * 1. Quietly 表示,即使同步失败,也不会抛出异常
+     * 2. 什么时候回出现异常?因为是主动同步,可能和支付渠道的异步回调存在并发冲突,导致抛出异常
+     *
+     * @param id 订单编号
+     */
+    void syncOrderQuietly(Long id);
+
     /**
      * 将已过期的订单,状态修改为已关闭
      *

+ 12 - 0
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java

@@ -467,6 +467,18 @@ public class PayOrderServiceImpl implements PayOrderService {
         return count;
     }
 
+    @Override
+    public void syncOrderQuietly(Long id) {
+        // 1. 查询待支付订单
+        List<PayOrderExtensionDO> orderExtensions = orderExtensionMapper.selectListByOrderIdAndStatus(id,
+                PayOrderStatusEnum.WAITING.getStatus());
+
+        // 2. 遍历执行
+        for (PayOrderExtensionDO orderExtension : orderExtensions) {
+            syncOrder(orderExtension);
+        }
+    }
+
     /**
      * 同步单个支付拓展单
      *