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,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 * @param status 状态 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,6 +4,7 @@ import cn.hutool.core.collection.CollectionUtil;
4 import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; 4 import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
5 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  7 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
7 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; 8 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
8 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; 9 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
9 import cn.iocoder.yudao.module.pay.controller.admin.order.vo.*; 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 +12,14 @@ import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert;
11 import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; 12 import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
12 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; 13 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
13 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; 14 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO;
  15 +import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
14 import cn.iocoder.yudao.module.pay.framework.pay.core.WalletPayClient; 16 import cn.iocoder.yudao.module.pay.framework.pay.core.WalletPayClient;
15 import cn.iocoder.yudao.module.pay.service.app.PayAppService; 17 import cn.iocoder.yudao.module.pay.service.app.PayAppService;
16 import cn.iocoder.yudao.module.pay.service.order.PayOrderService; 18 import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
17 import com.google.common.collect.Maps; 19 import com.google.common.collect.Maps;
18 import io.swagger.v3.oas.annotations.Operation; 20 import io.swagger.v3.oas.annotations.Operation;
19 import io.swagger.v3.oas.annotations.Parameter; 21 import io.swagger.v3.oas.annotations.Parameter;
  22 +import io.swagger.v3.oas.annotations.Parameters;
20 import io.swagger.v3.oas.annotations.tags.Tag; 23 import io.swagger.v3.oas.annotations.tags.Tag;
21 import jakarta.annotation.Resource; 24 import jakarta.annotation.Resource;
22 import jakarta.servlet.http.HttpServletResponse; 25 import jakarta.servlet.http.HttpServletResponse;
@@ -51,10 +54,21 @@ public class PayOrderController { @@ -51,10 +54,21 @@ public class PayOrderController {
51 54
52 @GetMapping("/get") 55 @GetMapping("/get")
53 @Operation(summary = "获得支付订单") 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 @PreAuthorize("@ss.hasPermission('pay:order:query')") 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 @GetMapping("/get-detail") 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 package cn.iocoder.yudao.module.pay.controller.app.order; 1 package cn.iocoder.yudao.module.pay.controller.app.order;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
4 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; 5 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
5 import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderRespVO; 6 import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderRespVO;
6 import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderSubmitRespVO; 7 import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderSubmitRespVO;
7 import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitReqVO; 8 import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitReqVO;
8 import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitRespVO; 9 import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitRespVO;
9 import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert; 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 import cn.iocoder.yudao.module.pay.framework.pay.core.WalletPayClient; 13 import cn.iocoder.yudao.module.pay.framework.pay.core.WalletPayClient;
11 import cn.iocoder.yudao.module.pay.service.order.PayOrderService; 14 import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
12 import com.google.common.collect.Maps; 15 import com.google.common.collect.Maps;
13 import io.swagger.v3.oas.annotations.Operation; 16 import io.swagger.v3.oas.annotations.Operation;
14 import io.swagger.v3.oas.annotations.Parameter; 17 import io.swagger.v3.oas.annotations.Parameter;
  18 +import io.swagger.v3.oas.annotations.Parameters;
15 import io.swagger.v3.oas.annotations.tags.Tag; 19 import io.swagger.v3.oas.annotations.tags.Tag;
16 import lombok.extern.slf4j.Slf4j; 20 import lombok.extern.slf4j.Slf4j;
17 import org.springframework.validation.annotation.Validated; 21 import org.springframework.validation.annotation.Validated;
@@ -37,12 +41,22 @@ public class AppPayOrderController { @@ -37,12 +41,22 @@ public class AppPayOrderController {
37 @Resource 41 @Resource
38 private PayOrderService payOrderService; 42 private PayOrderService payOrderService;
39 43
40 - // TODO 芋艿:临时 demo,技术打样。  
41 @GetMapping("/get") 44 @GetMapping("/get")
42 @Operation(summary = "获得支付订单") 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 @PostMapping("/submit") 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,6 +24,11 @@ public interface PayOrderExtensionMapper extends BaseMapperX&lt;PayOrderExtensionDO
24 return selectList(PayOrderExtensionDO::getOrderId, orderId); 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 default List<PayOrderExtensionDO> selectListByStatusAndCreateTimeGe(Integer status, LocalDateTime minCreateTime) { 32 default List<PayOrderExtensionDO> selectListByStatusAndCreateTimeGe(Integer status, LocalDateTime minCreateTime) {
28 return selectList(new LambdaQueryWrapper<PayOrderExtensionDO>() 33 return selectList(new LambdaQueryWrapper<PayOrderExtensionDO>()
29 .eq(PayOrderExtensionDO::getStatus, status) 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,6 +140,16 @@ public interface PayOrderService {
140 int syncOrder(LocalDateTime minCreateTime); 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 * @return 过期的订单数量 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,6 +467,18 @@ public class PayOrderServiceImpl implements PayOrderService {
467 return count; 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 *