Commit 626bd0bd55eb5bd774ad54cabac0fae141c2bf72

Authored by jason
1 parent 86598dd1

转账 - code review 修改

Showing 24 changed files with 323 additions and 204 deletions
sql/mysql/pay_wallet.sql
@@ -9,17 +9,18 @@ CREATE TABLE `pay_transfer` @@ -9,17 +9,18 @@ CREATE TABLE `pay_transfer`
9 `app_id` bigint NOT NULL COMMENT '应用编号', 9 `app_id` bigint NOT NULL COMMENT '应用编号',
10 `channel_id` bigint NOT NULL COMMENT '转账渠道编号', 10 `channel_id` bigint NOT NULL COMMENT '转账渠道编号',
11 `channel_code` varchar(32) NOT NULL COMMENT '转账渠道编码', 11 `channel_code` varchar(32) NOT NULL COMMENT '转账渠道编码',
12 - `merchant_order_id` varchar(64) NOT NULL COMMENT '商户订单编号', 12 + `merchant_transfer_id` varchar(64) NOT NULL COMMENT '商户转账单编号',
13 `type` int NOT NULL COMMENT '类型', 13 `type` int NOT NULL COMMENT '类型',
14 `status` tinyint NOT NULL COMMENT '转账状态', 14 `status` tinyint NOT NULL COMMENT '转账状态',
15 `success_time` datetime NULL COMMENT '转账成功时间', 15 `success_time` datetime NULL COMMENT '转账成功时间',
16 `price` int NOT NULL COMMENT '转账金额,单位:分', 16 `price` int NOT NULL COMMENT '转账金额,单位:分',
17 `subject` varchar(512) NOT NULL COMMENT '转账标题', 17 `subject` varchar(512) NOT NULL COMMENT '转账标题',
18 `alipay_logon_id` varchar(64) NULL COMMENT '支付宝登录号', 18 `alipay_logon_id` varchar(64) NULL COMMENT '支付宝登录号',
19 - `alipay_account_name` varchar(64) NULL COMMENT '支付宝账号名称',  
20 - `openid` varchar(64) NULL COMMENT '微信 openId',  
21 - `wx_account_name` varchar(64) NULL COMMENT '微信账号名称',  
22 - `notify_url` varchar(64) NULL COMMENT '异步通知商户地址', 19 + `alipay_account_name` varchar(64) NULL COMMENT '支付宝账号名称',
  20 + `openid` varchar(64) NULL COMMENT '微信 openId',
  21 + `wx_account_name` varchar(64) NULL COMMENT '微信账号名称',
  22 + `notify_url` varchar(1024) NOT NULL COMMENT '异步通知商户地址',
  23 + `user_ip` varchar(50) NOT NULL COMMENT '用户 IP',
23 `channel_extras` varchar(512) NULL DEFAULT NULL COMMENT '渠道的额外参数', 24 `channel_extras` varchar(512) NULL DEFAULT NULL COMMENT '渠道的额外参数',
24 `channel_transfer_no` varchar(64) NULL DEFAULT NULL COMMENT '渠道转账单号', 25 `channel_transfer_no` varchar(64) NULL DEFAULT NULL COMMENT '渠道转账单号',
25 `channel_error_code` varchar(128) NULL DEFAULT NULL COMMENT '调用渠道的错误码', 26 `channel_error_code` varchar(128) NULL DEFAULT NULL COMMENT '调用渠道的错误码',
@@ -64,6 +65,7 @@ DROP TABLE IF EXISTS `pay_demo_transfer`; @@ -64,6 +65,7 @@ DROP TABLE IF EXISTS `pay_demo_transfer`;
64 CREATE TABLE `pay_demo_transfer` ( 65 CREATE TABLE `pay_demo_transfer` (
65 `id` bigint NOT NULL AUTO_INCREMENT COMMENT '订单编号', 66 `id` bigint NOT NULL AUTO_INCREMENT COMMENT '订单编号',
66 `user_id` bigint UNSIGNED NOT NULL COMMENT '用户编号', 67 `user_id` bigint UNSIGNED NOT NULL COMMENT '用户编号',
  68 + `app_id` bigint NOT NULL COMMENT '应用编号',
67 `price` int NOT NULL COMMENT '转账金额,单位:分', 69 `price` int NOT NULL COMMENT '转账金额,单位:分',
68 `type` int NOT NULL COMMENT '转账类型', 70 `type` int NOT NULL COMMENT '转账类型',
69 `alipay_logon_id` varchar(64) NULL COMMENT '支付宝登录号', 71 `alipay_logon_id` varchar(64) NULL COMMENT '支付宝登录号',
@@ -81,7 +83,7 @@ CREATE TABLE `pay_demo_transfer` ( @@ -81,7 +83,7 @@ CREATE TABLE `pay_demo_transfer` (
81 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 83 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
82 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', 84 `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
83 PRIMARY KEY (`id`) USING BTREE 85 PRIMARY KEY (`id`) USING BTREE
84 -) ENGINE = InnoDB COMMENT = '示例业务转账订单\n'; 86 +) ENGINE = InnoDB COMMENT = '示例业务转账订单';
85 87
86 88
87 ALTER TABLE `pay_channel` 89 ALTER TABLE `pay_channel`
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/transfer/PayTransferRespDTO.java
@@ -29,7 +29,7 @@ public class PayTransferRespDTO { @@ -29,7 +29,7 @@ public class PayTransferRespDTO {
29 /** 29 /**
30 * 支付渠道编号 30 * 支付渠道编号
31 */ 31 */
32 - private String channelOrderNo; 32 + private String channelTransferNo;
33 33
34 /** 34 /**
35 * 支付成功时间 35 * 支付成功时间
@@ -57,7 +57,7 @@ public class PayTransferRespDTO { @@ -57,7 +57,7 @@ public class PayTransferRespDTO {
57 String outTransferNo, Object rawData) { 57 String outTransferNo, Object rawData) {
58 PayTransferRespDTO respDTO = new PayTransferRespDTO(); 58 PayTransferRespDTO respDTO = new PayTransferRespDTO();
59 respDTO.status = PayTransferStatusRespEnum.WAITING.getStatus(); 59 respDTO.status = PayTransferStatusRespEnum.WAITING.getStatus();
60 - respDTO.channelOrderNo = channelOrderNo; 60 + respDTO.channelTransferNo = channelOrderNo;
61 respDTO.outTransferNo = outTransferNo; 61 respDTO.outTransferNo = outTransferNo;
62 respDTO.rawData = rawData; 62 respDTO.rawData = rawData;
63 return respDTO; 63 return respDTO;
@@ -85,7 +85,7 @@ public class PayTransferRespDTO { @@ -85,7 +85,7 @@ public class PayTransferRespDTO {
85 String outTransferNo, Object rawData) { 85 String outTransferNo, Object rawData) {
86 PayTransferRespDTO respDTO = new PayTransferRespDTO(); 86 PayTransferRespDTO respDTO = new PayTransferRespDTO();
87 respDTO.status = PayTransferStatusRespEnum.SUCCESS.getStatus(); 87 respDTO.status = PayTransferStatusRespEnum.SUCCESS.getStatus();
88 - respDTO.channelOrderNo = channelTransferNo; 88 + respDTO.channelTransferNo = channelTransferNo;
89 respDTO.successTime = successTime; 89 respDTO.successTime = successTime;
90 // 相对通用的字段 90 // 相对通用的字段
91 respDTO.outTransferNo = outTransferNo; 91 respDTO.outTransferNo = outTransferNo;
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/transfer/PayTransferUnifiedReqDTO.java
@@ -6,6 +6,7 @@ import lombok.Data; @@ -6,6 +6,7 @@ import lombok.Data;
6 import org.hibernate.validator.constraints.Length; 6 import org.hibernate.validator.constraints.Length;
7 7
8 import javax.validation.constraints.Min; 8 import javax.validation.constraints.Min;
  9 +import javax.validation.constraints.NotBlank;
9 import javax.validation.constraints.NotEmpty; 10 import javax.validation.constraints.NotEmpty;
10 import javax.validation.constraints.NotNull; 11 import javax.validation.constraints.NotNull;
11 import java.util.Map; 12 import java.util.Map;
@@ -50,27 +51,23 @@ public class PayTransferUnifiedReqDTO { @@ -50,27 +51,23 @@ public class PayTransferUnifiedReqDTO {
50 @Length(max = 128, message = "转账标题不能超过 128") 51 @Length(max = 128, message = "转账标题不能超过 128")
51 private String title; 52 private String title;
52 53
53 - /**  
54 - * 收款方信息。  
55 - *  
56 - * 转账类型 {@link #type} 不同,收款方信息不同  
57 - */  
58 - @NotEmpty(message = "收款方信息 不能为空")  
59 - private Map<String, String> payeeInfo;  
60 54
61 /** 55 /**
62 * 支付宝登录号 56 * 支付宝登录号
63 */ 57 */
  58 + @NotBlank(message = "支付宝登录号不能为空", groups = {PayTransferTypeEnum.Alipay.class})
64 private String alipayLogonId; 59 private String alipayLogonId;
65 60
66 /** 61 /**
67 * 支付宝账号名称 62 * 支付宝账号名称
68 */ 63 */
  64 + @NotBlank(message = "支付宝账号名称不能为空", groups = {PayTransferTypeEnum.Alipay.class})
69 private String alipayAccountName; 65 private String alipayAccountName;
70 66
71 /** 67 /**
72 * 微信 openId 68 * 微信 openId
73 */ 69 */
  70 + @NotBlank(message = "微信 openId 不能为空", groups = {PayTransferTypeEnum.WxPay.class})
74 private String openid; 71 private String openid;
75 72
76 /** 73 /**
@@ -82,5 +79,4 @@ public class PayTransferUnifiedReqDTO { @@ -82,5 +79,4 @@ public class PayTransferUnifiedReqDTO {
82 * 支付渠道的额外参数 79 * 支付渠道的额外参数
83 */ 80 */
84 private Map<String, String> channelExtras; 81 private Map<String, String> channelExtras;
85 -  
86 } 82 }
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java
@@ -11,6 +11,7 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReq @@ -11,6 +11,7 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReq
11 import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO; 11 import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
12 import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO; 12 import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
13 import cn.iocoder.yudao.framework.pay.core.client.exception.PayException; 13 import cn.iocoder.yudao.framework.pay.core.client.exception.PayException;
  14 +import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
14 import lombok.extern.slf4j.Slf4j; 15 import lombok.extern.slf4j.Slf4j;
15 16
16 import java.util.Map; 17 import java.util.Map;
@@ -185,7 +186,7 @@ public abstract class AbstractPayClient&lt;Config extends PayClientConfig&gt; implemen @@ -185,7 +186,7 @@ public abstract class AbstractPayClient&lt;Config extends PayClientConfig&gt; implemen
185 186
186 @Override 187 @Override
187 public final PayTransferRespDTO unifiedTransfer(PayTransferUnifiedReqDTO reqDTO) { 188 public final PayTransferRespDTO unifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
188 - ValidationUtils.validate(reqDTO); 189 + validatePayTransferReqDTO(reqDTO);
189 PayTransferRespDTO resp; 190 PayTransferRespDTO resp;
190 try{ 191 try{
191 resp = doUnifiedTransfer(reqDTO); 192 resp = doUnifiedTransfer(reqDTO);
@@ -199,6 +200,22 @@ public abstract class AbstractPayClient&lt;Config extends PayClientConfig&gt; implemen @@ -199,6 +200,22 @@ public abstract class AbstractPayClient&lt;Config extends PayClientConfig&gt; implemen
199 } 200 }
200 return resp; 201 return resp;
201 } 202 }
  203 + private void validatePayTransferReqDTO(PayTransferUnifiedReqDTO reqDTO) {
  204 + PayTransferTypeEnum transferType = PayTransferTypeEnum.typeOf(reqDTO.getType());
  205 + switch (transferType) {
  206 + case ALIPAY_BALANCE: {
  207 + ValidationUtils.validate(reqDTO, PayTransferTypeEnum.Alipay.class);
  208 + break;
  209 + }
  210 + case WX_BALANCE: {
  211 + ValidationUtils.validate(reqDTO, PayTransferTypeEnum.WxPay.class);
  212 + break;
  213 + }
  214 + default: {
  215 + throw new UnsupportedOperationException("待实现");
  216 + }
  217 + }
  218 + }
202 219
203 protected abstract PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) 220 protected abstract PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO)
204 throws Throwable; 221 throws Throwable;
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java
@@ -44,6 +44,8 @@ import java.util.function.Supplier; @@ -44,6 +44,8 @@ import java.util.function.Supplier;
44 44
45 import static cn.hutool.core.date.DatePattern.NORM_DATETIME_FORMATTER; 45 import static cn.hutool.core.date.DatePattern.NORM_DATETIME_FORMATTER;
46 import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST; 46 import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
  47 +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.NOT_IMPLEMENTED;
  48 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
47 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0; 49 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; 50 import static cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig.MODE_CERTIFICATE;
49 51
@@ -227,9 +229,8 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa @@ -227,9 +229,8 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa
227 protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) throws AlipayApiException { 229 protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) throws AlipayApiException {
228 // 1.1 校验公钥类型 必须使用公钥证书模式 230 // 1.1 校验公钥类型 必须使用公钥证书模式
229 if (!Objects.equals(config.getMode(), MODE_CERTIFICATE)) { 231 if (!Objects.equals(config.getMode(), MODE_CERTIFICATE)) {
230 - throw new IllegalStateException("支付宝单笔转账必须使用公钥证书模式"); 232 + throw exception0(BAD_REQUEST.getCode(),"支付宝单笔转账必须使用公钥证书模式");
231 } 233 }
232 -  
233 // 1.2 构建 AlipayFundTransUniTransferModel 234 // 1.2 构建 AlipayFundTransUniTransferModel
234 AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel(); 235 AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
235 // ① 通用的参数 236 // ① 通用的参数
@@ -247,16 +248,8 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa @@ -247,16 +248,8 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa
247 // ② 个性化的参数 248 // ② 个性化的参数
248 Participant payeeInfo = new Participant(); 249 Participant payeeInfo = new Participant();
249 payeeInfo.setIdentityType("ALIPAY_LOGON_ID"); 250 payeeInfo.setIdentityType("ALIPAY_LOGON_ID");
250 - String logonId = MapUtil.getStr(reqDTO.getPayeeInfo(), "ALIPAY_LOGON_ID");  
251 - if (StrUtil.isEmpty(logonId)) {  
252 - throw exception0(BAD_REQUEST.getCode(), "支付包登录 ID 不能为空");  
253 - }  
254 - String accountName = MapUtil.getStr(reqDTO.getPayeeInfo(), "ALIPAY_ACCOUNT_NAME");  
255 - if (StrUtil.isEmpty(accountName)) {  
256 - throw exception0(BAD_REQUEST.getCode(), "支付包账户名称不能为空");  
257 - }  
258 - payeeInfo.setIdentity(logonId); // 支付宝登录号  
259 - payeeInfo.setName(accountName); // 支付宝账号姓名 251 + payeeInfo.setIdentity(reqDTO.getAlipayLogonId()); // 支付宝登录号
  252 + payeeInfo.setName(reqDTO.getAlipayAccountName()); // 支付宝账号姓名
260 model.setPayeeInfo(payeeInfo); 253 model.setPayeeInfo(payeeInfo);
261 // 1.3 构建 AlipayFundTransUniTransferRequest 254 // 1.3 构建 AlipayFundTransUniTransferRequest
262 AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest(); 255 AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
@@ -279,10 +272,10 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa @@ -279,10 +272,10 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa
279 Participant payeeInfo = new Participant(); 272 Participant payeeInfo = new Participant();
280 payeeInfo.setIdentityType("BANKCARD_ACCOUNT"); 273 payeeInfo.setIdentityType("BANKCARD_ACCOUNT");
281 // TODO 待实现 274 // TODO 待实现
282 - throw new UnsupportedOperationException("待实现"); 275 + throw exception(NOT_IMPLEMENTED);
283 } 276 }
284 default: { 277 default: {
285 - throw new IllegalStateException("不正确的转账类型: " + transferType); 278 + throw exception0(BAD_REQUEST.getCode(),"不正确的转账类型: {}",transferType);
286 } 279 }
287 } 280 }
288 } 281 }
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java
@@ -62,4 +62,7 @@ public enum PayChannelEnum { @@ -62,4 +62,7 @@ public enum PayChannelEnum {
62 return ArrayUtil.firstMatch(o -> o.getCode().equals(code), values()); 62 return ArrayUtil.firstMatch(o -> o.getCode().equals(code), values());
63 } 63 }
64 64
  65 + public static boolean isAlipay(String channelCode) {
  66 + return channelCode != null && channelCode.startsWith("alipay");
  67 + }
65 } 68 }
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/transfer/PayTransferTypeEnum.java
@@ -21,8 +21,11 @@ public enum PayTransferTypeEnum implements IntArrayValuable { @@ -21,8 +21,11 @@ public enum PayTransferTypeEnum implements IntArrayValuable {
21 BANK_CARD(3, "银行卡"), 21 BANK_CARD(3, "银行卡"),
22 WALLET_BALANCE(4, "钱包余额"); 22 WALLET_BALANCE(4, "钱包余额");
23 23
24 - public static final String ALIPAY_LOGON_ID = "ALIPAY_LOGON_ID";  
25 - public static final String ALIPAY_ACCOUNT_NAME = "ALIPAY_ACCOUNT_NAME"; 24 + public interface WxPay {
  25 + }
  26 +
  27 + public interface Alipay {
  28 + }
26 29
27 private final Integer type; 30 private final Integer type;
28 private final String name; 31 private final String name;
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferCreateReqDTO.java
@@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferTypeEnum; @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferTypeEnum;
5 import lombok.Data; 5 import lombok.Data;
6 6
7 import javax.validation.constraints.Min; 7 import javax.validation.constraints.Min;
  8 +import javax.validation.constraints.NotBlank;
8 import javax.validation.constraints.NotEmpty; 9 import javax.validation.constraints.NotEmpty;
9 import javax.validation.constraints.NotNull; 10 import javax.validation.constraints.NotNull;
10 import java.util.Map; 11 import java.util.Map;
@@ -21,6 +22,17 @@ public class PayTransferCreateReqDTO { @@ -21,6 +22,17 @@ public class PayTransferCreateReqDTO {
21 @NotNull(message = "应用编号不能为空") 22 @NotNull(message = "应用编号不能为空")
22 private Long appId; 23 private Long appId;
23 24
  25 + @NotEmpty(message = "转账渠道不能为空")
  26 + private String channelCode;
  27 +
  28 + /**
  29 + * 转账渠道的额外参数
  30 + */
  31 + private Map<String, String> channelExtras;
  32 +
  33 + @NotEmpty(message = "用户 IP 不能为空")
  34 + private String userIp;
  35 +
24 /** 36 /**
25 * 类型 37 * 类型
26 */ 38 */
@@ -28,11 +40,12 @@ public class PayTransferCreateReqDTO { @@ -28,11 +40,12 @@ public class PayTransferCreateReqDTO {
28 @InEnum(PayTransferTypeEnum.class) 40 @InEnum(PayTransferTypeEnum.class)
29 private Integer type; 41 private Integer type;
30 42
  43 +
31 /** 44 /**
32 - * 商户订单编号 45 + * 商户转账单编号
33 */ 46 */
34 - @NotEmpty(message = "商户订单编号不能为空")  
35 - private String merchantOrderId; 47 + @NotEmpty(message = "商户转账单编号能为空")
  48 + private String merchantTransferId;
36 49
37 /** 50 /**
38 * 转账金额,单位:分 51 * 转账金额,单位:分
@@ -45,9 +58,21 @@ public class PayTransferCreateReqDTO { @@ -45,9 +58,21 @@ public class PayTransferCreateReqDTO {
45 * 转账标题 58 * 转账标题
46 */ 59 */
47 @NotEmpty(message = "转账标题不能为空") 60 @NotEmpty(message = "转账标题不能为空")
48 - private String title; 61 + private String subject;
49 62
50 @NotEmpty(message = "收款方信息不能为空") 63 @NotEmpty(message = "收款方信息不能为空")
51 private Map<String, String> payeeInfo; 64 private Map<String, String> payeeInfo;
52 65
  66 + @NotBlank(message = "支付宝登录号不能为空", groups = {PayTransferTypeEnum.Alipay.class})
  67 + private String alipayLogonId;
  68 +
  69 + @NotBlank(message = "支付宝登录号不能为空", groups = {PayTransferTypeEnum.Alipay.class})
  70 + private String alipayAccountName;
  71 +
  72 + // ========== 微信转账相关字段 ==========
  73 + @NotBlank(message = "微信 openId 不能为空", groups = {PayTransferTypeEnum.WxPay.class})
  74 + private String openid;
  75 +
  76 + private String wxAccountName;
  77 +
53 } 78 }
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java
@@ -67,11 +67,11 @@ public interface ErrorCodeConstants { @@ -67,11 +67,11 @@ public interface ErrorCodeConstants {
67 ErrorCode PAY_TRANSFER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1_007_009_000, "发起转账报错,错误码:{},错误提示:{}"); 67 ErrorCode PAY_TRANSFER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1_007_009_000, "发起转账报错,错误码:{},错误提示:{}");
68 ErrorCode PAY_TRANSFER_NOT_FOUND = new ErrorCode(1_007_009_001, "转账交易单不存在"); 68 ErrorCode PAY_TRANSFER_NOT_FOUND = new ErrorCode(1_007_009_001, "转账交易单不存在");
69 ErrorCode PAY_TRANSFER_STATUS_IS_SUCCESS = new ErrorCode(1_007_009_002, "转账单已成功转账"); 69 ErrorCode PAY_TRANSFER_STATUS_IS_SUCCESS = new ErrorCode(1_007_009_002, "转账单已成功转账");
70 - ErrorCode PAY_TRANSFER_STATUS_IS_NOT_WAITING = new ErrorCode(1_007_009_003, "转账单不处于待转账");  
71 - ErrorCode PAY_TRANSFER_STATUS_IS_NOT_PENDING = new ErrorCode(1_007_009_004, "转账单不处于待转账或转账中");  
72 - ErrorCode PAY_TRANSFER_EXTENSION_NOT_FOUND = new ErrorCode(1_007_009_005, "转账交易拓展单不存在");  
73 - ErrorCode PAY_TRANSFER_TYPE_AND_CHANNEL_NOT_MATCH = new ErrorCode(1_007_009_006, "转账类型和转账渠道不匹配");  
74 - ErrorCode PAY_TRANSFER_EXTENSION_STATUS_IS_NOT_PENDING = new ErrorCode(1_007_009_007, "转账拓展单不处于待转账或转账中"); 70 + ErrorCode PAY_TRANSFER_EXISTS = new ErrorCode(1_007_009_003, "已经存在转账单");
  71 + ErrorCode PAY_MERCHANT_TRANSFER_EXISTS = new ErrorCode(1_007_009_004, "该笔业务的转账已经存在,请查询相关状态");
  72 + ErrorCode PAY_TRANSFER_STATUS_IS_NOT_WAITING = new ErrorCode(1_007_009_005, "转账单不处于待转账");
  73 + ErrorCode PAY_TRANSFER_STATUS_IS_NOT_PENDING = new ErrorCode(1_007_009_006, "转账单不处于待转账或转账中");
  74 + ErrorCode PAY_TRANSFER_TYPE_AND_CHANNEL_NOT_MATCH = new ErrorCode(1_007_009_008, "转账类型和转账渠道不匹配");
75 75
76 // ========== 示例订单 1-007-900-000 ========== 76 // ========== 示例订单 1-007-900-000 ==========
77 ErrorCode DEMO_ORDER_NOT_FOUND = new ErrorCode(1_007_900_000, "示例订单不存在"); 77 ErrorCode DEMO_ORDER_NOT_FOUND = new ErrorCode(1_007_900_000, "示例订单不存在");
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/transfer/PayTransferStatusEnum.java
@@ -49,7 +49,7 @@ public enum PayTransferStatusEnum { @@ -49,7 +49,7 @@ public enum PayTransferStatusEnum {
49 * @param status 状态 49 * @param status 状态
50 */ 50 */
51 public static boolean isPendingStatus(Integer status) { 51 public static boolean isPendingStatus(Integer status) {
52 - return Objects.equals(status, WAITING.getStatus()) || Objects.equals(status, IN_PROGRESS.status); 52 + return Objects.equals(status, WAITING.getStatus()) || Objects.equals(status, IN_PROGRESS.getStatus());
53 } 53 }
54 54
55 } 55 }
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/transfer/PayTransferTypeEnum.java
@@ -21,8 +21,11 @@ public enum PayTransferTypeEnum implements IntArrayValuable { @@ -21,8 +21,11 @@ public enum PayTransferTypeEnum implements IntArrayValuable {
21 BANK_CARD(3, "银行卡"), 21 BANK_CARD(3, "银行卡"),
22 WALLET_BALANCE(4, "钱包余额"); 22 WALLET_BALANCE(4, "钱包余额");
23 23
24 - public static final String ALIPAY_LOGON_ID = "ALIPAY_LOGON_ID";  
25 - public static final String ALIPAY_ACCOUNT_NAME = "ALIPAY_ACCOUNT_NAME"; 24 + public interface WxPay {
  25 + }
  26 +
  27 + public interface Alipay {
  28 + }
26 29
27 private final Integer type; 30 private final Integer type;
28 private final String name; 31 private final String name;
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/vo/transfer/PayDemoTransferCreateReqVO.java
@@ -28,13 +28,13 @@ public class PayDemoTransferCreateReqVO { @@ -28,13 +28,13 @@ public class PayDemoTransferCreateReqVO {
28 @Min(value = 1, message = "转账金额必须大于零") 28 @Min(value = 1, message = "转账金额必须大于零")
29 private Integer price; 29 private Integer price;
30 30
31 - // ========== 支付宝,微信转账相关字段 ========== 31 + // ========== 支付宝转账相关字段 ==========
32 @Schema(description = "支付宝登录号,支持邮箱和手机号格式", example = "test1@@sandbox.com") 32 @Schema(description = "支付宝登录号,支持邮箱和手机号格式", example = "test1@@sandbox.com")
33 @NotBlank(message = "支付宝登录号不能为空", groups = {Alipay.class}) 33 @NotBlank(message = "支付宝登录号不能为空", groups = {Alipay.class})
34 private String alipayLogonId; 34 private String alipayLogonId;
35 35
36 @Schema(description = "支付宝账号名称", example = "test1") 36 @Schema(description = "支付宝账号名称", example = "test1")
37 - @NotBlank(message = "支付宝登录号不能为空", groups = {Alipay.class}) 37 + @NotBlank(message = "支付宝账号名称不能为空", groups = {Alipay.class})
38 private String alipayAccountName; 38 private String alipayAccountName;
39 39
40 // ========== 微信转账相关字段 ========== 40 // ========== 微信转账相关字段 ==========
@@ -42,7 +42,7 @@ public class PayDemoTransferCreateReqVO { @@ -42,7 +42,7 @@ public class PayDemoTransferCreateReqVO {
42 @NotBlank(message = "微信 openId 不能为空", groups = {WxPay.class}) 42 @NotBlank(message = "微信 openId 不能为空", groups = {WxPay.class})
43 private String openid; 43 private String openid;
44 44
45 - @Schema(description = "微信账号名称", example = "oLefc4g5Gjxxxxxx") 45 + @Schema(description = "微信账号名称", example = "test2")
46 private String wxAccountName; 46 private String wxAccountName;
47 47
48 // ========== 转账到银行卡和钱包相关字段 待补充 ========== 48 // ========== 转账到银行卡和钱包相关字段 待补充 ==========
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/PayTransferController.java
1 package cn.iocoder.yudao.module.pay.controller.admin.transfer; 1 package cn.iocoder.yudao.module.pay.controller.admin.transfer;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 -import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferSubmitReqVO;  
5 -import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferSubmitRespVO; 4 +import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateReqVO;
  5 +import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateRespVO;
  6 +import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
6 import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService; 7 import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService;
7 import io.swagger.v3.oas.annotations.Operation; 8 import io.swagger.v3.oas.annotations.Operation;
8 import io.swagger.v3.oas.annotations.tags.Tag; 9 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -27,12 +28,12 @@ public class PayTransferController { @@ -27,12 +28,12 @@ public class PayTransferController {
27 @Resource 28 @Resource
28 private PayTransferService payTransferService; 29 private PayTransferService payTransferService;
29 30
30 - @PostMapping("/submit")  
31 - @Operation(summary = "提交转账订单") 31 + @PostMapping("/initiate")
  32 + @Operation(summary = "发起转账")
32 // TODO @jason:权限的设置, 管理后台页面加的时候加一下 33 // TODO @jason:权限的设置, 管理后台页面加的时候加一下
33 - public CommonResult<PayTransferSubmitRespVO> submitPayTransfer(@Valid @RequestBody PayTransferSubmitReqVO reqVO) {  
34 - PayTransferSubmitRespVO respVO = payTransferService.submitTransfer(reqVO, getClientIP());  
35 - return success(respVO); 34 + public CommonResult<PayTransferCreateRespVO> initiatePayTransfer(@Valid @RequestBody PayTransferCreateReqVO reqVO) {
  35 + PayTransferDO payTransfer = payTransferService.initiateTransfer(reqVO, getClientIP());
  36 + return success(new PayTransferCreateRespVO().setId(payTransfer.getId()).setStatus(payTransfer.getStatus()));
36 } 37 }
37 38
38 } 39 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferCreateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.pay.controller.admin.transfer.vo;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
  4 +import cn.iocoder.yudao.framework.common.validation.InEnum;
  5 +import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO;
  6 +import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferTypeEnum;
  7 +import io.swagger.v3.oas.annotations.media.Schema;
  8 +import lombok.Data;
  9 +
  10 +import javax.validation.Validator;
  11 +import javax.validation.constraints.Min;
  12 +import javax.validation.constraints.NotBlank;
  13 +import javax.validation.constraints.NotEmpty;
  14 +import javax.validation.constraints.NotNull;
  15 +import java.util.Map;
  16 +
  17 +@Schema(description = "管理后台 - 发起转账 Request VO")
  18 +@Data
  19 +public class PayTransferCreateReqVO {
  20 +
  21 + @Schema(description = "应用编号不能为空", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  22 + @NotNull(message = "应用编号不能为空")
  23 + private Long appId;
  24 +
  25 + @Schema(description = "商户转账单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  26 + @NotNull(message = "商户转账单编号不能为空")
  27 + private String merchantTransferId;
  28 +
  29 + @Schema(description = "转账类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  30 + @NotNull(message = "转账类型不能为空")
  31 + @InEnum(PayTransferTypeEnum.class)
  32 + private Integer type;
  33 +
  34 + @Schema(description = "转账渠道", requiredMode = Schema.RequiredMode.REQUIRED, example = "alipay_pc")
  35 + @NotEmpty(message = "转账渠道不能为空")
  36 + private String channelCode;
  37 +
  38 + @Min(value = 1, message = "转账金额必须大于零")
  39 + @NotNull(message = "转账金额不能为空")
  40 + private Integer price;
  41 +
  42 + @Schema(description = "转账标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "示例转账")
  43 + @NotEmpty(message = "转账标题不能为空")
  44 + private String subject;
  45 +
  46 + @Schema(description = "支付宝登录号", example = "test1@sandbox.com")
  47 + @NotBlank(message = "支付宝登录号不能为空", groups = {PayTransferTypeEnum.Alipay.class})
  48 + private String alipayLogonId;
  49 +
  50 + @Schema(description = "支付宝账号名称", example = "test1")
  51 + @NotBlank(message = "支付宝账号名称不能为空", groups = {PayTransferTypeEnum.Alipay.class})
  52 + private String alipayAccountName;
  53 +
  54 + @Schema(description = "微信 openId", example = "oLefc4g5Gxx")
  55 + @NotBlank(message = "微信 openId 不能为空", groups = {PayTransferTypeEnum.WxPay.class})
  56 + private String openid;
  57 +
  58 + @Schema(description = "微信账号名称", example = "test2")
  59 + private String wxAccountName;
  60 +
  61 + @Schema(description = "转账渠道的额外参数")
  62 + private Map<String, String> channelExtras;
  63 +
  64 + public void validate(Validator validator) {
  65 + PayTransferTypeEnum transferType = PayTransferTypeEnum.typeOf(type);
  66 + switch (transferType) {
  67 + case ALIPAY_BALANCE: {
  68 + ValidationUtils.validate(validator, this, PayDemoTransferCreateReqVO.Alipay.class);
  69 + break;
  70 + }
  71 + case WX_BALANCE: {
  72 + ValidationUtils.validate(validator, this, PayDemoTransferCreateReqVO.WxPay.class);
  73 + break;
  74 + }
  75 + default: {
  76 + throw new UnsupportedOperationException("待实现");
  77 + }
  78 + }
  79 + }
  80 +
  81 +}
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferSubmitRespVO.java renamed to yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferCreateRespVO.java
@@ -3,9 +3,12 @@ package cn.iocoder.yudao.module.pay.controller.admin.transfer.vo; @@ -3,9 +3,12 @@ package cn.iocoder.yudao.module.pay.controller.admin.transfer.vo;
3 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
4 import lombok.Data; 4 import lombok.Data;
5 5
6 -@Schema(description = "管理后台 - 转账单提交 Response VO") 6 +@Schema(description = "管理后台 - 发起转账 Response VO")
7 @Data 7 @Data
8 -public class PayTransferSubmitRespVO { 8 +public class PayTransferCreateRespVO {
  9 +
  10 + @Schema(description = "转账单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  11 + private Long id;
9 12
10 @Schema(description = "转账状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") // 参见 PayTransferStatusEnum 枚举 13 @Schema(description = "转账状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") // 参见 PayTransferStatusEnum 枚举
11 private Integer status; 14 private Integer status;
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferSubmitReqVO.java deleted
1 -package cn.iocoder.yudao.module.pay.controller.admin.transfer.vo;  
2 -  
3 -import io.swagger.v3.oas.annotations.media.Schema;  
4 -import lombok.Data;  
5 -  
6 -import javax.validation.constraints.NotEmpty;  
7 -import javax.validation.constraints.NotNull;  
8 -import java.util.Map;  
9 -  
10 -@Schema(description = "管理后台 - 转账单提交 Request VO")  
11 -@Data  
12 -public class PayTransferSubmitReqVO {  
13 -  
14 - @Schema(description = "转账单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")  
15 - @NotNull(message = "转账单编号不能为空")  
16 - private Long id;  
17 -  
18 - @Schema(description = "转账渠道", requiredMode = Schema.RequiredMode.REQUIRED, example = "alipay_transfer")  
19 - @NotEmpty(message = "转账渠道不能为空")  
20 - private String channelCode;  
21 -  
22 - @Schema(description = "转账渠道的额外参数")  
23 - private Map<String, String> channelExtras;  
24 -  
25 -}  
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/transfer/PayTransferConvert.java
1 package cn.iocoder.yudao.module.pay.convert.transfer; 1 package cn.iocoder.yudao.module.pay.convert.transfer;
2 2
  3 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
3 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO; 4 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
4 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO; 5 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO;
  6 +import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateReqVO;
5 import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO; 7 import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
6 import org.mapstruct.Mapper; 8 import org.mapstruct.Mapper;
7 import org.mapstruct.Mapping; 9 import org.mapstruct.Mapping;
@@ -12,9 +14,13 @@ public interface PayTransferConvert { @@ -12,9 +14,13 @@ public interface PayTransferConvert {
12 14
13 PayTransferConvert INSTANCE = Mappers.getMapper(PayTransferConvert.class); 15 PayTransferConvert INSTANCE = Mappers.getMapper(PayTransferConvert.class);
14 16
15 - @Mapping(source = "title", target = "subject") // TODO @jason:是不是都改成 subject 完事呀?  
16 PayTransferDO convert(PayTransferCreateReqDTO dto); 17 PayTransferDO convert(PayTransferCreateReqDTO dto);
17 18
  19 + @Mapping(source = "subject", target = "title")
  20 + PayTransferUnifiedReqDTO convert2(PayTransferCreateReqDTO dto);
  21 +
  22 + PayTransferCreateReqDTO convert(PayTransferCreateReqVO vo);
  23 +
18 PayTransferCreateReqDTO convert(PayDemoTransferCreateReqVO vo); 24 PayTransferCreateReqDTO convert(PayDemoTransferCreateReqVO vo);
19 25
20 } 26 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletConvert.java
@@ -22,14 +22,10 @@ public interface PayWalletConvert { @@ -22,14 +22,10 @@ public interface PayWalletConvert {
22 22
23 PageResult<PayWalletRespVO> convertPage(PageResult<PayWalletDO> page); 23 PageResult<PayWalletRespVO> convertPage(PageResult<PayWalletDO> page);
24 24
25 - default PageResult<PayWalletRespVO> convertPage(PageResult<PayWalletDO> page, Map<Long, MemberUserRespDTO> userMap){ 25 + default PageResult<PayWalletRespVO> convertPage(PageResult<PayWalletDO> page, Map<Long, MemberUserRespDTO> userMap) {
26 PageResult<PayWalletRespVO> pageResult = convertPage(page); 26 PageResult<PayWalletRespVO> pageResult = convertPage(page);
27 - pageResult.getList().forEach( wallet -> MapUtils.findAndThen(userMap, wallet.getUserId(),  
28 - user -> {  
29 - // TODO @jason:可以链式调用哈;  
30 - wallet.setNickname(user.getNickname());  
31 - wallet.setAvatar(user.getAvatar());  
32 - })); 27 + pageResult.getList().forEach(wallet -> MapUtils.findAndThen(userMap, wallet.getUserId(),
  28 + user -> wallet.setNickname(user.getNickname()).setAvatar(user.getAvatar())));
33 return pageResult; 29 return pageResult;
34 } 30 }
35 31
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/demo/PayDemoTransferDO.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.dal.dataobject.demo; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.dal.dataobject.demo;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum; 4 import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
  5 +import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
5 import com.baomidou.mybatisplus.annotation.KeySequence; 6 import com.baomidou.mybatisplus.annotation.KeySequence;
6 import com.baomidou.mybatisplus.annotation.TableId; 7 import com.baomidou.mybatisplus.annotation.TableId;
7 import com.baomidou.mybatisplus.annotation.TableName; 8 import com.baomidou.mybatisplus.annotation.TableName;
@@ -31,6 +32,13 @@ public class PayDemoTransferDO extends BaseDO { @@ -31,6 +32,13 @@ public class PayDemoTransferDO extends BaseDO {
31 private Long userId; 32 private Long userId;
32 33
33 /** 34 /**
  35 + * 应用编号
  36 + *
  37 + * 关联 {@link PayAppDO#getId()}
  38 + */
  39 + private Long appId;
  40 +
  41 + /**
34 * 转账金额,单位:分 42 * 转账金额,单位:分
35 */ 43 */
36 private Integer price; 44 private Integer price;
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/transfer/PayTransferDO.java
@@ -61,11 +61,11 @@ public class PayTransferDO extends BaseDO { @@ -61,11 +61,11 @@ public class PayTransferDO extends BaseDO {
61 61
62 // ========== 商户相关字段 ========== 62 // ========== 商户相关字段 ==========
63 /** 63 /**
64 - * 商户订单编号 64 + * 商户转账单编号
65 * 65 *
66 * 例如说,内部系统 A 的订单号,需要保证每个 PayAppDO 唯一 66 * 例如说,内部系统 A 的订单号,需要保证每个 PayAppDO 唯一
67 */ 67 */
68 - private String merchantOrderId; 68 + private String merchantTransferId;
69 69
70 // ========== 转账相关字段 ========== 70 // ========== 转账相关字段 ==========
71 71
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/transfer/PayTransferMapper.java
@@ -15,6 +15,14 @@ public interface PayTransferMapper extends BaseMapperX&lt;PayTransferDO&gt; { @@ -15,6 +15,14 @@ public interface PayTransferMapper extends BaseMapperX&lt;PayTransferDO&gt; {
15 .eq(PayTransferDO::getId, id).in(PayTransferDO::getStatus, status)); 15 .eq(PayTransferDO::getId, id).in(PayTransferDO::getStatus, status));
16 } 16 }
17 17
  18 + default PayTransferDO selectByAppIdAndMerchantTransferId(Long appId, String merchantTransferId){
  19 + return selectOne(PayTransferDO::getAppId, appId,
  20 + PayTransferDO::getMerchantTransferId, merchantTransferId);
  21 + }
  22 +
  23 + default PayTransferDO selectByNo(String no){
  24 + return selectOne(PayTransferDO::getNo, no);
  25 + }
18 } 26 }
19 27
20 28
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoTransferServiceImpl.java
@@ -4,7 +4,6 @@ import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTran @@ -4,7 +4,6 @@ import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTran
4 import cn.iocoder.yudao.module.pay.convert.demo.PayDemoTransferConvert; 4 import cn.iocoder.yudao.module.pay.convert.demo.PayDemoTransferConvert;
5 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoTransferDO; 5 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoTransferDO;
6 import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoTransferMapper; 6 import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoTransferMapper;
7 -import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService;  
8 import org.springframework.stereotype.Service; 7 import org.springframework.stereotype.Service;
9 import org.springframework.transaction.annotation.Transactional; 8 import org.springframework.transaction.annotation.Transactional;
10 import org.springframework.validation.annotation.Validated; 9 import org.springframework.validation.annotation.Validated;
@@ -33,8 +32,6 @@ public class PayDemoTransferServiceImpl implements PayDemoTransferService { @@ -33,8 +32,6 @@ public class PayDemoTransferServiceImpl implements PayDemoTransferService {
33 @Resource 32 @Resource
34 private PayDemoTransferMapper demoTransferMapper; 33 private PayDemoTransferMapper demoTransferMapper;
35 @Resource 34 @Resource
36 - private PayTransferService transferService;  
37 - @Resource  
38 private Validator validator; 35 private Validator validator;
39 36
40 @Override 37 @Override
@@ -44,7 +41,7 @@ public class PayDemoTransferServiceImpl implements PayDemoTransferService { @@ -44,7 +41,7 @@ public class PayDemoTransferServiceImpl implements PayDemoTransferService {
44 vo.validate(validator); 41 vo.validate(validator);
45 // 2 保存示例转账业务表 42 // 2 保存示例转账业务表
46 PayDemoTransferDO demoTransfer = PayDemoTransferConvert.INSTANCE.convert(vo) 43 PayDemoTransferDO demoTransfer = PayDemoTransferConvert.INSTANCE.convert(vo)
47 - .setUserId(userId).setTransferStatus(WAITING.getStatus()); 44 + .setUserId(userId).setAppId(TRANSFER_APP_ID).setTransferStatus(WAITING.getStatus());
48 demoTransferMapper.insert(demoTransfer); 45 demoTransferMapper.insert(demoTransfer);
49 return demoTransfer.getId(); 46 return demoTransfer.getId();
50 } 47 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferService.java
1 package cn.iocoder.yudao.module.pay.service.transfer; 1 package cn.iocoder.yudao.module.pay.service.transfer;
2 2
3 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO; 3 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
4 -import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferSubmitReqVO;  
5 -import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferSubmitRespVO; 4 +import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateReqVO;
  5 +import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
6 6
7 import javax.validation.Valid; 7 import javax.validation.Valid;
8 8
@@ -14,7 +14,7 @@ import javax.validation.Valid; @@ -14,7 +14,7 @@ import javax.validation.Valid;
14 public interface PayTransferService { 14 public interface PayTransferService {
15 15
16 /** 16 /**
17 - * 提交转账单 17 + * 发起转账
18 * 18 *
19 * 此时,会发起支付渠道的调用 19 * 此时,会发起支付渠道的调用
20 * 20 *
@@ -22,7 +22,7 @@ public interface PayTransferService { @@ -22,7 +22,7 @@ public interface PayTransferService {
22 * @param userIp 用户 ip 22 * @param userIp 用户 ip
23 * @return 渠道的返回结果 23 * @return 渠道的返回结果
24 */ 24 */
25 - PayTransferSubmitRespVO submitTransfer(@Valid PayTransferSubmitReqVO reqVO, String userIp); 25 + PayTransferDO initiateTransfer(@Valid PayTransferCreateReqVO reqVO, String userIp);
26 26
27 /** 27 /**
28 * 创建转账单 28 * 创建转账单
@@ -32,4 +32,10 @@ public interface PayTransferService { @@ -32,4 +32,10 @@ public interface PayTransferService {
32 */ 32 */
33 Long createTransfer(@Valid PayTransferCreateReqDTO reqDTO); 33 Long createTransfer(@Valid PayTransferCreateReqDTO reqDTO);
34 34
  35 + /**
  36 + * 获取转账单
  37 + * @param id 转账单编号
  38 + */
  39 + PayTransferDO getTransfer(Long id);
  40 +
35 } 41 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceImpl.java
1 package cn.iocoder.yudao.module.pay.service.transfer; 1 package cn.iocoder.yudao.module.pay.service.transfer;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.hutool.core.util.StrUtil;  
5 import cn.hutool.extra.spring.SpringUtil; 4 import cn.hutool.extra.spring.SpringUtil;
6 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 5 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
7 import cn.iocoder.yudao.framework.pay.core.client.PayClient; 6 import cn.iocoder.yudao.framework.pay.core.client.PayClient;
8 import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO; 7 import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
9 import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO; 8 import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
  9 +import cn.iocoder.yudao.framework.pay.core.client.exception.PayException;
10 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; 10 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
11 import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferStatusRespEnum; 11 import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferStatusRespEnum;
12 import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum; 12 import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
13 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO; 13 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
14 -import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferSubmitReqVO;  
15 -import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferSubmitRespVO;  
16 -import cn.iocoder.yudao.module.pay.convert.transfer.PayTransferConvert; 14 +import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateReqVO;
  15 +import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
17 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; 16 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
18 import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO; 17 import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
19 -import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferExtensionDO;  
20 -import cn.iocoder.yudao.module.pay.dal.mysql.transfer.PayTransferExtensionMapper;  
21 import cn.iocoder.yudao.module.pay.dal.mysql.transfer.PayTransferMapper; 18 import cn.iocoder.yudao.module.pay.dal.mysql.transfer.PayTransferMapper;
22 import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; 19 import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO;
23 import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum; 20 import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum;
@@ -28,8 +25,10 @@ import org.springframework.stereotype.Service; @@ -28,8 +25,10 @@ import org.springframework.stereotype.Service;
28 import org.springframework.transaction.annotation.Transactional; 25 import org.springframework.transaction.annotation.Transactional;
29 26
30 import javax.annotation.Resource; 27 import javax.annotation.Resource;
  28 +import javax.validation.Validator;
31 29
32 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 30 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  31 +import static cn.iocoder.yudao.module.pay.convert.transfer.PayTransferConvert.INSTANCE;
33 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; 32 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
34 import static cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum.*; 33 import static cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum.*;
35 34
@@ -48,60 +47,69 @@ public class PayTransferServiceImpl implements PayTransferService { @@ -48,60 +47,69 @@ public class PayTransferServiceImpl implements PayTransferService {
48 @Resource 47 @Resource
49 private PayTransferMapper transferMapper; 48 private PayTransferMapper transferMapper;
50 @Resource 49 @Resource
51 - private PayTransferExtensionMapper transferExtensionMapper;  
52 -  
53 - @Resource  
54 private PayAppService appService; 50 private PayAppService appService;
55 @Resource 51 @Resource
56 private PayChannelService channelService; 52 private PayChannelService channelService;
57 -  
58 @Resource 53 @Resource
59 private PayNoRedisDAO noRedisDAO; 54 private PayNoRedisDAO noRedisDAO;
  55 + @Resource
  56 + private Validator validator;
60 57
61 @Override 58 @Override
62 - public PayTransferSubmitRespVO submitTransfer(PayTransferSubmitReqVO reqVO, String userIp) { 59 + @Transactional(rollbackFor = Exception.class)
  60 + public PayTransferDO initiateTransfer(PayTransferCreateReqVO reqVO, String userIp) {
  61 + // 1.1 校验参数
  62 + reqVO.validate(validator);
  63 + // todo 使用 AssertTrue
  64 + validateChannelCodeAndTypeMatch(reqVO.getChannelCode(), reqVO.getType());
  65 + // 1.2 校验转账单是否可以创建
  66 + validateTransferCanCreate(reqVO.getAppId(), reqVO.getMerchantTransferId());
  67 + // 2. 创建转账单,发起转账
  68 + PayTransferCreateReqDTO req = INSTANCE.convert(reqVO).setUserIp(userIp);
  69 + Long transferId = createTransfer(req);
  70 + // 3. 返回转账单
  71 + return getTransfer(transferId);
  72 + }
  73 +
  74 + @Override
  75 + @Transactional(rollbackFor = Exception.class)
  76 + public Long createTransfer(PayTransferCreateReqDTO reqDTO) {
63 // 1.1 校验转账单是否可以提交 77 // 1.1 校验转账单是否可以提交
64 - PayTransferDO transfer = validateTransferCanSubmit(reqVO.getId());  
65 - // 1.2 校验转账类型和渠道是否匹配  
66 - validateChannelCodeAndTypeMatch(reqVO.getChannelCode(), transfer.getType()); 78 + validateTransferExist(reqDTO.getAppId(), reqDTO.getMerchantTransferId());
  79 + // 1.2 校验 App
  80 + PayAppDO appDO = appService.validPayApp(reqDTO.getAppId());
67 // 1.3 校验支付渠道是否有效 81 // 1.3 校验支付渠道是否有效
68 - PayChannelDO channel = validateChannelCanSubmit(transfer.getAppId(), reqVO.getChannelCode()); 82 + PayChannelDO channel = channelService.validPayChannel(reqDTO.getAppId(), reqDTO.getChannelCode());
69 PayClient client = channelService.getPayClient(channel.getId()); 83 PayClient client = channelService.getPayClient(channel.getId());
70 -  
71 - // 2. 新增转账拓展单 84 + if (client == null) {
  85 + log.error("[createTransfer][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
  86 + throw exception(CHANNEL_NOT_FOUND);
  87 + }
  88 + // 2.创建转账单
72 String no = noRedisDAO.generate(TRANSFER_NO_PREFIX); 89 String no = noRedisDAO.generate(TRANSFER_NO_PREFIX);
73 - PayTransferExtensionDO transferExtension = new PayTransferExtensionDO().setNo(no)  
74 - .setTransferId(transfer.getId()).setChannelId(channel.getId())  
75 - .setChannelCode(channel.getCode()).setStatus(WAITING.getStatus());  
76 - transferExtensionMapper.insert(transferExtension);  
77 -  
78 - // 3. 调用三方渠道发起转账  
79 - PayTransferUnifiedReqDTO transferUnifiedReq = new PayTransferUnifiedReqDTO()  
80 - .setOutTransferNo(transferExtension.getNo()).setPrice(transfer.getPrice())  
81 - .setType(transfer.getType()).setTitle(transfer.getSubject())  
82 - .setUserIp(userIp)  
83 - .setChannelExtras(reqVO.getChannelExtras());  
84 - PayTransferRespDTO unifiedTransferResp = client.unifiedTransfer(transferUnifiedReq);  
85 -  
86 - // 4. 通知转账结果  
87 - getSelf().notifyTransfer(channel, unifiedTransferResp);  
88 - // 如有渠道错误码,则抛出业务异常,提示用户  
89 - if (StrUtil.isNotEmpty(unifiedTransferResp.getChannelErrorCode())) {  
90 - throw exception(PAY_TRANSFER_SUBMIT_CHANNEL_ERROR, unifiedTransferResp.getChannelErrorCode(),  
91 - unifiedTransferResp.getChannelErrorMsg()); 90 + PayTransferDO transfer = INSTANCE.convert(reqDTO)
  91 + .setChannelId(channel.getId())
  92 + .setNo(no).setStatus(WAITING.getStatus())
  93 + .setNotifyUrl(appDO.getRefundNotifyUrl()); // TODO 需要加个transfer Notify url
  94 + transferMapper.insert(transfer);
  95 + try {
  96 + // 3. 调用三方渠道发起转账
  97 + PayTransferUnifiedReqDTO transferUnifiedReq = INSTANCE.convert2(reqDTO)
  98 + .setOutTransferNo(no);
  99 + PayTransferRespDTO unifiedTransferResp = client.unifiedTransfer(transferUnifiedReq);
  100 + // 4. 通知转账结果
  101 + getSelf().notifyTransfer(channel, unifiedTransferResp);
  102 + } catch (PayException e) {
  103 + // 这里仅打印异常,不进行抛出。
  104 + // TODO 说明
  105 + log.error("[createTransfer][转账 id({}) requestDTO({}) 发生异常]", transfer.getId(), reqDTO, e);
92 } 106 }
93 - return new PayTransferSubmitRespVO().setStatus(unifiedTransferResp.getStatus()); 107 + return transfer.getId();
94 } 108 }
95 109
96 @Override 110 @Override
97 - public Long createTransfer(PayTransferCreateReqDTO reqDTO) {  
98 - // 校验 App  
99 - appService.validPayApp(reqDTO.getAppId());  
100 - // 创建转账单  
101 - PayTransferDO transfer = PayTransferConvert.INSTANCE.convert(reqDTO)  
102 - .setStatus(WAITING.getStatus());  
103 - transferMapper.insert(transfer);  
104 - return transfer.getId(); 111 + public PayTransferDO getTransfer(Long id) {
  112 + return transferMapper.selectById(id);
105 } 113 }
106 114
107 @Transactional(rollbackFor = Exception.class) 115 @Transactional(rollbackFor = Exception.class)
@@ -119,26 +127,38 @@ public class PayTransferServiceImpl implements PayTransferService { @@ -119,26 +127,38 @@ public class PayTransferServiceImpl implements PayTransferService {
119 // TODO IN_PROGRESS 待处理 127 // TODO IN_PROGRESS 待处理
120 } 128 }
121 129
122 - private void notifyTransferSuccess(PayChannelDO channel, PayTransferRespDTO notify) {  
123 - // 1. 更新 PayTransferExtensionDO 转账成功  
124 - PayTransferExtensionDO transferExtension = updateTransferExtensionSuccess(notify); 130 + private void validateTransferExist(Long appId, String merchantTransferId ) {
  131 + PayTransferDO transfer = transferMapper.selectByAppIdAndMerchantTransferId(appId, merchantTransferId);
  132 + if (transfer != null) { // 是否存在
  133 + throw exception(PAY_TRANSFER_EXISTS);
  134 + }
  135 + }
125 136
126 - // 2. 更新 PayTransferDO 转账成功  
127 - Boolean transferred = updateTransferSuccess(channel,transferExtension, notify); 137 + private void validateTransferCanCreate(Long appId, String merchantTransferId ) {
  138 + PayTransferDO transfer = transferMapper.selectByAppIdAndMerchantTransferId(appId, merchantTransferId);
  139 + if (transfer != null) { // 是否存在
  140 + throw exception(PAY_MERCHANT_TRANSFER_EXISTS);
  141 + }
  142 + }
  143 +
  144 + private void notifyTransferSuccess(PayChannelDO channel, PayTransferRespDTO notify) {
  145 + // 1. 更新 PayTransferDO 转账成功
  146 + Boolean transferred = updateTransferSuccess(channel, notify);
128 if (transferred) { 147 if (transferred) {
129 return; 148 return;
130 } 149 }
131 - // 3. TODO 插入转账通知记录 150 + // 2. TODO 插入转账通知记录
132 } 151 }
133 152
134 - private Boolean updateTransferSuccess(PayChannelDO channel, PayTransferExtensionDO transferExtension,  
135 - PayTransferRespDTO notify) { 153 + private Boolean updateTransferSuccess(PayChannelDO channel, PayTransferRespDTO notify) {
136 // 1.校验 154 // 1.校验
137 - PayTransferDO transfer = transferMapper.selectById(transferExtension.getTransferId()); 155 + PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo());
138 if (transfer == null) { 156 if (transfer == null) {
139 throw exception(PAY_TRANSFER_NOT_FOUND); 157 throw exception(PAY_TRANSFER_NOT_FOUND);
140 } 158 }
141 - 159 + if (isSuccess(transfer.getStatus())) { // 如果已成功,直接返回,不用重复更新
  160 + return Boolean.TRUE;
  161 + }
142 if (!isPendingStatus(transfer.getStatus())) { 162 if (!isPendingStatus(transfer.getStatus())) {
143 throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING); 163 throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING);
144 } 164 }
@@ -146,76 +166,52 @@ public class PayTransferServiceImpl implements PayTransferService { @@ -146,76 +166,52 @@ public class PayTransferServiceImpl implements PayTransferService {
146 int updateCounts = transferMapper.updateByIdAndStatus(transfer.getId(), 166 int updateCounts = transferMapper.updateByIdAndStatus(transfer.getId(),
147 CollUtil.newArrayList(WAITING.getStatus(), IN_PROGRESS.getStatus()), 167 CollUtil.newArrayList(WAITING.getStatus(), IN_PROGRESS.getStatus()),
148 new PayTransferDO().setStatus(SUCCESS.getStatus()).setSuccessTime(notify.getSuccessTime()) 168 new PayTransferDO().setStatus(SUCCESS.getStatus()).setSuccessTime(notify.getSuccessTime())
  169 + .setChannelTransferNo(notify.getChannelTransferNo())
149 .setChannelId(channel.getId()).setChannelCode(channel.getCode()) 170 .setChannelId(channel.getId()).setChannelCode(channel.getCode())
150 - .setNo(transferExtension.getNo())); 171 + .setChannelNotifyData(JsonUtils.toJsonString(notify)));
151 if (updateCounts == 0) { 172 if (updateCounts == 0) {
152 throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING); 173 throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING);
153 } 174 }
154 log.info("[updateTransferSuccess][transfer({}) 更新为已转账]", transfer.getId()); 175 log.info("[updateTransferSuccess][transfer({}) 更新为已转账]", transfer.getId());
155 - return false; 176 + return Boolean.FALSE;
156 } 177 }
157 178
158 - private PayTransferExtensionDO updateTransferExtensionSuccess(PayTransferRespDTO notify) {  
159 - // 1 校验  
160 - PayTransferExtensionDO transferExtension = transferExtensionMapper.selectByNo(notify.getOutTransferNo());  
161 - if (transferExtension == null) {  
162 - throw exception(PAY_TRANSFER_EXTENSION_NOT_FOUND); 179 + private void updateTransferClosed(PayChannelDO channel, PayTransferRespDTO notify) {
  180 + // 1.校验
  181 + PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo());
  182 + if (transfer == null) {
  183 + throw exception(PAY_TRANSFER_NOT_FOUND);
163 } 184 }
164 - if (isSuccess(transferExtension.getStatus())) { // 如果已成功,直接返回,不用重复更新  
165 - log.info("[updateTransferExtensionSuccess][transferExtension({}) 已经是成功状态,无需更新]", transferExtension.getId());  
166 - return transferExtension; 185 + if (isClosed(transfer.getStatus())) { // 如果已是关闭状态,直接返回,不用重复更新
  186 + log.info("[updateTransferClosed][transfer({}) 已经是关闭状态,无需更新]", transfer.getId());
  187 + return;
167 } 188 }
168 - if (!isPendingStatus(transferExtension.getStatus())) {  
169 - throw exception(PAY_TRANSFER_EXTENSION_STATUS_IS_NOT_PENDING); 189 + if (!isPendingStatus(transfer.getStatus())) {
  190 + throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING);
170 } 191 }
171 - // 2. 更新 PayTransferExtensionDO  
172 - int updateCount = transferExtensionMapper.updateByIdAndStatus(transferExtension.getId(), 192 + // 2.更新
  193 + int updateCount = transferMapper.updateByIdAndStatus(transfer.getId(),
173 CollUtil.newArrayList(WAITING.getStatus(), IN_PROGRESS.getStatus()), 194 CollUtil.newArrayList(WAITING.getStatus(), IN_PROGRESS.getStatus()),
174 - new PayTransferExtensionDO().setStatus(SUCCESS.getStatus()) 195 + new PayTransferDO().setStatus(CLOSED.getStatus()) .setChannelId(channel.getId())
  196 + .setChannelCode(channel.getCode()).setChannelTransferNo(notify.getChannelTransferNo())
  197 + .setChannelErrorCode(notify.getChannelErrorCode()).setChannelErrorMsg(notify.getChannelErrorMsg())
175 .setChannelNotifyData(JsonUtils.toJsonString(notify))); 198 .setChannelNotifyData(JsonUtils.toJsonString(notify)));
176 if (updateCount == 0) { 199 if (updateCount == 0) {
177 - throw exception(PAY_TRANSFER_EXTENSION_STATUS_IS_NOT_PENDING); 200 + throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING);
178 } 201 }
179 - log.info("[updateTransferExtensionSuccess][transferExtension({}) 更新为已转账]", transferExtension.getId());  
180 - return transferExtension; 202 + log.info("[updateTransferClosed][transfer({}) 更新为关闭状态]", transfer.getId());
181 } 203 }
182 204
183 private void notifyTransferClosed(PayChannelDO channel, PayTransferRespDTO notify) { 205 private void notifyTransferClosed(PayChannelDO channel, PayTransferRespDTO notify) {
184 - // 更新 PayTransferExtensionDO 转账关闭  
185 - updateTransferExtensionClosed(notify);  
186 - }  
187 -  
188 - private void updateTransferExtensionClosed(PayTransferRespDTO notify) {  
189 - // 1 校验  
190 - PayTransferExtensionDO transferExtension = transferExtensionMapper.selectByNo(notify.getOutTransferNo());  
191 - if (transferExtension == null) {  
192 - throw exception(PAY_TRANSFER_EXTENSION_NOT_FOUND);  
193 - }  
194 - if (isClosed(transferExtension.getStatus())) { // 如果已是关闭状态,直接返回,不用重复更新  
195 - log.info("[updateTransferExtensionSuccess][transferExtension({}) 已经是关闭状态,无需更新]", transferExtension.getId());  
196 - return;  
197 - }  
198 - if (!isPendingStatus(transferExtension.getStatus())) {  
199 - throw exception(PAY_TRANSFER_EXTENSION_STATUS_IS_NOT_PENDING);  
200 - }  
201 - // 2. 更新 PayTransferExtensionDO  
202 - int updateCount = transferExtensionMapper.updateByIdAndStatus(transferExtension.getId(),  
203 - CollUtil.newArrayList(WAITING.getStatus(), IN_PROGRESS.getStatus()),  
204 - new PayTransferExtensionDO().setStatus(CLOSED.getStatus())  
205 - .setChannelNotifyData(JsonUtils.toJsonString(notify)));  
206 - if (updateCount == 0) {  
207 - throw exception(PAY_TRANSFER_EXTENSION_STATUS_IS_NOT_PENDING);  
208 - }  
209 - log.info("[updateTransferExtensionSuccess][transferExtension({}) 更新为关闭状态]", transferExtension.getId()); 206 + // 更新 PayTransferDO 转账关闭
  207 + updateTransferClosed(channel,notify);
210 } 208 }
211 209
212 private void validateChannelCodeAndTypeMatch(String channelCode, Integer type) { 210 private void validateChannelCodeAndTypeMatch(String channelCode, Integer type) {
213 PayTransferTypeEnum transferType = PayTransferTypeEnum.typeOf(type); 211 PayTransferTypeEnum transferType = PayTransferTypeEnum.typeOf(type);
214 - PayChannelEnum payChannel = PayChannelEnum.getByCode(channelCode);  
215 switch (transferType) { 212 switch (transferType) {
216 case ALIPAY_BALANCE: { 213 case ALIPAY_BALANCE: {
217 - // TODO @jason:可以抽到 PayChannelEnum 里,isAlipay? 类似这种哈  
218 - if (!payChannel.getCode().startsWith("alipay")) { 214 + if (!PayChannelEnum.isAlipay(channelCode)) {
219 throw exception(PAY_TRANSFER_TYPE_AND_CHANNEL_NOT_MATCH); 215 throw exception(PAY_TRANSFER_TYPE_AND_CHANNEL_NOT_MATCH);
220 } 216 }
221 break; 217 break;
@@ -241,7 +237,7 @@ public class PayTransferServiceImpl implements PayTransferService { @@ -241,7 +237,7 @@ public class PayTransferServiceImpl implements PayTransferService {
241 return channel; 237 return channel;
242 } 238 }
243 239
244 - private PayTransferDO validateTransferCanSubmit(Long id) { 240 + private PayTransferDO validateTransferExist(Long id) {
245 PayTransferDO transfer = transferMapper.selectById(id); 241 PayTransferDO transfer = transferMapper.selectById(id);
246 if (transfer == null) { // 是否存在 242 if (transfer == null) { // 是否存在
247 throw exception(PAY_TRANSFER_NOT_FOUND); 243 throw exception(PAY_TRANSFER_NOT_FOUND);