Commit 183206e2d3e442fff824b9dab4fae522ce66ba6e

Authored by jason
1 parent 00e18a48

转账 - 支付宝转账修改, 支付宝 Client 支持公钥证书模式

Showing 12 changed files with 118 additions and 163 deletions
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java
... ... @@ -50,8 +50,6 @@ public class PayClientFactoryImpl implements PayClientFactory {
50 50 clientClass.put(ALIPAY_APP, AlipayAppPayClient.class);
51 51 clientClass.put(ALIPAY_PC, AlipayPcPayClient.class);
52 52 clientClass.put(ALIPAY_BAR, AlipayBarPayClient.class);
53   - // 支付包转账客户端
54   - clientClass.put(ALIPAY_TRANSFER, AlipayTransferClient.class);
55 53 // Mock 支付客户端
56 54 clientClass.put(MOCK, MockPayClient.class);
57 55 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java
... ... @@ -6,24 +6,28 @@ import cn.hutool.core.lang.Assert;
6 6 import cn.hutool.core.map.MapUtil;
7 7 import cn.hutool.core.util.StrUtil;
8 8 import cn.hutool.http.HttpUtil;
  9 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
9 10 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
10 11 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
11 12 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
12 13 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
13 14 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
  15 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
  16 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
14 17 import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
15 18 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum;
  19 +import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
16 20 import com.alipay.api.AlipayApiException;
17 21 import com.alipay.api.AlipayConfig;
18 22 import com.alipay.api.AlipayResponse;
19 23 import com.alipay.api.DefaultAlipayClient;
20   -import com.alipay.api.domain.AlipayTradeFastpayRefundQueryModel;
21   -import com.alipay.api.domain.AlipayTradeQueryModel;
22   -import com.alipay.api.domain.AlipayTradeRefundModel;
  24 +import com.alipay.api.domain.*;
23 25 import com.alipay.api.internal.util.AlipaySignature;
  26 +import com.alipay.api.request.AlipayFundTransUniTransferRequest;
24 27 import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest;
25 28 import com.alipay.api.request.AlipayTradeQueryRequest;
26 29 import com.alipay.api.request.AlipayTradeRefundRequest;
  30 +import com.alipay.api.response.AlipayFundTransUniTransferResponse;
27 31 import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
28 32 import com.alipay.api.response.AlipayTradeQueryResponse;
29 33 import com.alipay.api.response.AlipayTradeRefundResponse;
... ... @@ -39,6 +43,9 @@ import java.util.Objects;
39 43 import java.util.function.Supplier;
40 44  
41 45 import static cn.hutool.core.date.DatePattern.NORM_DATETIME_FORMATTER;
  46 +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
  47 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
  48 +import static cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig.MODE_CERTIFICATE;
42 49  
43 50 /**
44 51 * 支付宝抽象类,实现支付宝统一的接口、以及部分实现(退款)
... ... @@ -105,16 +112,20 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
105 112 // 1.2 构建 AlipayTradeQueryRequest 请求
106 113 AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
107 114 request.setBizModel(model);
108   -
109   - // 2.1 执行请求
110   - AlipayTradeQueryResponse response = client.execute(request);
  115 + AlipayTradeQueryResponse response;
  116 + if (Objects.equals(config.getMode(), MODE_CERTIFICATE)) {
  117 + // 证书模式
  118 + response = client.certificateExecute(request);
  119 + } else {
  120 + response = client.execute(request);
  121 + }
111 122 if (!response.isSuccess()) { // 不成功,例如说订单不存在
112 123 return PayOrderRespDTO.closedOf(response.getSubCode(), response.getSubMsg(),
113 124 outTradeNo, response);
114 125 }
115 126 // 2.2 解析订单的状态
116 127 Integer status = parseStatus(response.getTradeStatus());
117   - Assert.notNull(status, (Supplier<Throwable>) () -> {
  128 + Assert.notNull(status, () -> {
118 129 throw new IllegalArgumentException(StrUtil.format("body({}) 的 trade_status 不正确", response.getBody()));
119 130 });
120 131 return PayOrderRespDTO.of(status, response.getTradeNo(), response.getBuyerUserId(), LocalDateTimeUtil.of(response.getSendPayDate()),
... ... @@ -148,7 +159,13 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa
148 159 request.setBizModel(model);
149 160  
150 161 // 2.1 执行请求
151   - AlipayTradeRefundResponse response = client.execute(request);
  162 + AlipayTradeRefundResponse response;
  163 + if (Objects.equals(config.getMode(), MODE_CERTIFICATE)) {
  164 + // 证书模式
  165 + response = client.certificateExecute(request);
  166 + } else {
  167 + response = client.execute(request);
  168 + }
152 169 if (!response.isSuccess()) {
153 170 // 当出现 ACQ.SYSTEM_ERROR, 退款可能成功也可能失败。 返回 WAIT 状态. 后续 job 会轮询
154 171 if (ObjectUtils.equalsAny(response.getSubCode(), "ACQ.SYSTEM_ERROR", "SYSTEM_ERROR")) {
... ... @@ -185,7 +202,13 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa
185 202 request.setBizModel(model);
186 203  
187 204 // 2.1 执行请求
188   - AlipayTradeFastpayRefundQueryResponse response = client.execute(request);
  205 + AlipayTradeFastpayRefundQueryResponse response;
  206 + if (Objects.equals(config.getMode(), MODE_CERTIFICATE)) {
  207 + // 证书模式
  208 + response = client.certificateExecute(request);
  209 + } else {
  210 + response = client.execute(request);
  211 + }
189 212 if (!response.isSuccess()) {
190 213 // 明确不存在的情况,应该就是失败,可进行关闭
191 214 if (ObjectUtils.equalsAny(response.getSubCode(), "TRADE_NOT_EXIST", "ACQ.TRADE_NOT_EXIST")) {
... ... @@ -202,7 +225,69 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa
202 225 return PayRefundRespDTO.waitingOf(null, outRefundNo, response);
203 226 }
204 227  
  228 + @Override
  229 + protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) throws AlipayApiException {
  230 + // 1.1 校验公钥类型 必须使用公钥证书模式
  231 + if (!Objects.equals(config.getMode(), MODE_CERTIFICATE)) {
  232 + throw new IllegalStateException("支付宝单笔转账必须使用公钥证书模式");
  233 + }
205 234  
  235 + // 1.2 构建 AlipayFundTransUniTransferModel
  236 + AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
  237 + // ① 通用的参数
  238 + model.setTransAmount(formatAmount(reqDTO.getPrice())); // 转账金额
  239 + model.setOrderTitle(reqDTO.getTitle()); // 转账业务的标题,用于在支付宝用户的账单里显示。
  240 + model.setOutBizNo(reqDTO.getOutTransferNo());
  241 + model.setProductCode("TRANS_ACCOUNT_NO_PWD"); // 销售产品码。单笔无密转账固定为 TRANS_ACCOUNT_NO_PWD
  242 + model.setBizScene("DIRECT_TRANSFER"); // 业务场景 单笔无密转账固定为 DIRECT_TRANSFER
  243 + model.setBusinessParams(JsonUtils.toJsonString(reqDTO.getChannelExtras()));
  244 + PayTransferTypeEnum transferType = PayTransferTypeEnum.typeOf(reqDTO.getType());
  245 + switch (transferType) {
  246 + // TODO @jason:是不是不用传递 transferType 参数哈?因为应该已经明确是支付宝啦?
  247 + // @芋艿。 是不是还要考虑转账到银行卡。所以传 transferType 但是转账到银行卡不知道要如何测试??
  248 + case ALIPAY_BALANCE: {
  249 + // ② 个性化的参数
  250 + Participant payeeInfo = new Participant();
  251 + payeeInfo.setIdentityType("ALIPAY_LOGON_ID");
  252 + String logonId = MapUtil.getStr(reqDTO.getPayeeInfo(), "ALIPAY_LOGON_ID");
  253 + if (StrUtil.isEmpty(logonId)) {
  254 + throw exception0(BAD_REQUEST.getCode(), "支付包登录 ID 不能为空");
  255 + }
  256 + String accountName = MapUtil.getStr(reqDTO.getPayeeInfo(), "ALIPAY_ACCOUNT_NAME");
  257 + if (StrUtil.isEmpty(accountName)) {
  258 + throw exception0(BAD_REQUEST.getCode(), "支付包账户名称不能为空");
  259 + }
  260 + payeeInfo.setIdentity(logonId); // 支付宝登录号
  261 + payeeInfo.setName(accountName); // 支付宝账号姓名
  262 + model.setPayeeInfo(payeeInfo);
  263 + // 1.3 构建 AlipayFundTransUniTransferRequest
  264 + AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
  265 + request.setBizModel(model);
  266 + // 执行请求
  267 + AlipayFundTransUniTransferResponse response = client.certificateExecute(request);
  268 + // 处理结果
  269 + if (!response.isSuccess()) {
  270 + // 当出现 SYSTEM_ERROR, 转账可能成功也可能失败。 返回 WAIT 状态. 后续 job 会轮询
  271 + if (ObjectUtils.equalsAny(response.getSubCode(), "SYSTEM_ERROR", "ACQ.SYSTEM_ERROR")) {
  272 + return PayTransferRespDTO.waitingOf(null, reqDTO.getOutTransferNo(), response);
  273 + }
  274 + return PayTransferRespDTO.closedOf(response.getSubCode(), response.getSubMsg(),
  275 + reqDTO.getOutTransferNo(), response);
  276 + }
  277 + return PayTransferRespDTO.successOf(response.getOrderId(), parseTime(response.getTransDate()),
  278 + response.getOutBizNo(), response);
  279 + }
  280 + case BANK_CARD: {
  281 + Participant payeeInfo = new Participant();
  282 + payeeInfo.setIdentityType("BANKCARD_ACCOUNT");
  283 + // TODO 待实现
  284 + throw new UnsupportedOperationException("待实现");
  285 + }
  286 + default: {
  287 + throw new IllegalStateException("不正确的转账类型: " + transferType);
  288 + }
  289 + }
  290 + }
206 291  
207 292 // ========== 各种工具方法 ==========
208 293  
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayAppPayClient.java
... ... @@ -2,8 +2,6 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
2 2  
3 3 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
4 4 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
5   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
6   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
7 5 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
8 6 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
9 7 import com.alipay.api.AlipayApiException;
... ... @@ -58,9 +56,4 @@ public class AlipayAppPayClient extends AbstractAlipayPayClient {
58 56 return PayOrderRespDTO.waitingOf(displayMode, response.getBody(),
59 57 reqDTO.getOutTradeNo(), response);
60 58 }
61   -
62   - @Override
63   - protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
64   - throw new UnsupportedOperationException("支付宝【App 支付】不支持转账操作");
65   - }
66 59 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayBarPayClient.java
... ... @@ -5,8 +5,6 @@ import cn.hutool.core.map.MapUtil;
5 5 import cn.hutool.core.util.StrUtil;
6 6 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
7 7 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
8   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
9   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
10 8 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
11 9 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
12 10 import com.alipay.api.AlipayApiException;
... ... @@ -16,9 +14,11 @@ import com.alipay.api.response.AlipayTradePayResponse;
16 14 import lombok.extern.slf4j.Slf4j;
17 15  
18 16 import java.time.LocalDateTime;
  17 +import java.util.Objects;
19 18  
20 19 import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
21 20 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
  21 +import static cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig.MODE_CERTIFICATE;
22 22  
23 23 /**
24 24 * 支付宝【条码支付】的 PayClient 实现类
... ... @@ -61,7 +61,13 @@ public class AlipayBarPayClient extends AbstractAlipayPayClient {
61 61 request.setReturnUrl(reqDTO.getReturnUrl());
62 62  
63 63 // 2.1 执行请求
64   - AlipayTradePayResponse response = client.execute(request);
  64 + AlipayTradePayResponse response;
  65 + if (Objects.equals(config.getMode(), MODE_CERTIFICATE)) {
  66 + // 证书模式
  67 + response = client.certificateExecute(request);
  68 + } else {
  69 + response = client.execute(request);
  70 + }
65 71 // 2.2 处理结果
66 72 if (!response.isSuccess()) {
67 73 return buildClosedPayOrderRespDTO(reqDTO, response);
... ... @@ -76,9 +82,4 @@ public class AlipayBarPayClient extends AbstractAlipayPayClient {
76 82 return PayOrderRespDTO.waitingOf(displayMode, "",
77 83 reqDTO.getOutTradeNo(), response);
78 84 }
79   -
80   - @Override
81   - protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
82   - throw new UnsupportedOperationException("支付宝【条码支付】不支持转账操作");
83   - }
84 85 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java
... ... @@ -4,8 +4,6 @@ import cn.hutool.core.util.ObjectUtil;
4 4 import cn.hutool.http.Method;
5 5 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
6 6 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
7   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
8   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
9 7 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
10 8 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
11 9 import com.alipay.api.AlipayApiException;
... ... @@ -68,9 +66,4 @@ public class AlipayPcPayClient extends AbstractAlipayPayClient {
68 66 return PayOrderRespDTO.waitingOf(displayMode, response.getBody(),
69 67 reqDTO.getOutTradeNo(), response);
70 68 }
71   -
72   - @Override
73   - protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
74   - throw new UnsupportedOperationException("支付宝【PC 网站】不支持转账操作");
75   - }
76 69 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClient.java
... ... @@ -2,8 +2,6 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
2 2  
3 3 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
4 4 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
5   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
6   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
7 5 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
8 6 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
9 7 import com.alipay.api.AlipayApiException;
... ... @@ -12,6 +10,10 @@ import com.alipay.api.request.AlipayTradePrecreateRequest;
12 10 import com.alipay.api.response.AlipayTradePrecreateResponse;
13 11 import lombok.extern.slf4j.Slf4j;
14 12  
  13 +import java.util.Objects;
  14 +
  15 +import static cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig.MODE_CERTIFICATE;
  16 +
15 17 /**
16 18 * 支付宝【扫码支付】的 PayClient 实现类
17 19 *
... ... @@ -47,7 +49,13 @@ public class AlipayQrPayClient extends AbstractAlipayPayClient {
47 49 request.setReturnUrl(reqDTO.getReturnUrl());
48 50  
49 51 // 2.1 执行请求
50   - AlipayTradePrecreateResponse response = client.execute(request);
  52 + AlipayTradePrecreateResponse response;
  53 + if (Objects.equals(config.getMode(), MODE_CERTIFICATE)) {
  54 + // 证书模式
  55 + response = client.certificateExecute(request);
  56 + } else {
  57 + response = client.execute(request);
  58 + }
51 59 // 2.2 处理结果
52 60 if (!response.isSuccess()) {
53 61 return buildClosedPayOrderRespDTO(reqDTO, response);
... ... @@ -55,9 +63,4 @@ public class AlipayQrPayClient extends AbstractAlipayPayClient {
55 63 return PayOrderRespDTO.waitingOf(displayMode, response.getQrCode(),
56 64 reqDTO.getOutTradeNo(), response);
57 65 }
58   -
59   - @Override
60   - protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
61   - throw new UnsupportedOperationException("支付宝【扫码支付】不支持转账操作");
62   - }
63 66 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayTransferClient.java deleted
1   -package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
2   -
3   -import cn.hutool.core.map.MapUtil;
4   -import cn.hutool.core.util.StrUtil;
5   -import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
6   -import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
7   -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
8   -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
9   -import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
10   -import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
11   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
12   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
13   -import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
14   -import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
15   -import com.alipay.api.AlipayApiException;
16   -import com.alipay.api.domain.AlipayFundTransUniTransferModel;
17   -import com.alipay.api.domain.Participant;
18   -import com.alipay.api.request.AlipayFundTransUniTransferRequest;
19   -import com.alipay.api.response.AlipayFundTransUniTransferResponse;
20   -import lombok.extern.slf4j.Slf4j;
21   -
22   -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
23   -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
24   -
25   -// TODO @jason:看看能不能融合到 AbstractAlipayPayClient 中。
26   -/**
27   - * 支付宝转账的 PayClient 实现类
28   - *
29   - * @author jason
30   - */
31   -@Slf4j
32   -public class AlipayTransferClient extends AbstractAlipayPayClient {
33   - // TODO @jason:方法之间,要有空格噢
34   - public AlipayTransferClient(Long channelId, AlipayPayClientConfig config) {
35   - super(channelId, PayChannelEnum.ALIPAY_TRANSFER.getCode(), config);
36   - }
37   - @Override
38   - protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
39   - throw new UnsupportedOperationException("支付宝转账不支持统一下单请求");
40   - }
41   - @Override
42   - protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
43   - throw new UnsupportedOperationException("支付宝转账不支持统一退款请求");
44   - }
45   - @Override
46   - protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) throws AlipayApiException {
47   - // 1.1 构建 AlipayFundTransUniTransferModel
48   - AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
49   - // ① 通用的参数
50   - model.setTransAmount(formatAmount(reqDTO.getPrice())); // 转账金额
51   - model.setOrderTitle(reqDTO.getTitle()); // 转账业务的标题,用于在支付宝用户的账单里显示。
52   - model.setOutBizNo(reqDTO.getOutTransferNo());
53   - model.setProductCode("TRANS_ACCOUNT_NO_PWD"); // 销售产品码。单笔无密转账固定为 TRANS_ACCOUNT_NO_PWD
54   - model.setBizScene("DIRECT_TRANSFER"); // 业务场景 单笔无密转账固定为 DIRECT_TRANSFER
55   - model.setBusinessParams(JsonUtils.toJsonString(reqDTO.getChannelExtras()));
56   - PayTransferTypeEnum transferType = PayTransferTypeEnum.ofType(reqDTO.getType());
57   - switch(transferType) {
58   - case WX_BALANCE:
59   - case WALLET_BALANCE: {
60   - log.error("[doUnifiedTransfer],支付宝转账不支持的转账类型{}", transferType);
61   - throw new UnsupportedOperationException(String.format("支付宝转账不支持转账类型: %s",transferType.getName()));
62   - }
63   - // TODO @jason:是不是不用传递 transferType 参数哈?因为应该已经明确是支付宝啦?
64   - case ALIPAY_BALANCE: {
65   - // ② 个性化的参数
66   - Participant payeeInfo = new Participant();
67   - payeeInfo.setIdentityType("ALIPAY_LOGON_ID");
68   - String logonId = MapUtil.getStr(reqDTO.getPayeeInfo(), "ALIPAY_LOGON_ID");
69   - if (StrUtil.isEmpty(logonId)) {
70   - throw exception0(BAD_REQUEST.getCode(), "支付包登录 ID 不能为空");
71   - }
72   - String accountName = MapUtil.getStr(reqDTO.getPayeeInfo(), "ALIPAY_ACCOUNT_NAME");
73   - if (StrUtil.isEmpty(accountName)) {
74   - throw exception0(BAD_REQUEST.getCode(), "支付包账户名称不能为空");
75   - }
76   - payeeInfo.setIdentity(logonId); // 支付宝登录号
77   - payeeInfo.setName(accountName); // 支付宝账号姓名
78   - model.setPayeeInfo(payeeInfo);
79   - // 1.2 构建 AlipayFundTransUniTransferRequest
80   - AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
81   - request.setBizModel(model);
82   - // 执行请求
83   - AlipayFundTransUniTransferResponse response = client.certificateExecute(request);
84   - // 处理结果
85   - if (!response.isSuccess()) {
86   - // 当出现 SYSTEM_ERROR, 转账可能成功也可能失败。 返回 WAIT 状态. 后续 job 会轮询
87   - if (ObjectUtils.equalsAny(response.getSubCode(), "SYSTEM_ERROR", "ACQ.SYSTEM_ERROR")) {
88   - return PayTransferRespDTO.waitingOf(null, reqDTO.getOutTransferNo(), response);
89   - }
90   - return PayTransferRespDTO.closedOf(response.getSubCode(), response.getSubMsg(),
91   - reqDTO.getOutTransferNo(), response);
92   - }
93   - return PayTransferRespDTO.successOf(response.getOrderId(), parseTime(response.getTransDate()),
94   - response.getOutBizNo(), response);
95   - }
96   - case BANK_CARD: {
97   - Participant payeeInfo = new Participant();
98   - payeeInfo.setIdentityType("BANKCARD_ACCOUNT");
99   - throw new UnsupportedOperationException("待实现");
100   - }
101   - default: {
102   - throw new IllegalStateException("不正确的转账类型: " + transferType);
103   - }
104   - }
105   - }
106   -
107   -}
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java
... ... @@ -3,8 +3,6 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
3 3 import cn.hutool.http.Method;
4 4 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
5 5 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
6   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
7   -import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
8 6 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
9 7 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
10 8 import com.alipay.api.AlipayApiException;
... ... @@ -57,9 +55,4 @@ public class AlipayWapPayClient extends AbstractAlipayPayClient {
57 55 return PayOrderRespDTO.waitingOf(displayMode, response.getBody(),
58 56 reqDTO.getOutTradeNo(), response);
59 57 }
60   -
61   - @Override
62   - public PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
63   - throw new UnsupportedOperationException("支付宝【Wap 网站】不支持转账操作");
64   - }
65 58 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java
... ... @@ -28,9 +28,6 @@ public enum PayChannelEnum {
28 28 ALIPAY_APP("alipay_app", "支付宝App 支付", AlipayPayClientConfig.class),
29 29 ALIPAY_QR("alipay_qr", "支付宝扫码支付", AlipayPayClientConfig.class),
30 30 ALIPAY_BAR("alipay_bar", "支付宝条码支付", AlipayPayClientConfig.class),
31   - // TODO @jason:是不是按照微信聊的,合并回 ALIPAY_PC;因为支付宝、微信都是多种支付方式,选择其中的一种即可;
32   - ALIPAY_TRANSFER("alipay_transfer", "支付宝转账", AlipayPayClientConfig.class),
33   -
34 31 MOCK("mock", "模拟支付", NonePayClientConfig.class),
35 32  
36 33 WALLET("wallet", "钱包支付", NonePayClientConfig.class);
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/transfer/PayTransferTypeEnum.java
... ... @@ -34,8 +34,7 @@ public enum PayTransferTypeEnum implements IntArrayValuable {
34 34 return ARRAYS;
35 35 }
36 36  
37   - // TODO @jason:是不是 typeOf 更符合预期哈?
38   - public static PayTransferTypeEnum ofType(Integer type) {
  37 + public static PayTransferTypeEnum typeOf(Integer type) {
39 38 return ArrayUtil.firstMatch(item -> item.getType().equals(type), values());
40 39 }
41 40  
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoTransferServiceImpl.java
... ... @@ -66,7 +66,7 @@ public class PayDemoTransferServiceImpl implements PayDemoTransferService {
66 66  
67 67 // TODO @jason:可以参考 AppBrokerageWithdrawCreateReqVO 搞下字段哈,进行校验
68 68 private void validatePayeeInfo(Integer transferType, Map<String, String> payeeInfo) {
69   - PayTransferTypeEnum transferTypeEnum = ofType(transferType);
  69 + PayTransferTypeEnum transferTypeEnum = typeOf(transferType);
70 70 switch (transferTypeEnum) {
71 71 case ALIPAY_BALANCE: {
72 72 if (StrUtil.isEmpty(MapUtil.getStr(payeeInfo, ALIPAY_LOGON_ID))) {
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceImpl.java
... ... @@ -214,11 +214,11 @@ public class PayTransferServiceImpl implements PayTransferService {
214 214 }
215 215  
216 216 private void validateChannelCodeAndTypeMatch(String channelCode, Integer type) {
217   - PayTransferTypeEnum transferType = PayTransferTypeEnum.ofType(type);
  217 + PayTransferTypeEnum transferType = PayTransferTypeEnum.typeOf(type);
218 218 PayChannelEnum payChannel = PayChannelEnum.getByCode(channelCode);
219 219 switch (transferType) {
220 220 case ALIPAY_BALANCE: {
221   - if (payChannel != PayChannelEnum.ALIPAY_TRANSFER) {
  221 + if (!payChannel.getCode().startsWith("alipay")) {
222 222 throw exception(PAY_TRANSFER_TYPE_AND_CHANNEL_NOT_MATCH);
223 223 }
224 224 break;
... ...