Commit 567cbeae681e4978f6ebe9292287aaa497ef123e

Authored by YunaiV
1 parent 3bde43b1

【功能优化】商城:商城订单的支付回调,增加“已支付”情况下的防重处理

yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
... ... @@ -9,7 +9,6 @@ import cn.hutool.core.util.ObjectUtil;
9 9 import cn.hutool.core.util.RandomUtil;
10 10 import cn.hutool.core.util.StrUtil;
11 11 import cn.hutool.extra.spring.SpringUtil;
12   -import cn.iocoder.yudao.framework.common.core.KeyValue;
13 12 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
14 13 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
15 14 import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
... ... @@ -269,12 +268,24 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
269 268 @Transactional(rollbackFor = Exception.class)
270 269 @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_PAY)
271 270 public void updateOrderPaid(Long id, Long payOrderId) {
272   - // 1. 校验并获得交易订单(可支付)
273   - KeyValue<TradeOrderDO, PayOrderRespDTO> orderResult = validateOrderPayable(id, payOrderId);
274   - TradeOrderDO order = orderResult.getKey();
275   - PayOrderRespDTO payOrder = orderResult.getValue();
  271 + // 1.1 校验订单是否存在
  272 + TradeOrderDO order = validateOrderExists(id);
  273 + // 1.2 校验订单已支付
  274 + if (!TradeOrderStatusEnum.isUnpaid(order.getStatus()) || order.getPayStatus()) {
  275 + // 特殊:如果订单已支付,且支付单号相同,直接返回,说明重复回调
  276 + if (ObjectUtil.equals(order.getPayOrderId(), payOrderId)) {
  277 + log.warn("[updateOrderPaid][order({}) 已支付,且支付单号相同({}),直接返回]", order, payOrderId);
  278 + return;
  279 + }
  280 + log.error("[updateOrderPaid][order({}) 支付单不匹配({}),请进行处理!order 数据是:{}]",
  281 + id, payOrderId, JsonUtils.toJsonString(order));
  282 + throw exception(ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR);
  283 + }
  284 +
  285 + // 2. 校验支付订单的合法性
  286 + PayOrderRespDTO payOrder = validatePayOrderPaid(order, payOrderId);
276 287  
277   - // 2. 更新 TradeOrderDO 状态为已支付,等待发货
  288 + // 3. 更新 TradeOrderDO 状态为已支付,等待发货
278 289 int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getStatus(),
279 290 new TradeOrderDO().setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus()).setPayStatus(true)
280 291 .setPayTime(LocalDateTime.now()).setPayChannelCode(payOrder.getChannelCode()));
... ... @@ -282,66 +293,49 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
282 293 throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID);
283 294 }
284 295  
285   - // 3. 执行 TradeOrderHandler 的后置处理
  296 + // 4. 执行 TradeOrderHandler 的后置处理
286 297 List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id);
287 298 tradeOrderHandlers.forEach(handler -> handler.afterPayOrder(order, orderItems));
288 299  
289   - // 4. 记录订单日志
  300 + // 5. 记录订单日志
290 301 TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.UNDELIVERED.getStatus());
291 302 TradeOrderLogUtils.setUserInfo(order.getUserId(), UserTypeEnum.MEMBER.getValue());
292 303 }
293 304  
294 305 /**
295   - * 校验交易订单满足被支付的条件
296   - * <p>
297   - * 1. 交易订单未支付
298   - * 2. 支付单已支付
  306 + * 校验支付订单的合法性
299 307 *
300   - * @param id 交易订单编号
  308 + * @param order 交易订单
301 309 * @param payOrderId 支付订单编号
302   - * @return 交易订单
  310 + * @return 支付订单
303 311 */
304   - private KeyValue<TradeOrderDO, PayOrderRespDTO> validateOrderPayable(Long id, Long payOrderId) {
305   - // 校验订单是否存在
306   - TradeOrderDO order = validateOrderExists(id);
307   - // 校验订单未支付
308   - if (!TradeOrderStatusEnum.isUnpaid(order.getStatus()) || order.getPayStatus()) {
309   - log.error("[validateOrderPaid][order({}) 不处于待支付状态,请进行处理!order 数据是:{}]",
310   - id, JsonUtils.toJsonString(order));
311   - throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID);
312   - }
313   - // 校验支付订单匹配
314   - if (ObjectUtil.notEqual(order.getPayOrderId(), payOrderId)) { // 支付单号
315   - log.error("[validateOrderPaid][order({}) 支付单不匹配({}),请进行处理!order 数据是:{}]",
316   - id, payOrderId, JsonUtils.toJsonString(order));
317   - throw exception(ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR);
318   - }
319   -
320   - // 校验支付单是否存在
  312 + private PayOrderRespDTO validatePayOrderPaid(TradeOrderDO order, Long payOrderId) {
  313 + // 1. 校验支付单是否存在
321 314 PayOrderRespDTO payOrder = payOrderApi.getOrder(payOrderId);
322 315 if (payOrder == null) {
323   - log.error("[validateOrderPaid][order({}) payOrder({}) 不存在,请进行处理!]", id, payOrderId);
  316 + log.error("[validatePayOrderPaid][order({}) payOrder({}) 不存在,请进行处理!]", order.getId(), payOrderId);
324 317 throw exception(ORDER_NOT_FOUND);
325 318 }
326   - // 校验支付单已支付
  319 +
  320 + // 2.1 校验支付单已支付
327 321 if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) {
328   - log.error("[validateOrderPaid][order({}) payOrder({}) 未支付,请进行处理!payOrder 数据是:{}]",
329   - id, payOrderId, JsonUtils.toJsonString(payOrder));
  322 + log.error("[validatePayOrderPaid][order({}) payOrder({}) 未支付,请进行处理!payOrder 数据是:{}]",
  323 + order.getId(), payOrderId, JsonUtils.toJsonString(payOrder));
330 324 throw exception(ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS);
331 325 }
332   - // 校验支付金额一致
  326 + // 2.2 校验支付金额一致
333 327 if (ObjectUtil.notEqual(payOrder.getPrice(), order.getPayPrice())) {
334   - log.error("[validateOrderPaid][order({}) payOrder({}) 支付金额不匹配,请进行处理!order 数据是:{},payOrder 数据是:{}]",
335   - id, payOrderId, JsonUtils.toJsonString(order), JsonUtils.toJsonString(payOrder));
  328 + log.error("[validatePayOrderPaid][order({}) payOrder({}) 支付金额不匹配,请进行处理!order 数据是:{},payOrder 数据是:{}]",
  329 + order.getId(), payOrderId, JsonUtils.toJsonString(order), JsonUtils.toJsonString(payOrder));
336 330 throw exception(ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH);
337 331 }
338   - // 校验支付订单匹配(二次)
339   - if (ObjectUtil.notEqual(payOrder.getMerchantOrderId(), id.toString())) {
340   - log.error("[validateOrderPaid][order({}) 支付单不匹配({}),请进行处理!payOrder 数据是:{}]",
341   - id, payOrderId, JsonUtils.toJsonString(payOrder));
  332 + // 2.2 校验支付订单匹配(二次)
  333 + if (ObjectUtil.notEqual(payOrder.getMerchantOrderId(), order.getId().toString())) {
  334 + log.error("[validatePayOrderPaid][order({}) 支付单不匹配({}),请进行处理!payOrder 数据是:{}]",
  335 + order.getId(), payOrderId, JsonUtils.toJsonString(payOrder));
342 336 throw exception(ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR);
343 337 }
344   - return new KeyValue<>(order, payOrder);
  338 + return payOrder;
345 339 }
346 340  
347 341 @Override
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java
... ... @@ -154,25 +154,25 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService {
154 154 // 1. 校验支付单是否存在
155 155 PayOrderRespDTO payOrder = payOrderApi.getOrder(payOrderId);
156 156 if (payOrder == null) {
157   - log.error("[validatePayOrderPaid][order({}) payOrder({}) 不存在,请进行处理!]", order, payOrderId);
  157 + log.error("[validatePayOrderPaid][order({}) payOrder({}) 不存在,请进行处理!]", order.getId(), payOrderId);
158 158 throw exception(PAY_ORDER_NOT_FOUND);
159 159 }
160 160 // 2.1 校验支付单已支付
161 161 if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) {
162 162 log.error("[validatePayOrderPaid][order({}) payOrder({}) 未支付,请进行处理!payOrder 数据是:{}]",
163   - order, payOrderId, toJsonString(payOrder));
  163 + order.getId(), payOrderId, toJsonString(payOrder));
164 164 throw exception(DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS);
165 165 }
166 166 // 2.1 校验支付金额一致
167 167 if (notEqual(payOrder.getPrice(), order.getPrice())) {
168 168 log.error("[validatePayOrderPaid][order({}) payOrder({}) 支付金额不匹配,请进行处理!order 数据是:{},payOrder 数据是:{}]",
169   - order, payOrderId, toJsonString(order), toJsonString(payOrder));
  169 + order.getId(), payOrderId, toJsonString(order), toJsonString(payOrder));
170 170 throw exception(DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH);
171 171 }
172 172 // 2.2 校验支付订单匹配(二次)
173 173 if (notEqual(payOrder.getMerchantOrderId(), order.getId().toString())) {
174 174 log.error("[validatePayOrderPaid][order({}) 支付单不匹配({}),请进行处理!payOrder 数据是:{}]",
175   - order, payOrderId, toJsonString(payOrder));
  175 + order.getId(), payOrderId, toJsonString(payOrder));
176 176 throw exception(DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR);
177 177 }
178 178 return payOrder;
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java
... ... @@ -292,26 +292,26 @@ public class PayWalletRechargeServiceImpl implements PayWalletRechargeService {
292 292 PayOrderDO payOrder = payOrderService.getOrder(payOrderId);
293 293 if (payOrder == null) {
294 294 log.error("[validatePayOrderPaid][充值订单({}) payOrder({}) 不存在,请进行处理!]",
295   - recharge, payOrderId);
  295 + recharge.getId(), payOrderId);
296 296 throw exception(PAY_ORDER_NOT_FOUND);
297 297 }
298 298  
299 299 // 2.1 校验支付单已支付
300 300 if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) {
301 301 log.error("[validatePayOrderPaid][充值订单({}) payOrder({}) 未支付,请进行处理!payOrder 数据是:{}]",
302   - recharge, payOrderId, toJsonString(payOrder));
  302 + recharge.getId(), payOrderId, toJsonString(payOrder));
303 303 throw exception(WALLET_RECHARGE_UPDATE_PAID_PAY_ORDER_STATUS_NOT_SUCCESS);
304 304 }
305 305 // 2.2 校验支付金额一致
306 306 if (notEqual(payOrder.getPrice(), recharge.getPayPrice())) {
307 307 log.error("[validatePayOrderPaid][充值订单({}) payOrder({}) 支付金额不匹配,请进行处理!钱包 数据是:{},payOrder 数据是:{}]",
308   - recharge, payOrderId, toJsonString(recharge), toJsonString(payOrder));
  308 + recharge.getId(), payOrderId, toJsonString(recharge), toJsonString(payOrder));
309 309 throw exception(WALLET_RECHARGE_UPDATE_PAID_PAY_PRICE_NOT_MATCH);
310 310 }
311 311 // 2.3 校验支付订单的商户订单匹配
312 312 if (notEqual(payOrder.getMerchantOrderId(), recharge.getId().toString())) {
313 313 log.error("[validatePayOrderPaid][充值订单({}) 支付单不匹配({}),请进行处理!payOrder 数据是:{}]",
314   - recharge, payOrderId, toJsonString(payOrder));
  314 + recharge.getId(), payOrderId, toJsonString(payOrder));
315 315 throw exception(WALLET_RECHARGE_UPDATE_PAID_PAY_ORDER_ID_ERROR);
316 316 }
317 317 return payOrder;
... ...