Commit 2c2e9fe87d7d4a2357bd57c27e423faada12bab9

Authored by YunaiV
1 parent 4d9d702c

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

yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderStatusEnum.java
... ... @@ -31,6 +31,16 @@ public enum PayOrderStatusEnum implements IntArrayValuable {
31 31 }
32 32  
33 33 /**
  34 + * 判断是否等待支付
  35 + *
  36 + * @param status 状态
  37 + * @return 是否等待支付
  38 + */
  39 + public static boolean isWaiting(Integer status) {
  40 + return Objects.equals(status, WAITING.getStatus());
  41 + }
  42 +
  43 + /**
34 44 * 判断是否支付成功
35 45 *
36 46 * @param status 状态
... ...
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;
4 4 import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
5 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
6 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  7 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
7 8 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
8 9 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
9 10 import cn.iocoder.yudao.module.pay.controller.admin.order.vo.*;
... ... @@ -11,12 +12,14 @@ import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert;
11 12 import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
12 13 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
13 14 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO;
  15 +import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
14 16 import cn.iocoder.yudao.module.pay.framework.pay.core.WalletPayClient;
15 17 import cn.iocoder.yudao.module.pay.service.app.PayAppService;
16 18 import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
17 19 import com.google.common.collect.Maps;
18 20 import io.swagger.v3.oas.annotations.Operation;
19 21 import io.swagger.v3.oas.annotations.Parameter;
  22 +import io.swagger.v3.oas.annotations.Parameters;
20 23 import io.swagger.v3.oas.annotations.tags.Tag;
21 24 import jakarta.annotation.Resource;
22 25 import jakarta.servlet.http.HttpServletResponse;
... ... @@ -51,10 +54,21 @@ public class PayOrderController {
51 54  
52 55 @GetMapping("/get")
53 56 @Operation(summary = "获得支付订单")
54   - @Parameter(name = "id", description = "编号", required = true, example = "1024")
  57 + @Parameters({
  58 + @Parameter(name = "id", description = "编号", required = true, example = "1024"),
  59 + @Parameter(name = "sync", description = "是否同步", example = "true")
  60 + })
55 61 @PreAuthorize("@ss.hasPermission('pay:order:query')")
56   - public CommonResult<PayOrderRespVO> getOrder(@RequestParam("id") Long id) {
57   - return success(PayOrderConvert.INSTANCE.convert(orderService.getOrder(id)));
  62 + public CommonResult<PayOrderRespVO> getOrder(@RequestParam("id") Long id,
  63 + @RequestParam(value = "sync", required = false) Boolean sync) {
  64 + PayOrderDO order = orderService.getOrder(id);
  65 + // sync 仅在等待支付
  66 + if (Boolean.TRUE.equals(sync) && PayOrderStatusEnum.isWaiting(order.getStatus())) {
  67 + orderService.syncOrderQuietly(order.getId());
  68 + // 重新查询,因为同步后,可能会有变化
  69 + order = orderService.getOrder(id);
  70 + }
  71 + return success(BeanUtils.toBean(order, PayOrderRespVO.class));
58 72 }
59 73  
60 74 @GetMapping("/get-detail")
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.java
1 1 package cn.iocoder.yudao.module.pay.controller.app.order;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
4 5 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
5 6 import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderRespVO;
6 7 import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderSubmitRespVO;
7 8 import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitReqVO;
8 9 import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitRespVO;
9 10 import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert;
  11 +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
  12 +import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
10 13 import cn.iocoder.yudao.module.pay.framework.pay.core.WalletPayClient;
11 14 import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
12 15 import com.google.common.collect.Maps;
13 16 import io.swagger.v3.oas.annotations.Operation;
14 17 import io.swagger.v3.oas.annotations.Parameter;
  18 +import io.swagger.v3.oas.annotations.Parameters;
15 19 import io.swagger.v3.oas.annotations.tags.Tag;
16 20 import lombok.extern.slf4j.Slf4j;
17 21 import org.springframework.validation.annotation.Validated;
... ... @@ -37,12 +41,22 @@ public class AppPayOrderController {
37 41 @Resource
38 42 private PayOrderService payOrderService;
39 43  
40   - // TODO 芋艿:临时 demo,技术打样。
41 44 @GetMapping("/get")
42 45 @Operation(summary = "获得支付订单")
43   - @Parameter(name = "id", description = "编号", required = true, example = "1024")
44   - public CommonResult<PayOrderRespVO> getOrder(@RequestParam("id") Long id) {
45   - return success(PayOrderConvert.INSTANCE.convert(payOrderService.getOrder(id)));
  46 + @Parameters({
  47 + @Parameter(name = "id", description = "编号", required = true, example = "1024"),
  48 + @Parameter(name = "sync", description = "是否同步", example = "true")
  49 + })
  50 + public CommonResult<PayOrderRespVO> getOrder(@RequestParam("id") Long id,
  51 + @RequestParam(value = "sync", required = false) Boolean sync) {
  52 + PayOrderDO order = payOrderService.getOrder(id);
  53 + // sync 仅在等待支付
  54 + if (Boolean.TRUE.equals(sync) && PayOrderStatusEnum.isWaiting(order.getStatus())) {
  55 + payOrderService.syncOrderQuietly(order.getId());
  56 + // 重新查询,因为同步后,可能会有变化
  57 + order = payOrderService.getOrder(id);
  58 + }
  59 + return success(BeanUtils.toBean(order, PayOrderRespVO.class));
46 60 }
47 61  
48 62 @PostMapping("/submit")
... ...
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&lt;PayOrderExtensionDO
24 24 return selectList(PayOrderExtensionDO::getOrderId, orderId);
25 25 }
26 26  
  27 + default List<PayOrderExtensionDO> selectListByOrderIdAndStatus(Long orderId, Integer status) {
  28 + return selectList(PayOrderExtensionDO::getOrderId, orderId,
  29 + PayOrderExtensionDO::getStatus, status);
  30 + }
  31 +
27 32 default List<PayOrderExtensionDO> selectListByStatusAndCreateTimeGe(Integer status, LocalDateTime minCreateTime) {
28 33 return selectList(new LambdaQueryWrapper<PayOrderExtensionDO>()
29 34 .eq(PayOrderExtensionDO::getStatus, status)
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java
... ... @@ -140,6 +140,16 @@ public interface PayOrderService {
140 140 int syncOrder(LocalDateTime minCreateTime);
141 141  
142 142 /**
  143 + * 同步订单的支付状态
  144 + *
  145 + * 1. Quietly 表示,即使同步失败,也不会抛出异常
  146 + * 2. 什么时候回出现异常?因为是主动同步,可能和支付渠道的异步回调存在并发冲突,导致抛出异常
  147 + *
  148 + * @param id 订单编号
  149 + */
  150 + void syncOrderQuietly(Long id);
  151 +
  152 + /**
143 153 * 将已过期的订单,状态修改为已关闭
144 154 *
145 155 * @return 过期的订单数量
... ...
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 {
467 467 return count;
468 468 }
469 469  
  470 + @Override
  471 + public void syncOrderQuietly(Long id) {
  472 + // 1. 查询待支付订单
  473 + List<PayOrderExtensionDO> orderExtensions = orderExtensionMapper.selectListByOrderIdAndStatus(id,
  474 + PayOrderStatusEnum.WAITING.getStatus());
  475 +
  476 + // 2. 遍历执行
  477 + for (PayOrderExtensionDO orderExtension : orderExtensions) {
  478 + syncOrder(orderExtension);
  479 + }
  480 + }
  481 +
470 482 /**
471 483 * 同步单个支付拓展单
472 484 *
... ...