From 534b7e1f7374e4cf868860d0c6243a9ad4cab7bc Mon Sep 17 00:00:00 2001 From: wuKong Date: Mon, 10 Nov 2025 11:36:47 +0800 Subject: [PATCH] =?UTF-8?q?feat(pay,mall-trade):=20=E5=B0=8F=E7=A8=8B?= =?UTF-8?q?=E5=BA=8F=E5=95=86=E5=93=81=E8=AE=A2=E5=8D=95=E8=AF=A6=E6=83=85?= =?UTF-8?q?path=E9=85=8D=E7=BD=AE=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 PayOrderApi 中新增 getMerchantOrderIdByPayOrderNo 方法 - 在 PayOrderApiImpl 中实现该方法,调用 service 层逻辑 - 在 PayOrderMapper 中增加 selectByNo 查询方法 - 在 PayOrderService 中定义 getMerchantOrderIdByNo 接口 - 在 PayOrderServiceImpl 中实现 getMerchantOrderIdByNo 业务逻辑 - 支持通过支付订单编号查询对应的商户订单编号feat(trade): 新增通过支付订单编号查询交易订单详情功能 - 在 AppTradeOrderController 中新增 getOrderDetailByOutTradeNo 接口 - 支持微信小程序订单中心跳转到订单详情页面 - 在 TradeOrderQueryService 中定义 getOrderByOutTradeNo 方法 - 在 TradeOrderQueryServiceImpl 中实现该方法 - 通过 PayOrderApi 调用获取商户订单编号 - 根据商户订单编号查询对应的交易订单信息 --- .../app/order/AppTradeOrderController.java | 36 ++++++++++++++++++- .../service/order/TradeOrderQueryService.java | 10 +++++- .../order/TradeOrderQueryServiceImpl.java | 18 ++++++++++ .../module/pay/api/order/PayOrderApi.java | 4 +++ .../module/pay/api/order/PayOrderApiImpl.java | 4 +++ .../pay/dal/mysql/order/PayOrderMapper.java | 4 +++ .../pay/service/order/PayOrderService.java | 8 ++++- .../service/order/PayOrderServiceImpl.java | 11 ++++++ 8 files changed, 92 insertions(+), 3 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-server/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java b/yudao-module-mall/yudao-module-trade-server/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java index b2b887050..6f72e6507 100644 --- a/yudao-module-mall/yudao-module-trade-server/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java +++ b/yudao-module-mall/yudao-module-trade-server/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java @@ -105,7 +105,7 @@ public class AppTradeOrderController { && TradeOrderStatusEnum.isUnpaid(order.getStatus()) && !order.getPayStatus()) { tradeOrderUpdateService.syncOrderPayStatusQuietly(order.getId(), order.getPayOrderId()); // 重新查询,因为同步后,可能会有变化 - order = tradeOrderQueryService.getOrder(id); + order = tradeOrderQueryService.getOrder(order.getId()); } // 2.1 查询订单项 @@ -117,6 +117,40 @@ public class AppTradeOrderController { return success(TradeOrderConvert.INSTANCE.convert02(order, orderItems, tradeOrderProperties, express)); } + @GetMapping("/get-detailByOutTradeNo") + @Operation(summary = "获得交易订单") + @Parameters({ + @Parameter(name = "id", description = "PATH需包含「${商品订单号} 」,微信将把你在支付预下单接口填入的 out_trade_no 替换此内容"), + @Parameter(name = "sync", description = "是否同步支付状态", example = "true") + }) + public CommonResult getOrderDetailByOutTradeNo(@RequestParam("id") String id, + @RequestParam(value = "sync", required = false) Boolean sync) { + // PATH需包含「${商品订单号} 」,微信将把你在支付预下单接口填入的 out_trade_no 替换此内容,如「index/orderDetail?id=${商品订单号}&channel=1」。PATH最多输入1条。 + // https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order_center/order_center.html + // 小程序商品订单详情path配置为:pages/order/detail?id=${商品订单号}&comein_type=wechat + // 通过 rpc payOrderNo -> tradeOrderId + // 1.1 查询订单 + TradeOrderDO order = tradeOrderQueryService.getOrderByOutTradeNo(getLoginUserId(), id); + if (order == null) { + return success(null); + } + // 1.2 sync 仅在等待支付 + if (Boolean.TRUE.equals(sync) + && TradeOrderStatusEnum.isUnpaid(order.getStatus()) && !order.getPayStatus()) { + tradeOrderUpdateService.syncOrderPayStatusQuietly(order.getId(), order.getPayOrderId()); + // 重新查询,因为同步后,可能会有变化 + order = tradeOrderQueryService.getOrder(order.getId()); + } + + // 2.1 查询订单项 + List orderItems = tradeOrderQueryService.getOrderItemListByOrderId(order.getId()); + // 2.2 查询物流公司 + DeliveryExpressDO express = order.getLogisticsId() != null && order.getLogisticsId() > 0 ? + deliveryExpressService.getDeliveryExpress(order.getLogisticsId()) : null; + // 2.3 最终组合 + return success(TradeOrderConvert.INSTANCE.convert02(order, orderItems, tradeOrderProperties, express)); + } + @GetMapping("/get-express-track-list") @Operation(summary = "获得交易订单的物流轨迹") @Parameter(name = "id", description = "交易订单编号") diff --git a/yudao-module-mall/yudao-module-trade-server/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java b/yudao-module-mall/yudao-module-trade-server/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java index d2509643d..975f79394 100644 --- a/yudao-module-mall/yudao-module-trade-server/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java +++ b/yudao-module-mall/yudao-module-trade-server/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java @@ -39,7 +39,15 @@ public interface TradeOrderQueryService { * @return 交易订单 */ TradeOrderDO getOrder(Long userId, Long id); - + /** + * 获得指定用户,指定的交易订单 + * PATH需包含「${商品订单号} 」,微信将把你在支付预下单接口填入的 out_trade_no 替换此内容,如「index/orderDetail?id=${商品订单号}&channel=1」。PATH最多输入1条。 + * https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order_center/order_center.html + * @param userId 用户编号 + * @param outTradeNo 支付订单no + * @return 交易订单 + */ + TradeOrderDO getOrderByOutTradeNo(Long userId, String outTradeNo); /** * 获得指定用户,指定活动,指定状态的交易订单 * diff --git a/yudao-module-mall/yudao-module-trade-server/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java b/yudao-module-mall/yudao-module-trade-server/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java index ad530f842..1470f17e8 100644 --- a/yudao-module-mall/yudao-module-trade-server/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-server/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java @@ -1,13 +1,16 @@ package cn.iocoder.yudao.module.trade.service.order; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; import cn.hutool.core.map.MapUtil; +import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.member.api.user.MemberUserApi; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderSummaryRespVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO; @@ -57,6 +60,8 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { @Resource private MemberUserApi memberUserApi; + @Resource + private PayOrderApi payOrderApi; // =================== Order =================== @Override @@ -73,6 +78,19 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { } return order; } + @Override + public TradeOrderDO getOrderByOutTradeNo(Long userId, String outTradeNo) { + // PATH需包含「${商品订单号} 」,微信将把你在支付预下单接口填入的 out_trade_no 替换此内容,如「index/orderDetail?id=${商品订单号}&channel=1」。PATH最多输入1条。 + // https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order_center/order_center.html + // 小程序商品订单详情path配置为:pages/order/detail?id=${商品订单号}&comein_type=wechat + // 通过 rpc payOrderNo -> tradeOrderId + String id = outTradeNo; + String merchantOrderId = payOrderApi.getMerchantOrderIdByPayOrderNo(outTradeNo).getCheckedData(); + if(CharSequenceUtil.isNotEmpty(merchantOrderId)){ + id = merchantOrderId; + } + return getSelf().getOrder(userId, Convert.toLong(id)); + } @Override public TradeOrderDO getOrderByUserIdAndStatusAndCombination(Long userId, Long combinationActivityId, Integer status) { diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java index c0d818d3b..07ac82489 100644 --- a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java @@ -39,4 +39,8 @@ public interface PayOrderApi { CommonResult updatePayOrderPrice(@RequestParam("id") Long id, @RequestParam("payPrice") Integer payPrice); + @PostMapping(PREFIX + "/getMerchantOrderIdByNo") + @Operation(summary = "根据支付订单编号获取商户订单编号") + @Parameter(name = "no", description = "支付单编号", example = "Pxxxx", required = true) + CommonResult getMerchantOrderIdByPayOrderNo(@RequestParam("no") String no); } diff --git a/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java b/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java index 1ca3414db..d83971519 100644 --- a/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java +++ b/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java @@ -37,4 +37,8 @@ public class PayOrderApiImpl implements PayOrderApi { return success(true); } + @Override + public CommonResult getMerchantOrderIdByPayOrderNo(String no) { + return success(payOrderService.getMerchantOrderIdByNo(no)); + } } diff --git a/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderMapper.java b/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderMapper.java index 95510d5f7..e83d0387c 100755 --- a/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderMapper.java +++ b/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderMapper.java @@ -48,6 +48,10 @@ public interface PayOrderMapper extends BaseMapperX { PayOrderDO::getMerchantOrderId, merchantOrderId); } + default PayOrderDO selectByNo(String no) { + return selectOne(PayOrderDO::getNo, no); + } + default int updateByIdAndStatus(Long id, Integer status, PayOrderDO update) { return update(update, new LambdaQueryWrapper() .eq(PayOrderDO::getId, id).eq(PayOrderDO::getStatus, status)); diff --git a/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java b/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java index c4496f829..7853b4417 100755 --- a/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java +++ b/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java @@ -40,6 +40,13 @@ public interface PayOrderService { */ PayOrderDO getOrder(Long appId, String merchantOrderId); + /** + * 获得商户订单编号 + * + * @param no 编号 + * @return merchantOrderId + */ + String getMerchantOrderIdByNo(String no); /** * 获得支付订单列表 * @@ -155,5 +162,4 @@ public interface PayOrderService { * @return 过期的订单数量 */ int expireOrder(); - } diff --git a/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java b/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java index b7f18abd6..6597e048a 100755 --- a/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java @@ -84,6 +84,17 @@ public class PayOrderServiceImpl implements PayOrderService { return orderMapper.selectByAppIdAndMerchantOrderId(appId, merchantOrderId); } + @Override + public String getMerchantOrderIdByNo(String no) { + if(no.contains(payProperties.getOrderNoPrefix())){ + PayOrderDO order = orderMapper.selectByNo(no); + if(ObjectUtil.isNotNull(order)){ + return order.getMerchantOrderId(); + } + } + return null; + } + @Override public List getOrderList(Collection ids) { if (CollUtil.isEmpty(ids)) {