Commit 2b2a1773d62bd3c3e2cd757d769fe1b4911bed22

Authored by YunaiV
1 parent 848d4948

fix(pay): 校验 App 支付订单的用户归属

采用 #1304 的提交入口归属检查,并在查询和提交入口同时核对 userId、userType。
拒绝发生在同步、钱包和支付提交前,保留历史订单空字段兼容。
20 项实际 Spring MVC 边界检查通过。

Refs #1304, #1303
yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.java
... ... @@ -27,10 +27,12 @@ import org.springframework.web.bind.annotation.*;
27 27  
28 28 import java.util.Objects;
29 29  
  30 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
30 31 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
31 32 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
32 33 import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
33 34 import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserType;
  35 +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_ORDER_NOT_FOUND;
34 36  
35 37 @Tag(name = "用户 APP - 支付订单")
36 38 @RestController
... ... @@ -65,8 +67,7 @@ public class AppPayOrderController {
65 67 return success(null);
66 68 }
67 69 // 重要:校验订单是否是当前用户,避免越权
68   - if (order.getUserId() != null // 特殊:早期订单未存储 userId,所以忽略
69   - && ObjUtil.notEqual(order.getUserId(), getLoginUserId())) {
  70 + if (!isLoginUserOrder(order)) {
70 71 return success(null);
71 72 }
72 73  
... ... @@ -82,7 +83,13 @@ public class AppPayOrderController {
82 83 @PostMapping("/submit")
83 84 @Operation(summary = "提交支付订单")
84 85 public CommonResult<AppPayOrderSubmitRespVO> submitPayOrder(@RequestBody AppPayOrderSubmitReqVO reqVO) {
85   - // 1. 钱包支付事,需要额外传 user_id 和 user_type
  86 + // 1. 重要:校验订单是否是当前用户,避免越权
  87 + PayOrderDO order = payOrderService.getOrder(reqVO.getId());
  88 + if (order == null || !isLoginUserOrder(order)) {
  89 + throw exception(PAY_ORDER_NOT_FOUND);
  90 + }
  91 +
  92 + // 2. 钱包支付事,需要额外传 user_id 和 user_type
86 93 if (Objects.equals(reqVO.getChannelCode(), PayChannelEnum.WALLET.getCode())) {
87 94 if (reqVO.getChannelExtras() == null) {
88 95 reqVO.setChannelExtras(Maps.newHashMapWithExpectedSize(1));
... ... @@ -91,9 +98,23 @@ public class AppPayOrderController {
91 98 reqVO.getChannelExtras().put(WalletPayClient.WALLET_ID_KEY, String.valueOf(wallet.getId()));
92 99 }
93 100  
94   - // 2. 提交支付
  101 + // 3. 提交支付
95 102 PayOrderSubmitRespVO respVO = payOrderService.submitOrder(reqVO, getClientIP());
96 103 return success(BeanUtils.toBean(respVO, AppPayOrderSubmitRespVO.class));
97 104 }
98 105  
  106 + /**
  107 + * 判断订单是否属于当前登录用户,需同时匹配用户编号和用户类型
  108 + *
  109 + * 相关 issue:https://github.com/YunaiV/ruoyi-vue-pro/issues/1303
  110 + *
  111 + * @param order 支付订单
  112 + * @return 是否属于
  113 + */
  114 + private boolean isLoginUserOrder(PayOrderDO order) {
  115 + // 特殊:早期订单未存储 userId、userType,所以忽略
  116 + return (order.getUserId() == null || ObjUtil.equal(order.getUserId(), getLoginUserId()))
  117 + && (order.getUserType() == null || ObjUtil.equal(order.getUserType(), getLoginUserType()));
  118 + }
  119 +
99 120 }
... ...