Commit 2b2a1773d62bd3c3e2cd757d769fe1b4911bed22
1 parent
848d4948
fix(pay): 校验 App 支付订单的用户归属
采用 #1304 的提交入口归属检查,并在查询和提交入口同时核对 userId、userType。 拒绝发生在同步、钱包和支付提交前,保留历史订单空字段兼容。 20 项实际 Spring MVC 边界检查通过。 Refs #1304, #1303
Showing
1 changed file
with
25 additions
and
4 deletions
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 | } | ... | ... |