From 20eb0a2a888ad7aa654108a595a863371c4ab3ab Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 4 Jul 2023 23:43:16 +0800 Subject: [PATCH] =?UTF-8?q?mall=20+=20pay=EF=BC=9A=201=E3=80=81=E8=B0=83?= =?UTF-8?q?=E6=95=B4=20returnUrl=20=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/pay/config/PayProperties.java | 9 ----- .../client/impl/alipay/AlipayPcPayClient.java | 34 ++++--------------- .../impl/alipay/AlipayWapPayClient.java | 6 ++-- .../yudao-module-trade-biz/pom.xml | 4 +++ .../order/vo/AppTradeOrderDetailRespVO.java | 4 ++- .../convert/order/TradeOrderConvert.java | 6 ++++ .../module/pay/enums/DictTypeConstants.java | 2 ++ .../admin/notify/PayNotifyController.java | 19 ----------- .../admin/order/vo/PayOrderSubmitReqVO.java | 8 +++-- .../app/order/AppPayOrderController.http | 4 +-- .../service/order/PayOrderServiceImpl.java | 14 ++------ .../src/main/resources/application-dev.yaml | 1 - .../src/main/resources/application-local.yaml | 1 - 13 files changed, 33 insertions(+), 79 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/PayProperties.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/PayProperties.java index 1ea788674..4784e926b 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/PayProperties.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/PayProperties.java @@ -23,13 +23,4 @@ public class PayProperties { @URL(message = "回调地址的格式必须是 URL") private String callbackUrl; - /** - * 回跳地址 - * - * 实际上,对应的 PayNotifyController 的 returnCallback 方法的 URL - */ - @URL(message = "回跳地址的格式必须是 URL") - @NotEmpty(message = "回跳地址不能为空") - private String returnUrl; - } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java index f5626a770..591b02dbc 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; -import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.http.Method; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; @@ -41,11 +40,11 @@ public class AlipayPcPayClient extends AbstractAlipayClient { model.setTimeExpire(formatTime(reqDTO.getExpireTime())); model.setProductCode("FAST_INSTANT_TRADE_PAY"); // 销售产品码. 目前 PC 支付场景下仅支持 FAST_INSTANT_TRADE_PAY // ② 个性化的参数 - // 参考 https://www.pingxx.com/api/支付渠道 extra 参数说明.html 的 alipay_pc_direct 部分 - model.setQrPayMode(MapUtil.getStr(reqDTO.getChannelExtras(), "qr_pay_mode")); - model.setQrcodeWidth(MapUtil.getLong(reqDTO.getChannelExtras(), "qr_code_width")); - // ③ 支付宝 PC 支付有多种展示模式,因此这里需要计算 - String displayMode = getDisplayMode(reqDTO.getDisplayMode(), model.getQrPayMode()); + // 如果想弄更多个性化的参数,可参考 https://www.pingxx.com/api/支付渠道 extra 参数说明.html 的 alipay_pc_direct 部分进行拓展 + model.setQrPayMode("2"); // 跳转模式 - 订单码,效果参见:https://help.pingxx.com/article/1137360/ + // ③ 支付宝 PC 支付有两种展示模式:FORM、URL + String displayMode = ObjectUtil.defaultIfNull(reqDTO.getDisplayMode(), + PayDisplayModeEnum.URL.getMode()); // 1.2 构建 AlipayTradePagePayRequest 请求 AlipayTradePagePayRequest request = new AlipayTradePagePayRequest(); @@ -67,25 +66,4 @@ public class AlipayPcPayClient extends AbstractAlipayClient { .setDisplayContent(response.getBody()); } - /** - * 获得最终的支付 UI 展示模式 - * - * @param displayMode 前端传递的 UI 展示模式 - * @param qrPayMode 前端传递的二维码模式 - * @return 最终的支付 UI 展示模式 - */ - private String getDisplayMode(String displayMode, String qrPayMode) { - // 1.1 支付宝二维码的前置模式 - if (StrUtil.equalsAny(qrPayMode, "0", "1", "3", "4")) { - return PayDisplayModeEnum.IFRAME.getMode(); - } - // 1.2 支付宝二维码的跳转模式 - if (StrUtil.equals(qrPayMode, "2")) { - return PayDisplayModeEnum.URL.getMode(); - } - // 2. 前端传递了 UI 展示模式 - return displayMode != null ? displayMode : - PayDisplayModeEnum.URL.getMode(); // 模式使用 URL 跳转 - } - } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java index 68b91131c..23291a7f3 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; -import cn.hutool.core.util.ObjectUtil; import cn.hutool.http.Method; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; @@ -37,9 +36,8 @@ public class AlipayWapPayClient extends AbstractAlipayClient { model.setTotalAmount(formatAmount(reqDTO.getAmount())); model.setProductCode("QUICK_WAP_PAY"); // 销售产品码. 目前 Wap 支付场景下仅支持 QUICK_WAP_PAY // ② 个性化的参数【无】 - // ③ 支付宝 Wap 支付只有一种展示,考虑到前端可能希望二维码扫描后,手机打开 - String displayMode = ObjectUtil.defaultIfNull(reqDTO.getDisplayMode(), - PayDisplayModeEnum.URL.getMode()); + // ③ 支付宝 Wap 支付只有一种展示:URL + String displayMode = PayDisplayModeEnum.URL.getMode(); // 1.2 构建 AlipayTradeWapPayRequest 请求 AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest(); diff --git a/yudao-module-mall/yudao-module-trade-biz/pom.xml b/yudao-module-mall/yudao-module-trade-biz/pom.xml index a6f122a78..810446fa9 100644 --- a/yudao-module-mall/yudao-module-trade-biz/pom.xml +++ b/yudao-module-mall/yudao-module-trade-biz/pom.xml @@ -93,6 +93,10 @@ cn.iocoder.boot yudao-spring-boot-starter-excel + + cn.iocoder.boot + yudao-spring-boot-starter-biz-dict + diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderDetailRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderDetailRespVO.java index f9e6a6864..7a67190fc 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderDetailRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderDetailRespVO.java @@ -55,8 +55,10 @@ public class AppTradeOrderDetailRespVO { @Schema(description = "付款超时时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime payExpireTime; - @Schema(description = "支付渠道", requiredMode = Schema.RequiredMode.REQUIRED, example = "wx_lite_pay") + @Schema(description = "支付渠道", example = "wx_lite_pay") private String payChannelCode; + @Schema(description = "支付渠道名", example = "微信小程序支付") + private String payChannelName; @Schema(description = "商品原价(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") private Integer totalPrice; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java index 9fb449040..88ce02300 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java @@ -1,12 +1,15 @@ package cn.iocoder.yudao.module.trade.convert.order; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; +import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; @@ -234,6 +237,9 @@ public interface TradeOrderConvert { List propertyValueDetails, TradeOrderProperties tradeOrderProperties) { AppTradeOrderDetailRespVO orderVO = convert3(order, orderItems); orderVO.setPayExpireTime(addTime(tradeOrderProperties.getExpireTime())); + if (StrUtil.isNotEmpty(order.getPayChannelCode())) { + orderVO.setPayChannelName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.CHANNEL_CODE_TYPE, order.getPayChannelCode())); + } // 处理商品属性 Map propertyValueDetailMap = convertMap(propertyValueDetails, ProductPropertyValueDetailRespDTO::getValueId); for (int i = 0; i < orderItems.size(); i++) { diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/DictTypeConstants.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/DictTypeConstants.java index 58eb776d3..717ce09eb 100644 --- a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/DictTypeConstants.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/DictTypeConstants.java @@ -7,6 +7,8 @@ package cn.iocoder.yudao.module.pay.enums; */ public interface DictTypeConstants { + String CHANNEL_CODE_TYPE = "pay_channel_code_type"; // 支付-渠道名 + String ORDER_STATUS = "pay_order_status"; // 支付-订单-订单状态 String ORDER_NOTIFY_STATUS = "pay_order_notify_status"; // 支付-订单-订单回调商户状态 diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java index e64ec6a06..3660eddd5 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java @@ -6,8 +6,6 @@ import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayNotifyReqDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayOrderNotifyRespDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayRefundNotifyRespDTO; -import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO; -import cn.iocoder.yudao.module.pay.service.merchant.PayChannelService; import cn.iocoder.yudao.module.pay.service.order.PayOrderService; import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; import io.swagger.v3.oas.annotations.Operation; @@ -39,23 +37,6 @@ public class PayNotifyController { @Resource private PayClientFactory payClientFactory; - /** - * 统一的跳转页面,支付宝跳转参数说明 - * - * 支付宝 - 前台回跳参数说明 - * - * @param channelId 渠道编号 - * @return 返回跳转页面 - */ - @GetMapping(value = "/return/{channelId}") - @Operation(summary = "渠道统一的支付成功返回地址") - @Deprecated // TODO yunai:如果是 way 的情况,应该是跳转回前端地址 - public String returnCallback(@PathVariable("channelId") Long channelId, - @RequestParam Map params) { - log.info("[returnCallback][app_id({}) 跳转]", params.get("app_id")); - return String.format("渠道[%s]支付成功", channelId); - } - /** * 统一的渠道支付回调,支付宝的退款回调 * diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderSubmitReqVO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderSubmitReqVO.java index 09ac7381e..ffda105b7 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderSubmitReqVO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderSubmitReqVO.java @@ -2,11 +2,10 @@ package cn.iocoder.yudao.module.pay.controller.admin.order.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.experimental.Accessors; +import org.hibernate.validator.constraints.URL; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; -import java.awt.*; import java.util.Map; @Schema(description = "管理后台 - 支付订单提交 Request VO") @@ -26,4 +25,9 @@ public class PayOrderSubmitReqVO { @Schema(description = "展示模式", example = "url") // 参见 {@link PayDisplayModeEnum} 枚举。如果不传递,则每个支付渠道使用默认的方式 private String displayMode; + + @Schema(description = "回跳地址") + @URL(message = "回跳地址的格式必须是 URL") + private String returnUrl; + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.http b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.http index 539d7965d..b2da78127 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.http +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.http @@ -5,6 +5,6 @@ Authorization: Bearer {{appToken}} tenant-id: {{appTenentId}} { - "id": 125, - "channelCode": "alipay_qr" + "id": 174, + "channelCode": "alipay_pc" } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java index f416c07f3..a653887a9 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java @@ -4,7 +4,6 @@ import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.RandomUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.pay.config.PayProperties; import cn.iocoder.yudao.framework.pay.core.client.PayClient; import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; @@ -44,7 +43,7 @@ import java.util.Collection; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.*; +import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; /** * 支付订单 Service 实现类 @@ -147,7 +146,7 @@ public class PayOrderServiceImpl implements PayOrderService { .setMerchantOrderId(orderExtension.getNo()) // 注意,此处使用的是 PayOrderExtensionDO.no 属性! .setSubject(order.getSubject()).setBody(order.getBody()) .setNotifyUrl(genChannelPayNotifyUrl(channel)) - .setReturnUrl(genChannelReturnUrl(channel)) + .setReturnUrl(reqVO.getReturnUrl()) // 订单相关字段 .setAmount(order.getAmount()).setExpireTime(order.getExpireTime()); PayOrderUnifiedRespDTO unifiedOrderRespDTO = client.unifiedOrder(unifiedOrderReqDTO); @@ -183,15 +182,6 @@ public class PayOrderServiceImpl implements PayOrderService { return channel; } - /** - * 根据支付渠道的编码,生成支付渠道的返回地址 - * @param channel 支付渠道 - * @return 支付成功返回的地址。 配置地址 + "/" + channel id - */ - private String genChannelReturnUrl(PayChannelDO channel) { - return payProperties.getReturnUrl() + "/" + channel.getId(); - } - /** * 根据支付渠道的编码,生成支付渠道的回调地址 * diff --git a/yudao-server/src/main/resources/application-dev.yaml b/yudao-server/src/main/resources/application-dev.yaml index 7cc4801e5..ddacc5485 100644 --- a/yudao-server/src/main/resources/application-dev.yaml +++ b/yudao-server/src/main/resources/application-dev.yaml @@ -168,7 +168,6 @@ yudao: - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 pay: callback-url: http://yunai.natapp1.cc/admin-api/pay/notify/callback - return-url: http://yunai.natapp1.cc/admin-api/pay/notify/return demo: true # 开启演示模式 justauth: diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index cdc1d3fde..2059b107d 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -195,7 +195,6 @@ yudao: - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 pay: callback-url: http://yunai.natapp1.cc/admin-api/pay/notify/callback - return-url: http://yunai.natapp1.cc/admin-api/pay/notify/return access-log: # 访问日志的配置项 enable: false error-code: # 错误码相关配置项