Commit ccccd9f226bdc3c8505cad7c7bc6bd51dd6db56b

Authored by jason
1 parent 5f29399c

转账 - 转账代码修改,新增转账示例

Showing 25 changed files with 260 additions and 317 deletions
sql/mysql/pay_wallet.sql
@@ -15,10 +15,9 @@ CREATE TABLE `pay_transfer` @@ -15,10 +15,9 @@ CREATE TABLE `pay_transfer`
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 + `user_name` varchar(64) NULL COMMENT '收款人姓名',
18 `alipay_logon_id` varchar(64) NULL COMMENT '支付宝登录号', 19 `alipay_logon_id` varchar(64) NULL COMMENT '支付宝登录号',
19 - `alipay_account_name` varchar(64) NULL COMMENT '支付宝账号名称',  
20 `openid` varchar(64) NULL COMMENT '微信 openId', 20 `openid` varchar(64) NULL COMMENT '微信 openId',
21 - `wx_account_name` varchar(64) NULL COMMENT '微信账号名称',  
22 `notify_url` varchar(1024) NOT NULL COMMENT '异步通知商户地址', 21 `notify_url` varchar(1024) NOT NULL COMMENT '异步通知商户地址',
23 `user_ip` varchar(50) NOT NULL COMMENT '用户 IP', 22 `user_ip` varchar(50) NOT NULL COMMENT '用户 IP',
24 `channel_extras` varchar(512) NULL DEFAULT NULL COMMENT '渠道的额外参数', 23 `channel_extras` varchar(512) NULL DEFAULT NULL COMMENT '渠道的额外参数',
@@ -36,42 +35,17 @@ CREATE TABLE `pay_transfer` @@ -36,42 +35,17 @@ CREATE TABLE `pay_transfer`
36 ) ENGINE=InnoDB COMMENT='转账单表'; 35 ) ENGINE=InnoDB COMMENT='转账单表';
37 36
38 -- ---------------------------- 37 -- ----------------------------
39 --- 转账扩展单  
40 --- ----------------------------  
41 -DROP TABLE IF EXISTS `pay_transfer_extension`;  
42 -CREATE TABLE `pay_transfer_extension`  
43 -(  
44 - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',  
45 - `no` varchar(64) NOT NULL COMMENT '转账单号',  
46 - `transfer_id` bigint NOT NULL COMMENT '转账单编号',  
47 - `channel_id` bigint NOT NULL COMMENT '转账渠道编号',  
48 - `channel_code` varchar(32) NOT NULL COMMENT '转账渠道编码',  
49 - `channel_extras` varchar(512) NULL DEFAULT NULL COMMENT '支付渠道的额外参数',  
50 - `status` tinyint NOT NULL COMMENT '转账状态',  
51 - `channel_notify_data` varchar(4096) NULL DEFAULT NULL COMMENT '支付渠道异步通知的内容',  
52 - `creator` varchar(64) NULL DEFAULT '' COMMENT '创建者',  
53 - `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',  
54 - `updater` varchar(64) NULL DEFAULT '' COMMENT '更新者',  
55 - `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',  
56 - `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',  
57 - `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',  
58 - PRIMARY KEY (`id`) USING BTREE  
59 -) ENGINE=InnoDB COMMENT='转账拓展单表';  
60 -  
61 --- ----------------------------  
62 -- Table structure for pay_demo_transfer 38 -- Table structure for pay_demo_transfer
63 -- ---------------------------- 39 -- ----------------------------
64 DROP TABLE IF EXISTS `pay_demo_transfer`; 40 DROP TABLE IF EXISTS `pay_demo_transfer`;
65 CREATE TABLE `pay_demo_transfer` ( 41 CREATE TABLE `pay_demo_transfer` (
66 `id` bigint NOT NULL AUTO_INCREMENT COMMENT '订单编号', 42 `id` bigint NOT NULL AUTO_INCREMENT COMMENT '订单编号',
67 - `user_id` bigint UNSIGNED NOT NULL COMMENT '用户编号',  
68 `app_id` bigint NOT NULL COMMENT '应用编号', 43 `app_id` bigint NOT NULL COMMENT '应用编号',
69 - `price` int NOT NULL COMMENT '转账金额,单位:分',  
70 `type` int NOT NULL COMMENT '转账类型', 44 `type` int NOT NULL COMMENT '转账类型',
  45 + `price` int NOT NULL COMMENT '转账金额,单位:分',
  46 + `user_name` varchar(64) NULL COMMENT '收款人姓名',
71 `alipay_logon_id` varchar(64) NULL COMMENT '支付宝登录号', 47 `alipay_logon_id` varchar(64) NULL COMMENT '支付宝登录号',
72 - `alipay_account_name` varchar(64) NULL COMMENT '支付宝账号名称',  
73 `openid` varchar(64) NULL COMMENT '微信 openId', 48 `openid` varchar(64) NULL COMMENT '微信 openId',
74 - `wx_account_name` varchar(64) NULL COMMENT '微信账号名称',  
75 `transfer_status` tinyint NOT NULL DEFAULT 0 COMMENT '转账状态', 49 `transfer_status` tinyint NOT NULL DEFAULT 0 COMMENT '转账状态',
76 `pay_transfer_id` bigint NULL DEFAULT NULL COMMENT '转账订单编号', 50 `pay_transfer_id` bigint NULL DEFAULT NULL COMMENT '转账订单编号',
77 `pay_channel_code` varchar(16) NULL DEFAULT NULL COMMENT '转账支付成功渠道', 51 `pay_channel_code` varchar(16) NULL DEFAULT NULL COMMENT '转账支付成功渠道',
@@ -216,3 +190,48 @@ VALUES ( @@ -216,3 +190,48 @@ VALUES (
216 '', '', '', 0 190 '', '', '', 0
217 ); 191 );
218 192
  193 +-- 支付实战和转账实战数据库脚本
  194 +
  195 +update system_menu set deleted = 1 where id = 2161;
  196 +
  197 +INSERT INTO system_menu(
  198 + name, permission, type, sort, parent_id,
  199 + path, icon, component, status, component_name
  200 +)
  201 +VALUES (
  202 + '接入示例', '', 1, 99, 1117,
  203 + 'demo', 'ep:caret-right', '', 0, ''
  204 + );
  205 +
  206 +SELECT @parentId1 := LAST_INSERT_ID();
  207 +
  208 +INSERT INTO system_menu(
  209 + name, permission, type, sort, parent_id,
  210 + path, icon, component, status, component_name
  211 +)
  212 +VALUES (
  213 + '支付实战', '', 2, 1, @parentId1,
  214 + 'demo-order', 'fa:leaf', 'pay/demo/order/index', 0, NULL
  215 + );
  216 +
  217 +INSERT INTO system_menu(
  218 + name, permission, type, sort, parent_id,
  219 + path, icon, component, status, component_name
  220 +)
  221 +VALUES (
  222 + '转账实战', '', 2, 1, @parentId1,
  223 + 'demo-transfer', 'fa:leaf', 'pay/demo/transfer/index', 0, NULL
  224 + );
  225 +
  226 +-- 转账状态和转账类型数据字典
  227 +INSERT INTO `system_dict_type`(`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (171, '支付转账类型', 'pay_transfer_type', 0, '', '1', '2023-10-28 16:27:18', '1', '2023-10-28 16:27:18', b'0', '1970-01-01 00:00:00');
  228 +INSERT INTO `system_dict_type`(`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (170, '转账订单状态', 'pay_transfer_status', 0, '', '1', '2023-10-28 16:18:32', '1', '2023-10-28 16:18:32', b'0', '1970-01-01 00:00:00');
  229 +
  230 +INSERT INTO `system_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1245, 4, '钱包余额', '4', 'pay_transfer_type', 0, 'info', '', '', '1', '2023-10-28 16:28:37', '1', '2023-10-28 16:28:37', b'0');
  231 +INSERT INTO `system_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1244, 3, '银行卡', '3', 'pay_transfer_type', 0, 'default', '', '', '1', '2023-10-28 16:28:21', '1', '2023-10-28 16:28:21', b'0');
  232 +INSERT INTO `system_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1243, 2, '微信余额', '2', 'pay_transfer_type', 0, 'info', '', '', '1', '2023-10-28 16:28:07', '1', '2023-10-28 16:28:07', b'0');
  233 +INSERT INTO `system_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1242, 1, '支付宝余额', '1', 'pay_transfer_type', 0, 'default', '', '', '1', '2023-10-28 16:27:44', '1', '2023-10-28 16:27:44', b'0');
  234 +INSERT INTO `system_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1241, 4, '转账失败', '30', 'pay_transfer_status', 0, 'warning', '', '', '1', '2023-10-28 16:24:16', '1', '2023-10-28 16:24:16', b'0');
  235 +INSERT INTO `system_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1240, 3, '转账成功', '20', 'pay_transfer_status', 0, 'success', '', '', '1', '2023-10-28 16:23:50', '1', '2023-10-28 16:23:50', b'0');
  236 +INSERT INTO `system_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1239, 2, '转账进行中', '10', 'pay_transfer_status', 0, 'info', '', '', '1', '2023-10-28 16:23:12', '1', '2023-10-28 16:23:12', b'0');
  237 +INSERT INTO `system_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1238, 1, '等待转账', '0', 'pay_transfer_status', 0, 'default', '', '', '1', '2023-10-28 16:21:43', '1', '2023-10-28 16:23:22', b'0');
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/enums/GlobalErrorCodeConstants.java
@@ -30,6 +30,7 @@ public interface GlobalErrorCodeConstants { @@ -30,6 +30,7 @@ public interface GlobalErrorCodeConstants {
30 30
31 ErrorCode INTERNAL_SERVER_ERROR = new ErrorCode(500, "系统异常"); 31 ErrorCode INTERNAL_SERVER_ERROR = new ErrorCode(500, "系统异常");
32 ErrorCode NOT_IMPLEMENTED = new ErrorCode(501, "功能未实现/未开启"); 32 ErrorCode NOT_IMPLEMENTED = new ErrorCode(501, "功能未实现/未开启");
  33 + ErrorCode ERROR_CONFIGURATION = new ErrorCode(502, "错误的配置项");
33 34
34 // ========== 自定义错误段 ========== 35 // ========== 自定义错误段 ==========
35 ErrorCode REPEATED_REQUESTS = new ErrorCode(900, "重复请求,请稍后重试"); // 重复请求 36 ErrorCode REPEATED_REQUESTS = new ErrorCode(900, "重复请求,请稍后重试"); // 重复请求
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/transfer/PayTransferUnifiedReqDTO.java
@@ -11,6 +11,8 @@ import javax.validation.constraints.NotEmpty; @@ -11,6 +11,8 @@ import javax.validation.constraints.NotEmpty;
11 import javax.validation.constraints.NotNull; 11 import javax.validation.constraints.NotNull;
12 import java.util.Map; 12 import java.util.Map;
13 13
  14 +import static cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum.*;
  15 +
14 /** 16 /**
15 * 统一转账 Request DTO 17 * 统一转账 Request DTO
16 * 18 *
@@ -49,33 +51,27 @@ public class PayTransferUnifiedReqDTO { @@ -49,33 +51,27 @@ public class PayTransferUnifiedReqDTO {
49 */ 51 */
50 @NotEmpty(message = "转账标题不能为空") 52 @NotEmpty(message = "转账标题不能为空")
51 @Length(max = 128, message = "转账标题不能超过 128") 53 @Length(max = 128, message = "转账标题不能超过 128")
52 - private String title;  
53 - 54 + private String subject;
54 55
55 /** 56 /**
56 - * 支付宝登录号 57 + * 收款人姓名
57 */ 58 */
58 - @NotBlank(message = "支付宝登录号不能为空", groups = {PayTransferTypeEnum.Alipay.class})  
59 - private String alipayLogonId; 59 + @NotBlank(message = "收款人姓名不能为空", groups = {Alipay.class})
  60 + private String userName;
60 61
61 /** 62 /**
62 - * 支付宝账号名称 63 + * 支付宝登录号
63 */ 64 */
64 - @NotBlank(message = "支付宝账号名称不能为空", groups = {PayTransferTypeEnum.Alipay.class})  
65 - private String alipayAccountName; 65 + @NotBlank(message = "支付宝登录号不能为空", groups = {Alipay.class})
  66 + private String alipayLogonId;
66 67
67 /** 68 /**
68 * 微信 openId 69 * 微信 openId
69 */ 70 */
70 - @NotBlank(message = "微信 openId 不能为空", groups = {PayTransferTypeEnum.WxPay.class}) 71 + @NotBlank(message = "微信 openId 不能为空", groups = {WxPay.class})
71 private String openid; 72 private String openid;
72 73
73 /** 74 /**
74 - * 微信账号名称  
75 - */  
76 - private String wxAccountName;  
77 -  
78 - /**  
79 * 支付渠道的额外参数 75 * 支付渠道的额外参数
80 */ 76 */
81 private Map<String, String> channelExtras; 77 private Map<String, String> channelExtras;
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java
@@ -16,6 +16,8 @@ import lombok.extern.slf4j.Slf4j; @@ -16,6 +16,8 @@ import lombok.extern.slf4j.Slf4j;
16 16
17 import java.util.Map; 17 import java.util.Map;
18 18
  19 +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.NOT_IMPLEMENTED;
  20 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
19 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; 21 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
20 22
21 /** 23 /**
@@ -186,9 +188,9 @@ public abstract class AbstractPayClient&lt;Config extends PayClientConfig&gt; implemen @@ -186,9 +188,9 @@ public abstract class AbstractPayClient&lt;Config extends PayClientConfig&gt; implemen
186 188
187 @Override 189 @Override
188 public final PayTransferRespDTO unifiedTransfer(PayTransferUnifiedReqDTO reqDTO) { 190 public final PayTransferRespDTO unifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
189 - validatePayTransferReqDTO(reqDTO);  
190 PayTransferRespDTO resp; 191 PayTransferRespDTO resp;
191 try{ 192 try{
  193 + validatePayTransferReqDTO(reqDTO);
192 resp = doUnifiedTransfer(reqDTO); 194 resp = doUnifiedTransfer(reqDTO);
193 }catch (ServiceException ex) { // 业务异常,都是实现类已经翻译,所以直接抛出即可 195 }catch (ServiceException ex) { // 业务异常,都是实现类已经翻译,所以直接抛出即可
194 throw ex; 196 throw ex;
@@ -212,7 +214,7 @@ public abstract class AbstractPayClient&lt;Config extends PayClientConfig&gt; implemen @@ -212,7 +214,7 @@ public abstract class AbstractPayClient&lt;Config extends PayClientConfig&gt; implemen
212 break; 214 break;
213 } 215 }
214 default: { 216 default: {
215 - throw new UnsupportedOperationException("待实现"); 217 + throw exception(NOT_IMPLEMENTED);
216 } 218 }
217 } 219 }
218 } 220 }
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java
@@ -43,8 +43,7 @@ import java.util.Objects; @@ -43,8 +43,7 @@ import java.util.Objects;
43 import java.util.function.Supplier; 43 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;  
47 -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.NOT_IMPLEMENTED; 46 +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.*;
48 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 47 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
49 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0; 48 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
50 import static cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig.MODE_CERTIFICATE; 49 import static cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig.MODE_CERTIFICATE;
@@ -229,13 +228,13 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa @@ -229,13 +228,13 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa
229 protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) throws AlipayApiException { 228 protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) throws AlipayApiException {
230 // 1.1 校验公钥类型 必须使用公钥证书模式 229 // 1.1 校验公钥类型 必须使用公钥证书模式
231 if (!Objects.equals(config.getMode(), MODE_CERTIFICATE)) { 230 if (!Objects.equals(config.getMode(), MODE_CERTIFICATE)) {
232 - throw exception0(BAD_REQUEST.getCode(),"支付宝单笔转账必须使用公钥证书模式"); 231 + throw exception0(ERROR_CONFIGURATION.getCode(),"支付宝单笔转账必须使用公钥证书模式");
233 } 232 }
234 // 1.2 构建 AlipayFundTransUniTransferModel 233 // 1.2 构建 AlipayFundTransUniTransferModel
235 AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel(); 234 AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
236 // ① 通用的参数 235 // ① 通用的参数
237 model.setTransAmount(formatAmount(reqDTO.getPrice())); // 转账金额 236 model.setTransAmount(formatAmount(reqDTO.getPrice())); // 转账金额
238 - model.setOrderTitle(reqDTO.getTitle()); // 转账业务的标题,用于在支付宝用户的账单里显示。 237 + model.setOrderTitle(reqDTO.getSubject()); // 转账业务的标题,用于在支付宝用户的账单里显示。
239 model.setOutBizNo(reqDTO.getOutTransferNo()); 238 model.setOutBizNo(reqDTO.getOutTransferNo());
240 model.setProductCode("TRANS_ACCOUNT_NO_PWD"); // 销售产品码。单笔无密转账固定为 TRANS_ACCOUNT_NO_PWD 239 model.setProductCode("TRANS_ACCOUNT_NO_PWD"); // 销售产品码。单笔无密转账固定为 TRANS_ACCOUNT_NO_PWD
241 model.setBizScene("DIRECT_TRANSFER"); // 业务场景 单笔无密转账固定为 DIRECT_TRANSFER 240 model.setBizScene("DIRECT_TRANSFER"); // 业务场景 单笔无密转账固定为 DIRECT_TRANSFER
@@ -249,7 +248,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa @@ -249,7 +248,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa
249 Participant payeeInfo = new Participant(); 248 Participant payeeInfo = new Participant();
250 payeeInfo.setIdentityType("ALIPAY_LOGON_ID"); 249 payeeInfo.setIdentityType("ALIPAY_LOGON_ID");
251 payeeInfo.setIdentity(reqDTO.getAlipayLogonId()); // 支付宝登录号 250 payeeInfo.setIdentity(reqDTO.getAlipayLogonId()); // 支付宝登录号
252 - payeeInfo.setName(reqDTO.getAlipayAccountName()); // 支付宝账号姓名 251 + payeeInfo.setName(reqDTO.getUserName()); // 支付宝账号姓名
253 model.setPayeeInfo(payeeInfo); 252 model.setPayeeInfo(payeeInfo);
254 // 1.3 构建 AlipayFundTransUniTransferRequest 253 // 1.3 构建 AlipayFundTransUniTransferRequest
255 AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest(); 254 AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/transfer/PayTransferStatusRespEnum.java
@@ -14,7 +14,7 @@ import java.util.Objects; @@ -14,7 +14,7 @@ import java.util.Objects;
14 @AllArgsConstructor 14 @AllArgsConstructor
15 public enum PayTransferStatusRespEnum { 15 public enum PayTransferStatusRespEnum {
16 16
17 - WAITING(0, "转账中"), 17 + WAITING(0, "等待转账"),
18 18
19 /** 19 /**
20 * TODO 转账到银行卡. 会有T+0 T+1 到账的请情况。 还未实现 20 * TODO 转账到银行卡. 会有T+0 T+1 到账的请情况。 还未实现
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferCreateReqDTO.java
@@ -60,19 +60,16 @@ public class PayTransferCreateReqDTO { @@ -60,19 +60,16 @@ public class PayTransferCreateReqDTO {
60 @NotEmpty(message = "转账标题不能为空") 60 @NotEmpty(message = "转账标题不能为空")
61 private String subject; 61 private String subject;
62 62
63 - @NotEmpty(message = "收款方信息不能为空")  
64 - private Map<String, String> payeeInfo; 63 + /**
  64 + * 收款人姓名
  65 + */
  66 + @NotBlank(message = "收款人姓名不能为空", groups = {PayTransferTypeEnum.Alipay.class})
  67 + private String userName;
65 68
66 @NotBlank(message = "支付宝登录号不能为空", groups = {PayTransferTypeEnum.Alipay.class}) 69 @NotBlank(message = "支付宝登录号不能为空", groups = {PayTransferTypeEnum.Alipay.class})
67 private String alipayLogonId; 70 private String alipayLogonId;
68 71
69 - @NotBlank(message = "支付宝登录号不能为空", groups = {PayTransferTypeEnum.Alipay.class})  
70 - private String alipayAccountName;  
71 -  
72 // ========== 微信转账相关字段 ========== 72 // ========== 微信转账相关字段 ==========
73 @NotBlank(message = "微信 openId 不能为空", groups = {PayTransferTypeEnum.WxPay.class}) 73 @NotBlank(message = "微信 openId 不能为空", groups = {PayTransferTypeEnum.WxPay.class})
74 private String openid; 74 private String openid;
75 -  
76 - private String wxAccountName;  
77 -  
78 } 75 }
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java
@@ -68,11 +68,9 @@ public interface ErrorCodeConstants { @@ -68,11 +68,9 @@ public interface ErrorCodeConstants {
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_EXISTS = new ErrorCode(1_007_009_003, "已经存在转账单"); 70 ErrorCode PAY_TRANSFER_EXISTS = new ErrorCode(1_007_009_003, "已经存在转账单");
71 - ErrorCode PAY_MERCHANT_TRANSFER_EXISTS = new ErrorCode(1_007_009_004, "该笔业务的转账已经存在,请查询相关状态"); 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, "转账单不处于待转账"); 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, "转账单不处于待转账或转账中"); 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 -  
76 // ========== 示例订单 1-007-900-000 ========== 74 // ========== 示例订单 1-007-900-000 ==========
77 ErrorCode DEMO_ORDER_NOT_FOUND = new ErrorCode(1_007_900_000, "示例订单不存在"); 75 ErrorCode DEMO_ORDER_NOT_FOUND = new ErrorCode(1_007_900_000, "示例订单不存在");
78 ErrorCode DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1_007_900_001, "示例订单更新支付状态失败,订单不是【未支付】状态"); 76 ErrorCode DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1_007_900_001, "示例订单更新支付状态失败,订单不是【未支付】状态");
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/transfer/PayTransferStatusEnum.java
@@ -12,7 +12,7 @@ import java.util.Objects; @@ -12,7 +12,7 @@ import java.util.Objects;
12 @AllArgsConstructor 12 @AllArgsConstructor
13 public enum PayTransferStatusEnum { 13 public enum PayTransferStatusEnum {
14 14
15 - WAITING(0, "待转账"), 15 + WAITING(0, "等待转账"),
16 /** 16 /**
17 * TODO 转账到银行卡. 会有T+0 T+1 到账的请情况。 还未实现 17 * TODO 转账到银行卡. 会有T+0 T+1 到账的请情况。 还未实现
18 */ 18 */
@@ -20,7 +20,7 @@ public enum PayTransferStatusEnum { @@ -20,7 +20,7 @@ public enum PayTransferStatusEnum {
20 20
21 SUCCESS(20, "转账成功"), 21 SUCCESS(20, "转账成功"),
22 /** 22 /**
23 - * 转账关闭 (失败,或者其它情况) 23 + * 转账关闭 (失败,或者其它情况) // TODO 改成 转账失败状态
24 */ 24 */
25 CLOSED(30, "转账关闭"); 25 CLOSED(30, "转账关闭");
26 26
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoTransferController.java
1 package cn.iocoder.yudao.module.pay.controller.admin.demo; 1 package cn.iocoder.yudao.module.pay.controller.admin.demo;
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.framework.common.pojo.PageParam;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO; 6 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO;
  7 +import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferRespVO;
  8 +import cn.iocoder.yudao.module.pay.convert.demo.PayDemoTransferConvert;
  9 +import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoTransferDO;
5 import cn.iocoder.yudao.module.pay.service.demo.PayDemoTransferService; 10 import cn.iocoder.yudao.module.pay.service.demo.PayDemoTransferService;
6 import io.swagger.v3.oas.annotations.Operation; 11 import io.swagger.v3.oas.annotations.Operation;
7 import io.swagger.v3.oas.annotations.tags.Tag; 12 import io.swagger.v3.oas.annotations.tags.Tag;
8 import org.springframework.validation.annotation.Validated; 13 import org.springframework.validation.annotation.Validated;
9 -import org.springframework.web.bind.annotation.PostMapping;  
10 -import org.springframework.web.bind.annotation.RequestBody;  
11 -import org.springframework.web.bind.annotation.RequestMapping;  
12 -import org.springframework.web.bind.annotation.RestController; 14 +import org.springframework.web.bind.annotation.*;
13 15
14 import javax.annotation.Resource; 16 import javax.annotation.Resource;
15 import javax.validation.Valid; 17 import javax.validation.Valid;
16 18
17 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 19 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
18 -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;  
19 20
20 @Tag(name = "管理后台 - 示例转账单") 21 @Tag(name = "管理后台 - 示例转账单")
21 @RestController 22 @RestController
@@ -27,7 +28,14 @@ public class PayDemoTransferController { @@ -27,7 +28,14 @@ public class PayDemoTransferController {
27 28
28 @PostMapping("/create") 29 @PostMapping("/create")
29 @Operation(summary = "创建示例转账订单") 30 @Operation(summary = "创建示例转账订单")
30 - public CommonResult<Long> createDemoOrder(@Valid @RequestBody PayDemoTransferCreateReqVO createReqVO) {  
31 - return success(demoTransferService.createDemoTransfer(getLoginUserId(), createReqVO)); 31 + public CommonResult<Long> createDemoTransfer(@Valid @RequestBody PayDemoTransferCreateReqVO createReqVO) {
  32 + return success(demoTransferService.createDemoTransfer(createReqVO));
  33 + }
  34 +
  35 + @GetMapping("/page")
  36 + @Operation(summary = "获得示例订单分页")
  37 + public CommonResult<PageResult<PayDemoTransferRespVO>> getDemoTransferPage(@Valid PageParam pageVO) {
  38 + PageResult<PayDemoTransferDO> pageResult = demoTransferService.getDemoTransferPage(pageVO);
  39 + return success(PayDemoTransferConvert.INSTANCE.convertPage(pageResult));
32 } 40 }
33 } 41 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/vo/transfer/PayDemoTransferCreateReqVO.java
@@ -11,6 +11,8 @@ import javax.validation.constraints.Min; @@ -11,6 +11,8 @@ import javax.validation.constraints.Min;
11 import javax.validation.constraints.NotBlank; 11 import javax.validation.constraints.NotBlank;
12 import javax.validation.constraints.NotNull; 12 import javax.validation.constraints.NotNull;
13 13
  14 +import static cn.iocoder.yudao.module.pay.enums.transfer.PayTransferTypeEnum.*;
  15 +
14 /** 16 /**
15 * @author jason 17 * @author jason
16 */ 18 */
@@ -28,29 +30,22 @@ public class PayDemoTransferCreateReqVO { @@ -28,29 +30,22 @@ public class PayDemoTransferCreateReqVO {
28 @Min(value = 1, message = "转账金额必须大于零") 30 @Min(value = 1, message = "转账金额必须大于零")
29 private Integer price; 31 private Integer price;
30 32
  33 + @Schema(description = "收款人姓名", example = "test1")
  34 + @NotBlank(message = "收款人姓名不能为空", groups = {Alipay.class})
  35 + private String userName;
  36 +
31 // ========== 支付宝转账相关字段 ========== 37 // ========== 支付宝转账相关字段 ==========
32 @Schema(description = "支付宝登录号,支持邮箱和手机号格式", example = "test1@@sandbox.com") 38 @Schema(description = "支付宝登录号,支持邮箱和手机号格式", example = "test1@@sandbox.com")
33 @NotBlank(message = "支付宝登录号不能为空", groups = {Alipay.class}) 39 @NotBlank(message = "支付宝登录号不能为空", groups = {Alipay.class})
34 private String alipayLogonId; 40 private String alipayLogonId;
35 41
36 - @Schema(description = "支付宝账号名称", example = "test1")  
37 - @NotBlank(message = "支付宝账号名称不能为空", groups = {Alipay.class})  
38 - private String alipayAccountName;  
39 -  
40 // ========== 微信转账相关字段 ========== 42 // ========== 微信转账相关字段 ==========
41 @Schema(description = "微信 openId", example = "oLefc4g5Gxx") 43 @Schema(description = "微信 openId", example = "oLefc4g5Gxx")
42 @NotBlank(message = "微信 openId 不能为空", groups = {WxPay.class}) 44 @NotBlank(message = "微信 openId 不能为空", groups = {WxPay.class})
43 private String openid; 45 private String openid;
44 46
45 - @Schema(description = "微信账号名称", example = "test2")  
46 - private String wxAccountName;  
47 47
48 // ========== 转账到银行卡和钱包相关字段 待补充 ========== 48 // ========== 转账到银行卡和钱包相关字段 待补充 ==========
49 - public interface WxPay {  
50 - }  
51 -  
52 - public interface Alipay {  
53 - }  
54 49
55 public void validate(Validator validator) { 50 public void validate(Validator validator) {
56 PayTransferTypeEnum transferType = PayTransferTypeEnum.typeOf(type); 51 PayTransferTypeEnum transferType = PayTransferTypeEnum.typeOf(type);
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/vo/transfer/PayDemoTransferRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +import java.time.LocalDateTime;
  7 +
  8 +/**
  9 + * 示例业务转账订单 Base VO,提供给添加、修改、详细的子 VO 使用
  10 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  11 + */
  12 +@Data
  13 +public class PayDemoTransferRespVO {
  14 +
  15 + @Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  16 + private Long id;
  17 +
  18 + @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  19 + private Long appId;
  20 +
  21 + @Schema(description = "转账金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "22338")
  22 + private Integer price;
  23 +
  24 + @Schema(description = "转账类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  25 + private Integer type;
  26 +
  27 + @Schema(description = "收款人姓名", example = "test")
  28 + private String userName;
  29 +
  30 + @Schema(description = "支付宝登录号", example = "32167")
  31 + private String alipayLogonId;
  32 +
  33 + @Schema(description = "微信 openId", example = "31139")
  34 + private String openid;
  35 +
  36 + @Schema(description = "转账状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
  37 + private Integer transferStatus;
  38 +
  39 + @Schema(description = "转账订单编号", example = "23695")
  40 + private Long payTransferId;
  41 +
  42 + @Schema(description = "转账支付成功渠道")
  43 + private String payChannelCode;
  44 +
  45 + @Schema(description = "转账支付时间")
  46 + private LocalDateTime transferTime;
  47 +}
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/PayTransferController.java
@@ -28,11 +28,11 @@ public class PayTransferController { @@ -28,11 +28,11 @@ public class PayTransferController {
28 @Resource 28 @Resource
29 private PayTransferService payTransferService; 29 private PayTransferService payTransferService;
30 30
31 - @PostMapping("/initiate")  
32 - @Operation(summary = "发起转账") 31 + @PostMapping("/create")
  32 + @Operation(summary = "创建转账单,发起转账")
33 // TODO @jason:权限的设置, 管理后台页面加的时候加一下 33 // TODO @jason:权限的设置, 管理后台页面加的时候加一下
34 - public CommonResult<PayTransferCreateRespVO> initiatePayTransfer(@Valid @RequestBody PayTransferCreateReqVO reqVO) {  
35 - PayTransferDO payTransfer = payTransferService.initiateTransfer(reqVO, getClientIP()); 34 + public CommonResult<PayTransferCreateRespVO> createPayTransfer(@Valid @RequestBody PayTransferCreateReqVO reqVO) {
  35 + PayTransferDO payTransfer = payTransferService.createTransfer(reqVO, getClientIP());
36 return success(new PayTransferCreateRespVO().setId(payTransfer.getId()).setStatus(payTransfer.getStatus())); 36 return success(new PayTransferCreateRespVO().setId(payTransfer.getId()).setStatus(payTransfer.getStatus()));
37 } 37 }
38 38
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferCreateReqVO.java
@@ -2,23 +2,24 @@ package cn.iocoder.yudao.module.pay.controller.admin.transfer.vo; @@ -2,23 +2,24 @@ package cn.iocoder.yudao.module.pay.controller.admin.transfer.vo;
2 2
3 import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; 3 import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
4 import cn.iocoder.yudao.framework.common.validation.InEnum; 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
5 -import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO; 5 +import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
6 import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferTypeEnum; 6 import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferTypeEnum;
7 import io.swagger.v3.oas.annotations.media.Schema; 7 import io.swagger.v3.oas.annotations.media.Schema;
8 import lombok.Data; 8 import lombok.Data;
9 9
10 import javax.validation.Validator; 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; 11 +import javax.validation.constraints.*;
15 import java.util.Map; 12 import java.util.Map;
16 13
  14 +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.NOT_IMPLEMENTED;
  15 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  16 +import static cn.iocoder.yudao.module.pay.enums.transfer.PayTransferTypeEnum.*;
  17 +
17 @Schema(description = "管理后台 - 发起转账 Request VO") 18 @Schema(description = "管理后台 - 发起转账 Request VO")
18 @Data 19 @Data
19 public class PayTransferCreateReqVO { 20 public class PayTransferCreateReqVO {
20 21
21 - @Schema(description = "应用编号不能为空", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 22 + @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
22 @NotNull(message = "应用编号不能为空") 23 @NotNull(message = "应用编号不能为空")
23 private Long appId; 24 private Long appId;
24 25
@@ -43,33 +44,30 @@ public class PayTransferCreateReqVO { @@ -43,33 +44,30 @@ public class PayTransferCreateReqVO {
43 @NotEmpty(message = "转账标题不能为空") 44 @NotEmpty(message = "转账标题不能为空")
44 private String subject; 45 private String subject;
45 46
  47 + @Schema(description = "收款人姓名", example = "test1")
  48 + @NotBlank(message = "收款人姓名不能为空", groups = {Alipay.class})
  49 + private String userName;
  50 +
46 @Schema(description = "支付宝登录号", example = "test1@sandbox.com") 51 @Schema(description = "支付宝登录号", example = "test1@sandbox.com")
47 - @NotBlank(message = "支付宝登录号不能为空", groups = {PayTransferTypeEnum.Alipay.class}) 52 + @NotBlank(message = "支付宝登录号不能为空", groups = {Alipay.class})
48 private String alipayLogonId; 53 private String alipayLogonId;
49 54
50 - @Schema(description = "支付宝账号名称", example = "test1")  
51 - @NotBlank(message = "支付宝账号名称不能为空", groups = {PayTransferTypeEnum.Alipay.class})  
52 - private String alipayAccountName;  
53 -  
54 @Schema(description = "微信 openId", example = "oLefc4g5Gxx") 55 @Schema(description = "微信 openId", example = "oLefc4g5Gxx")
55 - @NotBlank(message = "微信 openId 不能为空", groups = {PayTransferTypeEnum.WxPay.class}) 56 + @NotBlank(message = "微信 openId 不能为空", groups = {WxPay.class})
56 private String openid; 57 private String openid;
57 58
58 - @Schema(description = "微信账号名称", example = "test2")  
59 - private String wxAccountName;  
60 -  
61 @Schema(description = "转账渠道的额外参数") 59 @Schema(description = "转账渠道的额外参数")
62 private Map<String, String> channelExtras; 60 private Map<String, String> channelExtras;
63 61
64 public void validate(Validator validator) { 62 public void validate(Validator validator) {
65 - PayTransferTypeEnum transferType = PayTransferTypeEnum.typeOf(type); 63 + PayTransferTypeEnum transferType = typeOf(type);
66 switch (transferType) { 64 switch (transferType) {
67 case ALIPAY_BALANCE: { 65 case ALIPAY_BALANCE: {
68 - ValidationUtils.validate(validator, this, PayDemoTransferCreateReqVO.Alipay.class); 66 + ValidationUtils.validate(validator, this, Alipay.class);
69 break; 67 break;
70 } 68 }
71 case WX_BALANCE: { 69 case WX_BALANCE: {
72 - ValidationUtils.validate(validator, this, PayDemoTransferCreateReqVO.WxPay.class); 70 + ValidationUtils.validate(validator, this, WxPay.class);
73 break; 71 break;
74 } 72 }
75 default: { 73 default: {
@@ -78,4 +76,20 @@ public class PayTransferCreateReqVO { @@ -78,4 +76,20 @@ public class PayTransferCreateReqVO {
78 } 76 }
79 } 77 }
80 78
  79 + @AssertTrue(message = "转账类型和转账渠道不匹配")
  80 + public boolean isValidChannelCode() {
  81 + PayTransferTypeEnum transferType = typeOf(type);
  82 + switch (transferType) {
  83 + case ALIPAY_BALANCE: {
  84 + return PayChannelEnum.isAlipay(channelCode);
  85 + }
  86 + case WX_BALANCE:
  87 + case BANK_CARD:
  88 + case WALLET_BALANCE: {
  89 + throw exception(NOT_IMPLEMENTED);
  90 + }
  91 + }
  92 + return Boolean.FALSE;
  93 + }
  94 +
81 } 95 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/demo/PayDemoTransferConvert.java
1 package cn.iocoder.yudao.module.pay.convert.demo; 1 package cn.iocoder.yudao.module.pay.convert.demo;
2 2
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
3 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO; 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.PayDemoTransferRespVO;
4 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoTransferDO; 6 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoTransferDO;
5 import org.mapstruct.Mapper; 7 import org.mapstruct.Mapper;
6 import org.mapstruct.factory.Mappers; 8 import org.mapstruct.factory.Mappers;
@@ -14,4 +16,6 @@ public interface PayDemoTransferConvert { @@ -14,4 +16,6 @@ public interface PayDemoTransferConvert {
14 PayDemoTransferConvert INSTANCE = Mappers.getMapper(PayDemoTransferConvert.class); 16 PayDemoTransferConvert INSTANCE = Mappers.getMapper(PayDemoTransferConvert.class);
15 17
16 PayDemoTransferDO convert(PayDemoTransferCreateReqVO bean); 18 PayDemoTransferDO convert(PayDemoTransferCreateReqVO bean);
  19 +
  20 + PageResult<PayDemoTransferRespVO> convertPage(PageResult<PayDemoTransferDO> pageResult);
17 } 21 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/transfer/PayTransferConvert.java
@@ -6,7 +6,6 @@ import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTran @@ -6,7 +6,6 @@ import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTran
6 import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateReqVO; 6 import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateReqVO;
7 import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO; 7 import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
8 import org.mapstruct.Mapper; 8 import org.mapstruct.Mapper;
9 -import org.mapstruct.Mapping;  
10 import org.mapstruct.factory.Mappers; 9 import org.mapstruct.factory.Mappers;
11 10
12 @Mapper 11 @Mapper
@@ -16,7 +15,6 @@ public interface PayTransferConvert { @@ -16,7 +15,6 @@ public interface PayTransferConvert {
16 15
17 PayTransferDO convert(PayTransferCreateReqDTO dto); 16 PayTransferDO convert(PayTransferCreateReqDTO dto);
18 17
19 - @Mapping(source = "subject", target = "title")  
20 PayTransferUnifiedReqDTO convert2(PayTransferCreateReqDTO dto); 18 PayTransferUnifiedReqDTO convert2(PayTransferCreateReqDTO dto);
21 19
22 PayTransferCreateReqDTO convert(PayTransferCreateReqVO vo); 20 PayTransferCreateReqDTO convert(PayTransferCreateReqVO vo);
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/demo/PayDemoTransferDO.java
@@ -27,11 +27,6 @@ public class PayDemoTransferDO extends BaseDO { @@ -27,11 +27,6 @@ public class PayDemoTransferDO extends BaseDO {
27 private Long id; 27 private Long id;
28 28
29 /** 29 /**
30 - * 用户编号  
31 - */  
32 - private Long userId;  
33 -  
34 - /**  
35 * 应用编号 30 * 应用编号
36 * 31 *
37 * 关联 {@link PayAppDO#getId()} 32 * 关联 {@link PayAppDO#getId()}
@@ -39,11 +34,6 @@ public class PayDemoTransferDO extends BaseDO { @@ -39,11 +34,6 @@ public class PayDemoTransferDO extends BaseDO {
39 private Long appId; 34 private Long appId;
40 35
41 /** 36 /**
42 - * 转账金额,单位:分  
43 - */  
44 - private Integer price;  
45 -  
46 - /**  
47 * 转账类型 37 * 转账类型
48 * <p> 38 * <p>
49 * 枚举 {@link PayTransferTypeEnum} 39 * 枚举 {@link PayTransferTypeEnum}
@@ -51,24 +41,24 @@ public class PayDemoTransferDO extends BaseDO { @@ -51,24 +41,24 @@ public class PayDemoTransferDO extends BaseDO {
51 private Integer type; 41 private Integer type;
52 42
53 /** 43 /**
54 - * 支付宝登录号 44 + * 转账金额,单位:分
55 */ 45 */
56 - private String alipayLogonId; 46 + private Integer price;
57 47
58 /** 48 /**
59 - * 支付宝账号名称 49 + * 收款人姓名
60 */ 50 */
61 - private String alipayAccountName; 51 + private String userName;
62 52
63 /** 53 /**
64 - * 微信 openId 54 + * 支付宝登录号
65 */ 55 */
66 - private String openid; 56 + private String alipayLogonId;
67 57
68 /** 58 /**
69 - * 微信账号名称 59 + * 微信 openId
70 */ 60 */
71 - private String wxAccountName; 61 + private String openid;
72 62
73 /** 63 /**
74 * 转账状态 64 * 转账状态
@@ -76,7 +66,7 @@ public class PayDemoTransferDO extends BaseDO { @@ -76,7 +66,7 @@ public class PayDemoTransferDO extends BaseDO {
76 private Integer transferStatus; 66 private Integer transferStatus;
77 67
78 /** 68 /**
79 - * 转账订单编号 69 + * 转账单编号
80 */ 70 */
81 private Long payTransferId; 71 private Long payTransferId;
82 72
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/transfer/PayTransferDO.java
@@ -85,6 +85,12 @@ public class PayTransferDO extends BaseDO { @@ -85,6 +85,12 @@ public class PayTransferDO extends BaseDO {
85 * 转账金额,单位:分 85 * 转账金额,单位:分
86 */ 86 */
87 private Integer price; 87 private Integer price;
  88 +
  89 + /**
  90 + * 收款人姓名
  91 + */
  92 + private String userName;
  93 +
88 /** 94 /**
89 * 转账状态 95 * 转账状态
90 * 96 *
@@ -103,10 +109,6 @@ public class PayTransferDO extends BaseDO { @@ -103,10 +109,6 @@ public class PayTransferDO extends BaseDO {
103 */ 109 */
104 private String alipayLogonId; 110 private String alipayLogonId;
105 111
106 - /**  
107 - * 支付宝账号名称  
108 - */  
109 - private String alipayAccountName;  
110 112
111 // ========== 微信转账相关字段 ========== 113 // ========== 微信转账相关字段 ==========
112 /** 114 /**
@@ -114,11 +116,6 @@ public class PayTransferDO extends BaseDO { @@ -114,11 +116,6 @@ public class PayTransferDO extends BaseDO {
114 */ 116 */
115 private String openid; 117 private String openid;
116 118
117 - /**  
118 - * 微信账号名称  
119 - */  
120 - private String wxAccountName;  
121 -  
122 // ========== 其它字段 ========== 119 // ========== 其它字段 ==========
123 120
124 /** 121 /**
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/transfer/PayTransferExtensionDO.java deleted
1 -package cn.iocoder.yudao.module.pay.dal.dataobject.transfer;  
2 -  
3 -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;  
4 -import com.baomidou.mybatisplus.annotation.KeySequence;  
5 -import com.baomidou.mybatisplus.annotation.TableField;  
6 -import com.baomidou.mybatisplus.annotation.TableId;  
7 -import com.baomidou.mybatisplus.annotation.TableName;  
8 -import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;  
9 -import lombok.Data;  
10 -  
11 -import java.util.Map;  
12 -  
13 -// TODO @jason:转账是不是类似 refund,不用拓展单呀?支付做拓展单的原因,是因为它存在不确定性,可以切换多种;转账和退款,都是明确方式的;  
14 -// @芋艿 转账是不是也存在多种方式。 例如转账到银行卡。 可以使用微信,也可以使用支付宝。 支付宝账号余额不够,可以切换到微信;  
15 -// TODO @jason:发起了,就不允许调整了,类似退款哈;  
16 -/**  
17 - * 转账拓展单 DO  
18 - *  
19 - * @author jason  
20 - */  
21 -@TableName(value ="pay_transfer_extension",autoResultMap = true)  
22 -@KeySequence("pay_transfer_extension_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。  
23 -@Data  
24 -public class PayTransferExtensionDO extends BaseDO {  
25 -  
26 - /**  
27 - * 编号  
28 - */  
29 - @TableId  
30 - private Long id;  
31 -  
32 - /**  
33 - * 转账单号  
34 - */  
35 - private String no;  
36 -  
37 - /**  
38 - * 转账单编号  
39 - */  
40 - private Long transferId;  
41 -  
42 - /**  
43 - * 转账渠道编号  
44 - */  
45 - private Long channelId;  
46 -  
47 - /**  
48 - * 转账渠道编码  
49 - */  
50 - private String channelCode;  
51 -  
52 - /**  
53 - * 支付渠道的额外参数  
54 - */  
55 - @TableField(typeHandler = JacksonTypeHandler.class)  
56 - private Map<String, String> channelExtras;  
57 -  
58 - /**  
59 - * 转账状态  
60 - */  
61 - private Integer status;  
62 -  
63 - /**  
64 - * 支付渠道异步通知的内容  
65 - */  
66 - private String channelNotifyData;  
67 -  
68 -}  
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/demo/PayDemoTransferMapper.java
1 package cn.iocoder.yudao.module.pay.dal.mysql.demo; 1 package cn.iocoder.yudao.module.pay.dal.mysql.demo;
2 2
3 -import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoTransferDO; 3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 5 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  6 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  7 +import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoTransferDO;
5 import org.apache.ibatis.annotations.Mapper; 8 import org.apache.ibatis.annotations.Mapper;
6 9
7 @Mapper 10 @Mapper
8 public interface PayDemoTransferMapper extends BaseMapperX<PayDemoTransferDO> { 11 public interface PayDemoTransferMapper extends BaseMapperX<PayDemoTransferDO> {
9 12
  13 + default PageResult<PayDemoTransferDO> selectPage(PageParam pageParam){
  14 + return selectPage(pageParam, new LambdaQueryWrapperX<PayDemoTransferDO>()
  15 + .orderByDesc(PayDemoTransferDO::getId));
  16 + }
10 } 17 }
11 \ No newline at end of file 18 \ No newline at end of file
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/transfer/PayTransferExtensionMapper.java deleted
1 -package cn.iocoder.yudao.module.pay.dal.mysql.transfer;  
2 -  
3 -import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferExtensionDO;  
4 -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;  
5 -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;  
6 -import org.apache.ibatis.annotations.Mapper;  
7 -  
8 -import java.util.List;  
9 -  
10 -@Mapper  
11 -public interface PayTransferExtensionMapper extends BaseMapperX<PayTransferExtensionDO> {  
12 -  
13 - default PayTransferExtensionDO selectByNo(String no){  
14 - return selectOne(PayTransferExtensionDO::getNo, no);  
15 - }  
16 -  
17 - default int updateByIdAndStatus(Long id, List<Integer> whereStatuses, PayTransferExtensionDO updateObj) {  
18 - return update(updateObj, new LambdaQueryWrapper<PayTransferExtensionDO>()  
19 - .eq(PayTransferExtensionDO::getId, id).in(PayTransferExtensionDO::getStatus, whereStatuses));  
20 - }  
21 -  
22 -}  
23 -  
24 -  
25 -  
26 -  
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoTransferService.java
1 package cn.iocoder.yudao.module.pay.service.demo; 1 package cn.iocoder.yudao.module.pay.service.demo;
2 2
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
3 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.dal.dataobject.demo.PayDemoTransferDO;
4 7
5 import javax.validation.Valid; 8 import javax.validation.Valid;
6 9
@@ -12,11 +15,17 @@ import javax.validation.Valid; @@ -12,11 +15,17 @@ import javax.validation.Valid;
12 public interface PayDemoTransferService { 15 public interface PayDemoTransferService {
13 16
14 /** 17 /**
15 - * 创建转账单 18 + * 创建转账业务示例订单
16 * 19 *
17 - * @param userId 用户编号  
18 * @param createReqVO 创建信息 20 * @param createReqVO 创建信息
19 * @return 编号 21 * @return 编号
20 */ 22 */
21 - Long createDemoTransfer(Long userId, @Valid PayDemoTransferCreateReqVO createReqVO); 23 + Long createDemoTransfer(@Valid PayDemoTransferCreateReqVO createReqVO);
  24 +
  25 + /**
  26 + * 获得转账业务示例订单分页
  27 + *
  28 + * @param pageVO 分页查询参数
  29 + */
  30 + PageResult<PayDemoTransferDO> getDemoTransferPage(PageParam pageVO);
22 } 31 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoTransferServiceImpl.java
1 package cn.iocoder.yudao.module.pay.service.demo; 1 package cn.iocoder.yudao.module.pay.service.demo;
2 2
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
3 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;
4 import cn.iocoder.yudao.module.pay.convert.demo.PayDemoTransferConvert; 6 import cn.iocoder.yudao.module.pay.convert.demo.PayDemoTransferConvert;
5 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoTransferDO; 7 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoTransferDO;
6 import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoTransferMapper; 8 import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoTransferMapper;
7 import org.springframework.stereotype.Service; 9 import org.springframework.stereotype.Service;
8 -import org.springframework.transaction.annotation.Transactional;  
9 import org.springframework.validation.annotation.Validated; 10 import org.springframework.validation.annotation.Validated;
10 11
11 import javax.annotation.Resource; 12 import javax.annotation.Resource;
@@ -35,14 +36,18 @@ public class PayDemoTransferServiceImpl implements PayDemoTransferService { @@ -35,14 +36,18 @@ public class PayDemoTransferServiceImpl implements PayDemoTransferService {
35 private Validator validator; 36 private Validator validator;
36 37
37 @Override 38 @Override
38 - @Transactional(rollbackFor = Exception.class)  
39 - public Long createDemoTransfer(Long userId, @Valid PayDemoTransferCreateReqVO vo) { 39 + public Long createDemoTransfer(@Valid PayDemoTransferCreateReqVO vo) {
40 // 1 校验参数 40 // 1 校验参数
41 vo.validate(validator); 41 vo.validate(validator);
42 // 2 保存示例转账业务表 42 // 2 保存示例转账业务表
43 PayDemoTransferDO demoTransfer = PayDemoTransferConvert.INSTANCE.convert(vo) 43 PayDemoTransferDO demoTransfer = PayDemoTransferConvert.INSTANCE.convert(vo)
44 - .setUserId(userId).setAppId(TRANSFER_APP_ID).setTransferStatus(WAITING.getStatus()); 44 + .setAppId(TRANSFER_APP_ID).setTransferStatus(WAITING.getStatus());
45 demoTransferMapper.insert(demoTransfer); 45 demoTransferMapper.insert(demoTransfer);
46 return demoTransfer.getId(); 46 return demoTransfer.getId();
47 } 47 }
  48 +
  49 + @Override
  50 + public PageResult<PayDemoTransferDO> getDemoTransferPage(PageParam pageVO) {
  51 + return demoTransferMapper.selectPage(pageVO);
  52 + }
48 } 53 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferService.java
@@ -14,18 +14,18 @@ import javax.validation.Valid; @@ -14,18 +14,18 @@ import javax.validation.Valid;
14 public interface PayTransferService { 14 public interface PayTransferService {
15 15
16 /** 16 /**
17 - * 发起转账 17 + * 创建转账单,并发起转账
18 * 18 *
19 - * 此时,会发起支付渠道的调用 19 + * 此时,会发起转账渠道的调用
20 * 20 *
21 * @param reqVO 请求 21 * @param reqVO 请求
22 * @param userIp 用户 ip 22 * @param userIp 用户 ip
23 * @return 渠道的返回结果 23 * @return 渠道的返回结果
24 */ 24 */
25 - PayTransferDO initiateTransfer(@Valid PayTransferCreateReqVO reqVO, String userIp); 25 + PayTransferDO createTransfer(@Valid PayTransferCreateReqVO reqVO, String userIp);
26 26
27 /** 27 /**
28 - * 创建转账单 28 + * 创建转账单,并发起转账
29 * 29 *
30 * @param reqDTO 创建请求 30 * @param reqDTO 创建请求
31 * @return 转账单编号 31 * @return 转账单编号
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceImpl.java
@@ -2,22 +2,18 @@ package cn.iocoder.yudao.module.pay.service.transfer; @@ -2,22 +2,18 @@ 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.extra.spring.SpringUtil; 4 import cn.hutool.extra.spring.SpringUtil;
  5 +import cn.iocoder.yudao.framework.common.exception.ServiceException;
5 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 6 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
6 import cn.iocoder.yudao.framework.pay.core.client.PayClient; 7 import cn.iocoder.yudao.framework.pay.core.client.PayClient;
7 import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO; 8 import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
8 import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO; 9 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;  
11 import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferStatusRespEnum; 10 import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferStatusRespEnum;
12 -import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;  
13 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO; 11 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
14 import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateReqVO; 12 import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateReqVO;
15 -import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;  
16 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; 13 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
17 import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO; 14 import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
18 import cn.iocoder.yudao.module.pay.dal.mysql.transfer.PayTransferMapper; 15 import cn.iocoder.yudao.module.pay.dal.mysql.transfer.PayTransferMapper;
19 import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; 16 import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO;
20 -import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum;  
21 import cn.iocoder.yudao.module.pay.service.app.PayAppService; 17 import cn.iocoder.yudao.module.pay.service.app.PayAppService;
22 import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; 18 import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
23 import lombok.extern.slf4j.Slf4j; 19 import lombok.extern.slf4j.Slf4j;
@@ -26,6 +22,7 @@ import org.springframework.transaction.annotation.Transactional; @@ -26,6 +22,7 @@ import org.springframework.transaction.annotation.Transactional;
26 22
27 import javax.annotation.Resource; 23 import javax.annotation.Resource;
28 import javax.validation.Validator; 24 import javax.validation.Validator;
  25 +import java.util.Objects;
29 26
30 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 27 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
31 import static cn.iocoder.yudao.module.pay.convert.transfer.PayTransferConvert.INSTANCE; 28 import static cn.iocoder.yudao.module.pay.convert.transfer.PayTransferConvert.INSTANCE;
@@ -33,6 +30,7 @@ import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; @@ -33,6 +30,7 @@ import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
33 import static cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum.*; 30 import static cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum.*;
34 31
35 // TODO @jason:等彻底实现完,单测写写; 32 // TODO @jason:等彻底实现完,单测写写;
  33 +
36 /** 34 /**
37 * 转账 Service 实现类 35 * 转账 Service 实现类
38 * 36 *
@@ -56,28 +54,24 @@ public class PayTransferServiceImpl implements PayTransferService { @@ -56,28 +54,24 @@ public class PayTransferServiceImpl implements PayTransferService {
56 private Validator validator; 54 private Validator validator;
57 55
58 @Override 56 @Override
59 - @Transactional(rollbackFor = Exception.class)  
60 - public PayTransferDO initiateTransfer(PayTransferCreateReqVO reqVO, String userIp) {  
61 - // 1.1 校验参数 57 + public PayTransferDO createTransfer(PayTransferCreateReqVO reqVO, String userIp) {
  58 + // 1. 校验参数
62 reqVO.validate(validator); 59 reqVO.validate(validator);
63 - // todo 使用 AssertTrue  
64 - validateChannelCodeAndTypeMatch(reqVO.getChannelCode(), reqVO.getType());  
65 - // 1.2 校验转账单是否可以创建  
66 - validateTransferCanCreate(reqVO.getAppId(), reqVO.getMerchantTransferId()); 60 +
67 // 2. 创建转账单,发起转账 61 // 2. 创建转账单,发起转账
68 PayTransferCreateReqDTO req = INSTANCE.convert(reqVO).setUserIp(userIp); 62 PayTransferCreateReqDTO req = INSTANCE.convert(reqVO).setUserIp(userIp);
69 Long transferId = createTransfer(req); 63 Long transferId = createTransfer(req);
  64 +
70 // 3. 返回转账单 65 // 3. 返回转账单
71 return getTransfer(transferId); 66 return getTransfer(transferId);
72 } 67 }
73 68
74 @Override 69 @Override
75 - @Transactional(rollbackFor = Exception.class)  
76 public Long createTransfer(PayTransferCreateReqDTO reqDTO) { 70 public Long createTransfer(PayTransferCreateReqDTO reqDTO) {
77 // 1.1 校验转账单是否可以提交 71 // 1.1 校验转账单是否可以提交
78 - validateTransferExist(reqDTO.getAppId(), reqDTO.getMerchantTransferId()); 72 + validateTransferCanCreate(reqDTO.getAppId(), reqDTO.getMerchantTransferId());
79 // 1.2 校验 App 73 // 1.2 校验 App
80 - PayAppDO appDO = appService.validPayApp(reqDTO.getAppId()); 74 + appService.validPayApp(reqDTO.getAppId());
81 // 1.3 校验支付渠道是否有效 75 // 1.3 校验支付渠道是否有效
82 PayChannelDO channel = channelService.validPayChannel(reqDTO.getAppId(), reqDTO.getChannelCode()); 76 PayChannelDO channel = channelService.validPayChannel(reqDTO.getAppId(), reqDTO.getChannelCode());
83 PayClient client = channelService.getPayClient(channel.getId()); 77 PayClient client = channelService.getPayClient(channel.getId());
@@ -90,19 +84,28 @@ public class PayTransferServiceImpl implements PayTransferService { @@ -90,19 +84,28 @@ public class PayTransferServiceImpl implements PayTransferService {
90 PayTransferDO transfer = INSTANCE.convert(reqDTO) 84 PayTransferDO transfer = INSTANCE.convert(reqDTO)
91 .setChannelId(channel.getId()) 85 .setChannelId(channel.getId())
92 .setNo(no).setStatus(WAITING.getStatus()) 86 .setNo(no).setStatus(WAITING.getStatus())
93 - .setNotifyUrl(appDO.getRefundNotifyUrl()); // TODO 需要加个transfer Notify url 87 + .setNotifyUrl("http://127.0.0.1:48080/admin-api/pay/todo"); // TODO 需要加个transfer Notify url
94 transferMapper.insert(transfer); 88 transferMapper.insert(transfer);
  89 + PayTransferRespDTO unifiedTransferResp = null;
95 try { 90 try {
96 // 3. 调用三方渠道发起转账 91 // 3. 调用三方渠道发起转账
97 PayTransferUnifiedReqDTO transferUnifiedReq = INSTANCE.convert2(reqDTO) 92 PayTransferUnifiedReqDTO transferUnifiedReq = INSTANCE.convert2(reqDTO)
98 .setOutTransferNo(no); 93 .setOutTransferNo(no);
99 - PayTransferRespDTO unifiedTransferResp = client.unifiedTransfer(transferUnifiedReq); 94 + unifiedTransferResp = client.unifiedTransfer(transferUnifiedReq);
  95 + } catch (ServiceException ex) {
  96 + // 业务异常.直接返回转账失败的结果
  97 + log.error("[createTransfer][转账 id({}) requestDTO({}) 发生业务异常]", transfer.getId(), reqDTO, ex);
  98 + unifiedTransferResp = PayTransferRespDTO.closedOf("", "", no, ex);
  99 + } catch (Throwable e) {
  100 + // 注意这里仅打印异常,不进行抛出。
  101 + // 原因是:虽然调用支付渠道进行转账发生异常(网络请求超时),实际转账成功。这个结果,后续通过转账回调、或者转账轮询可以拿到。
  102 + // TODO 需要加转账回调业务接口 和 转账轮询未实现
  103 + // 最终,在异常的情况下,支付中心会异步回调业务的转账回调接口,提供转账结果
  104 + log.error("[createTransfer][转账 id({}) requestDTO({}) 发生异常]", transfer.getId(), reqDTO, e);
  105 + }
  106 + if (Objects.nonNull(unifiedTransferResp)) {
100 // 4. 通知转账结果 107 // 4. 通知转账结果
101 getSelf().notifyTransfer(channel, unifiedTransferResp); 108 getSelf().notifyTransfer(channel, unifiedTransferResp);
102 - } catch (PayException e) {  
103 - // 这里仅打印异常,不进行抛出。  
104 - // TODO 说明  
105 - log.error("[createTransfer][转账 id({}) requestDTO({}) 发生异常]", transfer.getId(), reqDTO, e);  
106 } 109 }
107 return transfer.getId(); 110 return transfer.getId();
108 } 111 }
@@ -127,16 +130,9 @@ public class PayTransferServiceImpl implements PayTransferService { @@ -127,16 +130,9 @@ public class PayTransferServiceImpl implements PayTransferService {
127 // TODO IN_PROGRESS 待处理 130 // TODO IN_PROGRESS 待处理
128 } 131 }
129 132
130 - private void validateTransferExist(Long appId, String merchantTransferId ) { 133 + private void validateTransferCanCreate(Long appId, String merchantTransferId) {
131 PayTransferDO transfer = transferMapper.selectByAppIdAndMerchantTransferId(appId, merchantTransferId); 134 PayTransferDO transfer = transferMapper.selectByAppIdAndMerchantTransferId(appId, merchantTransferId);
132 - if (transfer != null) { // 是否存在  
133 - throw exception(PAY_TRANSFER_EXISTS);  
134 - }  
135 - }  
136 -  
137 - private void validateTransferCanCreate(Long appId, String merchantTransferId ) {  
138 - PayTransferDO transfer = transferMapper.selectByAppIdAndMerchantTransferId(appId, merchantTransferId);  
139 - if (transfer != null) { // 是否存在 135 + if (transfer != null) { // 是否存在
140 throw exception(PAY_MERCHANT_TRANSFER_EXISTS); 136 throw exception(PAY_MERCHANT_TRANSFER_EXISTS);
141 } 137 }
142 } 138 }
@@ -192,7 +188,7 @@ public class PayTransferServiceImpl implements PayTransferService { @@ -192,7 +188,7 @@ public class PayTransferServiceImpl implements PayTransferService {
192 // 2.更新 188 // 2.更新
193 int updateCount = transferMapper.updateByIdAndStatus(transfer.getId(), 189 int updateCount = transferMapper.updateByIdAndStatus(transfer.getId(),
194 CollUtil.newArrayList(WAITING.getStatus(), IN_PROGRESS.getStatus()), 190 CollUtil.newArrayList(WAITING.getStatus(), IN_PROGRESS.getStatus()),
195 - new PayTransferDO().setStatus(CLOSED.getStatus()) .setChannelId(channel.getId()) 191 + new PayTransferDO().setStatus(CLOSED.getStatus()).setChannelId(channel.getId())
196 .setChannelCode(channel.getCode()).setChannelTransferNo(notify.getChannelTransferNo()) 192 .setChannelCode(channel.getCode()).setChannelTransferNo(notify.getChannelTransferNo())
197 .setChannelErrorCode(notify.getChannelErrorCode()).setChannelErrorMsg(notify.getChannelErrorMsg()) 193 .setChannelErrorCode(notify.getChannelErrorCode()).setChannelErrorMsg(notify.getChannelErrorMsg())
198 .setChannelNotifyData(JsonUtils.toJsonString(notify))); 194 .setChannelNotifyData(JsonUtils.toJsonString(notify)));
@@ -204,52 +200,7 @@ public class PayTransferServiceImpl implements PayTransferService { @@ -204,52 +200,7 @@ public class PayTransferServiceImpl implements PayTransferService {
204 200
205 private void notifyTransferClosed(PayChannelDO channel, PayTransferRespDTO notify) { 201 private void notifyTransferClosed(PayChannelDO channel, PayTransferRespDTO notify) {
206 // 更新 PayTransferDO 转账关闭 202 // 更新 PayTransferDO 转账关闭
207 - updateTransferClosed(channel,notify);  
208 - }  
209 -  
210 - private void validateChannelCodeAndTypeMatch(String channelCode, Integer type) {  
211 - PayTransferTypeEnum transferType = PayTransferTypeEnum.typeOf(type);  
212 - switch (transferType) {  
213 - case ALIPAY_BALANCE: {  
214 - if (!PayChannelEnum.isAlipay(channelCode)) {  
215 - throw exception(PAY_TRANSFER_TYPE_AND_CHANNEL_NOT_MATCH);  
216 - }  
217 - break;  
218 - }  
219 - case WX_BALANCE:  
220 - case BANK_CARD:  
221 - case WALLET_BALANCE: {  
222 - throw new UnsupportedOperationException("待实现");  
223 - }  
224 - }  
225 - }  
226 -  
227 - private PayChannelDO validateChannelCanSubmit(Long appId, String channelCode) {  
228 - // 校验 App  
229 - appService.validPayApp(appId);  
230 - // 校验支付渠道是否有效  
231 - PayChannelDO channel = channelService.validPayChannel(appId, channelCode);  
232 - PayClient client = channelService.getPayClient(channel.getId());  
233 - if (client == null) {  
234 - log.error("[validateChannelCanSubmit][渠道编号({}) 找不到对应的支付客户端]", channel.getId());  
235 - throw exception(CHANNEL_NOT_FOUND);  
236 - }  
237 - return channel;  
238 - }  
239 -  
240 - private PayTransferDO validateTransferExist(Long id) {  
241 - PayTransferDO transfer = transferMapper.selectById(id);  
242 - if (transfer == null) { // 是否存在  
243 - throw exception(PAY_TRANSFER_NOT_FOUND);  
244 - }  
245 - if (PayTransferStatusEnum.isSuccess(transfer.getStatus())) {  
246 - throw exception(PAY_TRANSFER_STATUS_IS_SUCCESS);  
247 - }  
248 - if (!PayTransferStatusEnum.isWaiting(transfer.getStatus())) {  
249 - throw exception(PAY_TRANSFER_STATUS_IS_NOT_WAITING);  
250 - }  
251 - // TODO 查询拓展单是否未已转账和转账中  
252 - return transfer; 203 + updateTransferClosed(channel, notify);
253 } 204 }
254 205
255 /** 206 /**