Commit 20eb0a2a888ad7aa654108a595a863371c4ab3ab

Authored by YunaiV
1 parent 23e3c4d0

mall + pay:

1、调整 returnUrl 的实现
Showing 13 changed files with 33 additions and 79 deletions
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 {
23 23 @URL(message = "回调地址的格式必须是 URL")
24 24 private String callbackUrl;
25 25  
26   - /**
27   - * 回跳地址
28   - *
29   - * 实际上,对应的 PayNotifyController 的 returnCallback 方法的 URL
30   - */
31   - @URL(message = "回跳地址的格式必须是 URL")
32   - @NotEmpty(message = "回跳地址不能为空")
33   - private String returnUrl;
34   -
35 26 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java
1 1 package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
2 2  
3   -import cn.hutool.core.map.MapUtil;
4   -import cn.hutool.core.util.StrUtil;
  3 +import cn.hutool.core.util.ObjectUtil;
5 4 import cn.hutool.http.Method;
6 5 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
7 6 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO;
... ... @@ -41,11 +40,11 @@ public class AlipayPcPayClient extends AbstractAlipayClient {
41 40 model.setTimeExpire(formatTime(reqDTO.getExpireTime()));
42 41 model.setProductCode("FAST_INSTANT_TRADE_PAY"); // 销售产品码. 目前 PC 支付场景下仅支持 FAST_INSTANT_TRADE_PAY
43 42 // ② 个性化的参数
44   - // 参考 https://www.pingxx.com/api/支付渠道 extra 参数说明.html 的 alipay_pc_direct 部分
45   - model.setQrPayMode(MapUtil.getStr(reqDTO.getChannelExtras(), "qr_pay_mode"));
46   - model.setQrcodeWidth(MapUtil.getLong(reqDTO.getChannelExtras(), "qr_code_width"));
47   - // ③ 支付宝 PC 支付有多种展示模式,因此这里需要计算
48   - String displayMode = getDisplayMode(reqDTO.getDisplayMode(), model.getQrPayMode());
  43 + // 如果想弄更多个性化的参数,可参考 https://www.pingxx.com/api/支付渠道 extra 参数说明.html 的 alipay_pc_direct 部分进行拓展
  44 + model.setQrPayMode("2"); // 跳转模式 - 订单码,效果参见:https://help.pingxx.com/article/1137360/
  45 + // ③ 支付宝 PC 支付有两种展示模式:FORM、URL
  46 + String displayMode = ObjectUtil.defaultIfNull(reqDTO.getDisplayMode(),
  47 + PayDisplayModeEnum.URL.getMode());
49 48  
50 49 // 1.2 构建 AlipayTradePagePayRequest 请求
51 50 AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
... ... @@ -67,25 +66,4 @@ public class AlipayPcPayClient extends AbstractAlipayClient {
67 66 .setDisplayContent(response.getBody());
68 67 }
69 68  
70   - /**
71   - * 获得最终的支付 UI 展示模式
72   - *
73   - * @param displayMode 前端传递的 UI 展示模式
74   - * @param qrPayMode 前端传递的二维码模式
75   - * @return 最终的支付 UI 展示模式
76   - */
77   - private String getDisplayMode(String displayMode, String qrPayMode) {
78   - // 1.1 支付宝二维码的前置模式
79   - if (StrUtil.equalsAny(qrPayMode, "0", "1", "3", "4")) {
80   - return PayDisplayModeEnum.IFRAME.getMode();
81   - }
82   - // 1.2 支付宝二维码的跳转模式
83   - if (StrUtil.equals(qrPayMode, "2")) {
84   - return PayDisplayModeEnum.URL.getMode();
85   - }
86   - // 2. 前端传递了 UI 展示模式
87   - return displayMode != null ? displayMode :
88   - PayDisplayModeEnum.URL.getMode(); // 模式使用 URL 跳转
89   - }
90   -
91 69 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java
1 1 package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
2 2  
3   -import cn.hutool.core.util.ObjectUtil;
4 3 import cn.hutool.http.Method;
5 4 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
6 5 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO;
... ... @@ -37,9 +36,8 @@ public class AlipayWapPayClient extends AbstractAlipayClient {
37 36 model.setTotalAmount(formatAmount(reqDTO.getAmount()));
38 37 model.setProductCode("QUICK_WAP_PAY"); // 销售产品码. 目前 Wap 支付场景下仅支持 QUICK_WAP_PAY
39 38 // ② 个性化的参数【无】
40   - // ③ 支付宝 Wap 支付只有一种展示,考虑到前端可能希望二维码扫描后,手机打开
41   - String displayMode = ObjectUtil.defaultIfNull(reqDTO.getDisplayMode(),
42   - PayDisplayModeEnum.URL.getMode());
  39 + // ③ 支付宝 Wap 支付只有一种展示:URL
  40 + String displayMode = PayDisplayModeEnum.URL.getMode();
43 41  
44 42 // 1.2 构建 AlipayTradeWapPayRequest 请求
45 43 AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
... ...
yudao-module-mall/yudao-module-trade-biz/pom.xml
... ... @@ -93,6 +93,10 @@
93 93 <groupId>cn.iocoder.boot</groupId>
94 94 <artifactId>yudao-spring-boot-starter-excel</artifactId>
95 95 </dependency>
  96 + <dependency>
  97 + <groupId>cn.iocoder.boot</groupId>
  98 + <artifactId>yudao-spring-boot-starter-biz-dict</artifactId>
  99 + </dependency>
96 100  
97 101 </dependencies>
98 102  
... ...
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 {
55 55 @Schema(description = "付款超时时间", requiredMode = Schema.RequiredMode.REQUIRED)
56 56 private LocalDateTime payExpireTime;
57 57  
58   - @Schema(description = "支付渠道", requiredMode = Schema.RequiredMode.REQUIRED, example = "wx_lite_pay")
  58 + @Schema(description = "支付渠道", example = "wx_lite_pay")
59 59 private String payChannelCode;
  60 + @Schema(description = "支付渠道名", example = "微信小程序支付")
  61 + private String payChannelName;
60 62  
61 63 @Schema(description = "商品原价(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
62 64 private Integer totalPrice;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
1 1 package cn.iocoder.yudao.module.trade.convert.order;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.StrUtil;
4 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 6 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  7 +import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
6 8 import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
7 9 import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
8 10 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
9 11 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
  12 +import cn.iocoder.yudao.module.pay.enums.DictTypeConstants;
10 13 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
11 14 import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
12 15 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
... ... @@ -234,6 +237,9 @@ public interface TradeOrderConvert {
234 237 List<ProductPropertyValueDetailRespDTO> propertyValueDetails, TradeOrderProperties tradeOrderProperties) {
235 238 AppTradeOrderDetailRespVO orderVO = convert3(order, orderItems);
236 239 orderVO.setPayExpireTime(addTime(tradeOrderProperties.getExpireTime()));
  240 + if (StrUtil.isNotEmpty(order.getPayChannelCode())) {
  241 + orderVO.setPayChannelName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.CHANNEL_CODE_TYPE, order.getPayChannelCode()));
  242 + }
237 243 // 处理商品属性
238 244 Map<Long, ProductPropertyValueDetailRespDTO> propertyValueDetailMap = convertMap(propertyValueDetails, ProductPropertyValueDetailRespDTO::getValueId);
239 245 for (int i = 0; i < orderItems.size(); i++) {
... ...
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;
7 7 */
8 8 public interface DictTypeConstants {
9 9  
  10 + String CHANNEL_CODE_TYPE = "pay_channel_code_type"; // 支付-渠道名
  11 +
10 12 String ORDER_STATUS = "pay_order_status"; // 支付-订单-订单状态
11 13 String ORDER_NOTIFY_STATUS = "pay_order_notify_status"; // 支付-订单-订单回调商户状态
12 14  
... ...
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;
6 6 import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayNotifyReqDTO;
7 7 import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayOrderNotifyRespDTO;
8 8 import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayRefundNotifyRespDTO;
9   -import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO;
10   -import cn.iocoder.yudao.module.pay.service.merchant.PayChannelService;
11 9 import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
12 10 import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
13 11 import io.swagger.v3.oas.annotations.Operation;
... ... @@ -40,23 +38,6 @@ public class PayNotifyController {
40 38 private PayClientFactory payClientFactory;
41 39  
42 40 /**
43   - * 统一的跳转页面,支付宝跳转参数说明
44   - *
45   - * <a href="https://opendocs.alipay.com/open/203/105285#前台回跳参数说明">支付宝 - 前台回跳参数说明</a>
46   - *
47   - * @param channelId 渠道编号
48   - * @return 返回跳转页面
49   - */
50   - @GetMapping(value = "/return/{channelId}")
51   - @Operation(summary = "渠道统一的支付成功返回地址")
52   - @Deprecated // TODO yunai:如果是 way 的情况,应该是跳转回前端地址
53   - public String returnCallback(@PathVariable("channelId") Long channelId,
54   - @RequestParam Map<String, String> params) {
55   - log.info("[returnCallback][app_id({}) 跳转]", params.get("app_id"));
56   - return String.format("渠道[%s]支付成功", channelId);
57   - }
58   -
59   - /**
60 41 * 统一的渠道支付回调,支付宝的退款回调
61 42 *
62 43 * @param channelId 渠道编号
... ...
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;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Data;
5   -import lombok.experimental.Accessors;
  5 +import org.hibernate.validator.constraints.URL;
6 6  
7 7 import javax.validation.constraints.NotEmpty;
8 8 import javax.validation.constraints.NotNull;
9   -import java.awt.*;
10 9 import java.util.Map;
11 10  
12 11 @Schema(description = "管理后台 - 支付订单提交 Request VO")
... ... @@ -26,4 +25,9 @@ public class PayOrderSubmitReqVO {
26 25  
27 26 @Schema(description = "展示模式", example = "url") // 参见 {@link PayDisplayModeEnum} 枚举。如果不传递,则每个支付渠道使用默认的方式
28 27 private String displayMode;
  28 +
  29 + @Schema(description = "回跳地址")
  30 + @URL(message = "回跳地址的格式必须是 URL")
  31 + private String returnUrl;
  32 +
29 33 }
... ...
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}}
5 5 tenant-id: {{appTenentId}}
6 6  
7 7 {
8   - "id": 125,
9   - "channelCode": "alipay_qr"
  8 + "id": 174,
  9 + "channelCode": "alipay_pc"
10 10 }
... ...
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;
4 4 import cn.hutool.core.util.ObjectUtil;
5 5 import cn.hutool.core.util.RandomUtil;
6 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7   -import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
8 7 import cn.iocoder.yudao.framework.pay.config.PayProperties;
9 8 import cn.iocoder.yudao.framework.pay.core.client.PayClient;
10 9 import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
... ... @@ -44,7 +43,7 @@ import java.util.Collection;
44 43 import java.util.List;
45 44  
46 45 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
47   -import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.*;
  46 +import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
48 47  
49 48 /**
50 49 * 支付订单 Service 实现类
... ... @@ -147,7 +146,7 @@ public class PayOrderServiceImpl implements PayOrderService {
147 146 .setMerchantOrderId(orderExtension.getNo()) // 注意,此处使用的是 PayOrderExtensionDO.no 属性!
148 147 .setSubject(order.getSubject()).setBody(order.getBody())
149 148 .setNotifyUrl(genChannelPayNotifyUrl(channel))
150   - .setReturnUrl(genChannelReturnUrl(channel))
  149 + .setReturnUrl(reqVO.getReturnUrl())
151 150 // 订单相关字段
152 151 .setAmount(order.getAmount()).setExpireTime(order.getExpireTime());
153 152 PayOrderUnifiedRespDTO unifiedOrderRespDTO = client.unifiedOrder(unifiedOrderReqDTO);
... ... @@ -184,15 +183,6 @@ public class PayOrderServiceImpl implements PayOrderService {
184 183 }
185 184  
186 185 /**
187   - * 根据支付渠道的编码,生成支付渠道的返回地址
188   - * @param channel 支付渠道
189   - * @return 支付成功返回的地址。 配置地址 + "/" + channel id
190   - */
191   - private String genChannelReturnUrl(PayChannelDO channel) {
192   - return payProperties.getReturnUrl() + "/" + channel.getId();
193   - }
194   -
195   - /**
196 186 * 根据支付渠道的编码,生成支付渠道的回调地址
197 187 *
198 188 * @param channel 支付渠道
... ...
yudao-server/src/main/resources/application-dev.yaml
... ... @@ -168,7 +168,6 @@ yudao:
168 168 - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求
169 169 pay:
170 170 callback-url: http://yunai.natapp1.cc/admin-api/pay/notify/callback
171   - return-url: http://yunai.natapp1.cc/admin-api/pay/notify/return
172 171 demo: true # 开启演示模式
173 172  
174 173 justauth:
... ...
yudao-server/src/main/resources/application-local.yaml
... ... @@ -195,7 +195,6 @@ yudao:
195 195 - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求
196 196 pay:
197 197 callback-url: http://yunai.natapp1.cc/admin-api/pay/notify/callback
198   - return-url: http://yunai.natapp1.cc/admin-api/pay/notify/return
199 198 access-log: # 访问日志的配置项
200 199 enable: false
201 200 error-code: # 错误码相关配置项
... ...