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

This commit is contained in:
YunaiV 2024-09-24 09:04:18 +08:00
parent 4d9d702c21
commit 2c2e9fe87d
6 changed files with 72 additions and 7 deletions

View File

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

View File

@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; 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.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
import cn.iocoder.yudao.module.pay.controller.admin.order.vo.*; 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.app.PayAppDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; 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.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.framework.pay.core.WalletPayClient;
import cn.iocoder.yudao.module.pay.service.app.PayAppService; import cn.iocoder.yudao.module.pay.service.app.PayAppService;
import cn.iocoder.yudao.module.pay.service.order.PayOrderService; import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
@ -51,10 +54,21 @@ public class PayOrderController {
@GetMapping("/get") @GetMapping("/get")
@Operation(summary = "获得支付订单") @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')") @PreAuthorize("@ss.hasPermission('pay:order:query')")
public CommonResult<PayOrderRespVO> getOrder(@RequestParam("id") Long id) { public CommonResult<PayOrderRespVO> getOrder(@RequestParam("id") Long id,
return success(PayOrderConvert.INSTANCE.convert(orderService.getOrder(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") @GetMapping("/get-detail")

View File

@ -1,17 +1,21 @@
package cn.iocoder.yudao.module.pay.controller.app.order; package cn.iocoder.yudao.module.pay.controller.app.order;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; 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.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.PayOrderRespVO;
import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderSubmitRespVO; 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.AppPayOrderSubmitReqVO;
import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitRespVO; 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.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.framework.pay.core.WalletPayClient;
import cn.iocoder.yudao.module.pay.service.order.PayOrderService; import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -37,12 +41,22 @@ public class AppPayOrderController {
@Resource @Resource
private PayOrderService payOrderService; private PayOrderService payOrderService;
// TODO 芋艿临时 demo技术打样
@GetMapping("/get") @GetMapping("/get")
@Operation(summary = "获得支付订单") @Operation(summary = "获得支付订单")
@Parameter(name = "id", description = "编号", required = true, example = "1024") @Parameters({
public CommonResult<PayOrderRespVO> getOrder(@RequestParam("id") Long id) { @Parameter(name = "id", description = "编号", required = true, example = "1024"),
return success(PayOrderConvert.INSTANCE.convert(payOrderService.getOrder(id))); @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") @PostMapping("/submit")

View File

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

View File

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

View File

@ -467,6 +467,18 @@ public class PayOrderServiceImpl implements PayOrderService {
return count; 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);
}
}
/** /**
* 同步单个支付拓展单 * 同步单个支付拓展单
* *