Commit 09d45e639348aaf944da43b6628127a0dd05e165

Authored by jason
1 parent cf114409

转账 - 增加转账通知

Showing 17 changed files with 160 additions and 31 deletions
sql/mysql/pay_wallet.sql
@@ -245,4 +245,12 @@ INSERT INTO system_menu( @@ -245,4 +245,12 @@ INSERT INTO system_menu(
245 VALUES ( 245 VALUES (
246 '转账订单', '', 2, 3, 1117, 246 '转账订单', '', 2, 3, 1117,
247 'transfer', 'ep:credit-card', 'pay/transfer/index', 0, 'PayTransfer' 247 'transfer', 'ep:credit-card', 'pay/transfer/index', 0, 'PayTransfer'
248 - );  
249 \ No newline at end of file 248 \ No newline at end of file
  249 + );
  250 +
  251 +-- 转账通知脚本
  252 +
  253 +ALTER TABLE `pay_app`
  254 + ADD COLUMN `transfer_notify_url` varchar(1024) NOT NULL COMMENT '转账结果的回调地址' AFTER `refund_notify_url`;
  255 +ALTER TABLE `pay_notify_task`
  256 + MODIFY COLUMN `merchant_order_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '商户订单编号' AFTER `status`,
  257 + ADD COLUMN `merchant_transfer_id` varchar(64) COMMENT '商户转账单编号' AFTER `merchant_order_id`;
250 \ No newline at end of file 258 \ No newline at end of file
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/notify/dto/PayTransferNotifyReqDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.pay.api.notify.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import javax.validation.constraints.NotEmpty;
  6 +import javax.validation.constraints.NotNull;
  7 +
  8 +/**
  9 + * 转账单的通知 Request DTO
  10 + *
  11 + * @author jason
  12 + */
  13 +@Data
  14 +public class PayTransferNotifyReqDTO {
  15 +
  16 + /**
  17 + * 商户转账单号
  18 + */
  19 + @NotEmpty(message = "商户转账单号不能为空")
  20 + private String merchantTransferId;
  21 +
  22 + /**
  23 + * 转账订单编号
  24 + */
  25 + @NotNull(message = "转账订单编号不能为空")
  26 + private Long payTransferId;
  27 +}
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java
@@ -65,12 +65,13 @@ public interface ErrorCodeConstants { @@ -65,12 +65,13 @@ public interface ErrorCodeConstants {
65 65
66 // ========== 转账模块 1-007-009-000 ========== 66 // ========== 转账模块 1-007-009-000 ==========
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_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 +
74 // ========== 示例订单 1-007-900-000 ========== 75 // ========== 示例订单 1-007-900-000 ==========
75 ErrorCode DEMO_ORDER_NOT_FOUND = new ErrorCode(1_007_900_000, "示例订单不存在"); 76 ErrorCode DEMO_ORDER_NOT_FOUND = new ErrorCode(1_007_900_000, "示例订单不存在");
76 ErrorCode DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1_007_900_001, "示例订单更新支付状态失败,订单不是【未支付】状态"); 77 ErrorCode DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1_007_900_001, "示例订单更新支付状态失败,订单不是【未支付】状态");
@@ -84,4 +85,8 @@ public interface ErrorCodeConstants { @@ -84,4 +85,8 @@ public interface ErrorCodeConstants {
84 ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR = new ErrorCode(1_007_900_009, "发起退款失败,退款单编号不匹配"); 85 ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR = new ErrorCode(1_007_900_009, "发起退款失败,退款单编号不匹配");
85 ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_PRICE_NOT_MATCH = new ErrorCode(1_007_900_010, "发起退款失败,退款单金额不匹配"); 86 ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_PRICE_NOT_MATCH = new ErrorCode(1_007_900_010, "发起退款失败,退款单金额不匹配");
86 87
  88 + // ========== 示例转账订单 1-007-901-001 ==========
  89 + ErrorCode DEMO_TRANSFER_NOT_FOUND = new ErrorCode(1_007_901_001, "示例转账单不存在");
  90 + ErrorCode DEMO_TRANSFER_FAIL_TRANSFER_ID_ERROR = new ErrorCode(1_007_901_002, "转账失败,转账单编号不匹配");
  91 + ErrorCode DEMO_TRANSFER_FAIL_PRICE_NOT_MATCH = new ErrorCode(1_007_901_003, "转账失败,转账单金额不匹配");
87 } 92 }
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/notify/PayNotifyTypeEnum.java
@@ -14,6 +14,7 @@ public enum PayNotifyTypeEnum { @@ -14,6 +14,7 @@ public enum PayNotifyTypeEnum {
14 14
15 ORDER(1, "支付单"), 15 ORDER(1, "支付单"),
16 REFUND(2, "退款单"), 16 REFUND(2, "退款单"),
  17 + TRANSFER(3, "转账单")
17 ; 18 ;
18 19
19 /** 20 /**
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoOrderController.java
@@ -6,8 +6,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -6,8 +6,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; 6 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
7 import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO; 7 import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
8 import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO; 8 import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO;
9 -import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO;  
10 -import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderRespVO; 9 +import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.order.PayDemoOrderCreateReqVO;
  10 +import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.order.PayDemoOrderRespVO;
11 import cn.iocoder.yudao.module.pay.convert.demo.PayDemoOrderConvert; 11 import cn.iocoder.yudao.module.pay.convert.demo.PayDemoOrderConvert;
12 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO; 12 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
13 import cn.iocoder.yudao.module.pay.service.demo.PayDemoOrderService; 13 import cn.iocoder.yudao.module.pay.service.demo.PayDemoOrderService;
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoTransferController.java
@@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.pay.controller.admin.demo; @@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.pay.controller.admin.demo;
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; 4 import cn.iocoder.yudao.framework.common.pojo.PageParam;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
  7 +import cn.iocoder.yudao.module.pay.api.notify.dto.PayTransferNotifyReqDTO;
6 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO; 8 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; 9 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferRespVO;
8 import cn.iocoder.yudao.module.pay.convert.demo.PayDemoTransferConvert; 10 import cn.iocoder.yudao.module.pay.convert.demo.PayDemoTransferConvert;
@@ -14,6 +16,7 @@ import org.springframework.validation.annotation.Validated; @@ -14,6 +16,7 @@ import org.springframework.validation.annotation.Validated;
14 import org.springframework.web.bind.annotation.*; 16 import org.springframework.web.bind.annotation.*;
15 17
16 import javax.annotation.Resource; 18 import javax.annotation.Resource;
  19 +import javax.annotation.security.PermitAll;
17 import javax.validation.Valid; 20 import javax.validation.Valid;
18 21
19 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 22 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -33,9 +36,19 @@ public class PayDemoTransferController { @@ -33,9 +36,19 @@ public class PayDemoTransferController {
33 } 36 }
34 37
35 @GetMapping("/page") 38 @GetMapping("/page")
36 - @Operation(summary = "获得示例订单分页") 39 + @Operation(summary = "获得示例转账订单分页")
37 public CommonResult<PageResult<PayDemoTransferRespVO>> getDemoTransferPage(@Valid PageParam pageVO) { 40 public CommonResult<PageResult<PayDemoTransferRespVO>> getDemoTransferPage(@Valid PageParam pageVO) {
38 PageResult<PayDemoTransferDO> pageResult = demoTransferService.getDemoTransferPage(pageVO); 41 PageResult<PayDemoTransferDO> pageResult = demoTransferService.getDemoTransferPage(pageVO);
39 return success(PayDemoTransferConvert.INSTANCE.convertPage(pageResult)); 42 return success(PayDemoTransferConvert.INSTANCE.convertPage(pageResult));
40 } 43 }
  44 +
  45 + @PostMapping("/update-status")
  46 + @Operation(summary = "更新示例转账订单的转账状态") // 由 pay-module 转账服务,进行回调
  47 + @PermitAll // 无需登录,安全由 PayDemoTransferService 内部校验实现
  48 + @OperateLog(enable = false) // 禁用操作日志,因为没有操作人
  49 + public CommonResult<Boolean> updateDemoTransferStatus(@RequestBody PayTransferNotifyReqDTO notifyReqDTO) {
  50 + demoTransferService.updateDemoTransferStatus(Long.valueOf(notifyReqDTO.getMerchantTransferId()),
  51 + notifyReqDTO.getPayTransferId());
  52 + return success(true);
  53 + }
41 } 54 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/vo/PayDemoOrderCreateReqVO.java renamed to yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/vo/order/PayDemoOrderCreateReqVO.java
1 -package cn.iocoder.yudao.module.pay.controller.admin.demo.vo; 1 +package cn.iocoder.yudao.module.pay.controller.admin.demo.vo.order;
2 2
3 -import lombok.*;  
4 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
5 5
6 -import javax.validation.constraints.NotEmpty;  
7 import javax.validation.constraints.NotNull; 6 import javax.validation.constraints.NotNull;
8 7
9 @Schema(description = "管理后台 - 示例订单创建 Request VO") 8 @Schema(description = "管理后台 - 示例订单创建 Request VO")
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/vo/PayDemoOrderRespVO.java renamed to yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/vo/order/PayDemoOrderRespVO.java
1 -package cn.iocoder.yudao.module.pay.controller.admin.demo.vo; 1 +package cn.iocoder.yudao.module.pay.controller.admin.demo.vo.order;
2 2
3 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
4 import lombok.*; 4 import lombok.*;
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/demo/PayDemoOrderConvert.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.framework.common.pojo.PageResult;
4 -import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO;  
5 -import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderRespVO; 4 +import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.order.PayDemoOrderCreateReqVO;
  5 +import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.order.PayDemoOrderRespVO;
6 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO; 6 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
7 import org.mapstruct.Mapper; 7 import org.mapstruct.Mapper;
8 import org.mapstruct.factory.Mappers; 8 import org.mapstruct.factory.Mappers;
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/app/PayAppDO.java
@@ -54,4 +54,9 @@ public class PayAppDO extends BaseDO { @@ -54,4 +54,9 @@ public class PayAppDO extends BaseDO {
54 */ 54 */
55 private String refundNotifyUrl; 55 private String refundNotifyUrl;
56 56
  57 + /**
  58 + * 转账结果的回调地址
  59 + */
  60 + private String transferNotifyUrl;
  61 +
57 } 62 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java
@@ -67,6 +67,10 @@ public class PayNotifyTaskDO extends TenantBaseDO { @@ -67,6 +67,10 @@ public class PayNotifyTaskDO extends TenantBaseDO {
67 */ 67 */
68 private String merchantOrderId; 68 private String merchantOrderId;
69 /** 69 /**
  70 + * 商户转账单编号
  71 + */
  72 + private String merchantTransferId;
  73 + /**
70 * 通知状态 74 * 通知状态
71 * 75 *
72 * 外键 {@link PayNotifyStatusEnum} 76 * 外键 {@link PayNotifyStatusEnum}
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderService.java
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.pay.service.demo; @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.pay.service.demo;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageParam; 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 -import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO; 5 +import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.order.PayDemoOrderCreateReqVO;
6 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO; 6 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
7 7
8 import javax.validation.Valid; 8 import javax.validation.Valid;
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java
@@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; @@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
9 import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi; 9 import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi;
10 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; 10 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
11 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO; 11 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO;
12 -import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO; 12 +import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.order.PayDemoOrderCreateReqVO;
13 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO; 13 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
14 import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoOrderMapper; 14 import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoOrderMapper;
15 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; 15 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoTransferService.java
@@ -28,4 +28,12 @@ public interface PayDemoTransferService { @@ -28,4 +28,12 @@ public interface PayDemoTransferService {
28 * @param pageVO 分页查询参数 28 * @param pageVO 分页查询参数
29 */ 29 */
30 PageResult<PayDemoTransferDO> getDemoTransferPage(PageParam pageVO); 30 PageResult<PayDemoTransferDO> getDemoTransferPage(PageParam pageVO);
  31 +
  32 + /**
  33 + * 更新转账业务示例订单的转账状态
  34 + *
  35 + * @param id 编号
  36 + * @param payTransferId 转账单编号
  37 + */
  38 + void updateDemoTransferStatus(Long id, Long payTransferId);
31 } 39 }
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.hutool.core.util.ObjectUtil;
3 import cn.iocoder.yudao.framework.common.pojo.PageParam; 4 import cn.iocoder.yudao.framework.common.pojo.PageParam;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 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;
6 import cn.iocoder.yudao.module.pay.convert.demo.PayDemoTransferConvert; 7 import cn.iocoder.yudao.module.pay.convert.demo.PayDemoTransferConvert;
7 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoTransferDO; 8 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoTransferDO;
  9 +import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
8 import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoTransferMapper; 10 import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoTransferMapper;
  11 +import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum;
  12 +import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService;
9 import org.springframework.stereotype.Service; 13 import org.springframework.stereotype.Service;
10 import org.springframework.validation.annotation.Validated; 14 import org.springframework.validation.annotation.Validated;
11 15
12 import javax.annotation.Resource; 16 import javax.annotation.Resource;
13 import javax.validation.Valid; 17 import javax.validation.Valid;
14 import javax.validation.Validator; 18 import javax.validation.Validator;
  19 +import java.util.Objects;
15 20
  21 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  22 +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
16 import static cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum.WAITING; 23 import static cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum.WAITING;
17 24
18 /** 25 /**
@@ -33,6 +40,8 @@ public class PayDemoTransferServiceImpl implements PayDemoTransferService { @@ -33,6 +40,8 @@ public class PayDemoTransferServiceImpl implements PayDemoTransferService {
33 @Resource 40 @Resource
34 private PayDemoTransferMapper demoTransferMapper; 41 private PayDemoTransferMapper demoTransferMapper;
35 @Resource 42 @Resource
  43 + private PayTransferService payTransferService;
  44 + @Resource
36 private Validator validator; 45 private Validator validator;
37 46
38 @Override 47 @Override
@@ -50,4 +59,41 @@ public class PayDemoTransferServiceImpl implements PayDemoTransferService { @@ -50,4 +59,41 @@ public class PayDemoTransferServiceImpl implements PayDemoTransferService {
50 public PageResult<PayDemoTransferDO> getDemoTransferPage(PageParam pageVO) { 59 public PageResult<PayDemoTransferDO> getDemoTransferPage(PageParam pageVO) {
51 return demoTransferMapper.selectPage(pageVO); 60 return demoTransferMapper.selectPage(pageVO);
52 } 61 }
  62 +
  63 + @Override
  64 + public void updateDemoTransferStatus(Long id, Long payTransferId) {
  65 + PayTransferDO payTransfer = validateDemoTransferStatusCanUpdate(id, payTransferId);
  66 + // 更新示例订单状态
  67 + if (payTransfer != null) {
  68 + demoTransferMapper.updateById(new PayDemoTransferDO().setId(id)
  69 + .setPayTransferId(payTransferId)
  70 + .setPayChannelCode(payTransfer.getChannelCode())
  71 + .setTransferStatus(payTransfer.getStatus())
  72 + .setTransferTime(payTransfer.getSuccessTime()));
  73 + }
  74 + }
  75 +
  76 + private PayTransferDO validateDemoTransferStatusCanUpdate(Long id, Long payTransferId) {
  77 + PayDemoTransferDO demoTransfer = demoTransferMapper.selectById(id);
  78 + if (demoTransfer == null) {
  79 + throw exception(DEMO_TRANSFER_NOT_FOUND);
  80 + }
  81 + if (PayTransferStatusEnum.isSuccess(demoTransfer.getTransferStatus())
  82 + || PayTransferStatusEnum.isClosed(demoTransfer.getTransferStatus())) {
  83 + // 无需更新返回 null
  84 + return null;
  85 + }
  86 + PayTransferDO transfer = payTransferService.getTransfer(payTransferId);
  87 + if (transfer == null) {
  88 + throw exception(PAY_TRANSFER_NOT_FOUND);
  89 + }
  90 + if (!Objects.equals(demoTransfer.getPrice(), transfer.getPrice())) {
  91 + throw exception(DEMO_TRANSFER_FAIL_PRICE_NOT_MATCH);
  92 + }
  93 + if (ObjectUtil.notEqual(transfer.getMerchantTransferId(), id.toString())) {
  94 + throw exception(DEMO_TRANSFER_FAIL_TRANSFER_ID_ERROR);
  95 + }
  96 + // TODO 校验账号
  97 + return transfer;
  98 + }
53 } 99 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyServiceImpl.java
@@ -13,11 +13,13 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; @@ -13,11 +13,13 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
13 import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; 13 import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
14 import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO; 14 import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
15 import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO; 15 import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO;
  16 +import cn.iocoder.yudao.module.pay.api.notify.dto.PayTransferNotifyReqDTO;
16 import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO; 17 import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO;
17 import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO; 18 import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO;
18 import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO; 19 import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO;
19 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; 20 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
20 import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; 21 import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
  22 +import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
21 import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyLogMapper; 23 import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyLogMapper;
22 import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper; 24 import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper;
23 import cn.iocoder.yudao.module.pay.dal.redis.notify.PayNotifyLockRedisDAO; 25 import cn.iocoder.yudao.module.pay.dal.redis.notify.PayNotifyLockRedisDAO;
@@ -25,6 +27,7 @@ import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum; @@ -25,6 +27,7 @@ import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum;
25 import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; 27 import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
26 import cn.iocoder.yudao.module.pay.service.order.PayOrderService; 28 import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
27 import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; 29 import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
  30 +import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService;
28 import com.google.common.annotations.VisibleForTesting; 31 import com.google.common.annotations.VisibleForTesting;
29 import lombok.extern.slf4j.Slf4j; 32 import lombok.extern.slf4j.Slf4j;
30 import org.springframework.context.annotation.Lazy; 33 import org.springframework.context.annotation.Lazy;
@@ -73,6 +76,9 @@ public class PayNotifyServiceImpl implements PayNotifyService { @@ -73,6 +76,9 @@ public class PayNotifyServiceImpl implements PayNotifyService {
73 @Resource 76 @Resource
74 @Lazy // 循环依赖,避免报错 77 @Lazy // 循环依赖,避免报错
75 private PayRefundService refundService; 78 private PayRefundService refundService;
  79 + @Resource
  80 + @Lazy // 循环依赖,避免报错
  81 + private PayTransferService transferService;
76 82
77 @Resource 83 @Resource
78 private PayNotifyTaskMapper notifyTaskMapper; 84 private PayNotifyTaskMapper notifyTaskMapper;
@@ -100,6 +106,10 @@ public class PayNotifyServiceImpl implements PayNotifyService { @@ -100,6 +106,10 @@ public class PayNotifyServiceImpl implements PayNotifyService {
100 PayRefundDO refundDO = refundService.getRefund(task.getDataId()); 106 PayRefundDO refundDO = refundService.getRefund(task.getDataId());
101 task.setAppId(refundDO.getAppId()) 107 task.setAppId(refundDO.getAppId())
102 .setMerchantOrderId(refundDO.getMerchantOrderId()).setNotifyUrl(refundDO.getNotifyUrl()); 108 .setMerchantOrderId(refundDO.getMerchantOrderId()).setNotifyUrl(refundDO.getNotifyUrl());
  109 + } else if (Objects.equals(task.getType(), PayNotifyTypeEnum.TRANSFER.getType())) {
  110 + PayTransferDO transfer = transferService.getTransfer(task.getDataId());
  111 + task.setAppId(transfer.getAppId()).setMerchantTransferId(transfer.getMerchantTransferId())
  112 + .setNotifyUrl(transfer.getNotifyUrl());
103 } 113 }
104 114
105 // 执行插入 115 // 执行插入
@@ -214,6 +224,9 @@ public class PayNotifyServiceImpl implements PayNotifyService { @@ -214,6 +224,9 @@ public class PayNotifyServiceImpl implements PayNotifyService {
214 } else if (Objects.equals(task.getType(), PayNotifyTypeEnum.REFUND.getType())) { 224 } else if (Objects.equals(task.getType(), PayNotifyTypeEnum.REFUND.getType())) {
215 request = PayRefundNotifyReqDTO.builder().merchantOrderId(task.getMerchantOrderId()) 225 request = PayRefundNotifyReqDTO.builder().merchantOrderId(task.getMerchantOrderId())
216 .payRefundId(task.getDataId()).build(); 226 .payRefundId(task.getDataId()).build();
  227 + } else if (Objects.equals(task.getType(), PayNotifyTypeEnum.TRANSFER.getType())) {
  228 + request = new PayTransferNotifyReqDTO().setMerchantTransferId(task.getMerchantTransferId())
  229 + .setPayTransferId(task.getDataId());
217 } else { 230 } else {
218 throw new RuntimeException("未知的通知任务类型:" + JsonUtils.toJsonString(task)); 231 throw new RuntimeException("未知的通知任务类型:" + JsonUtils.toJsonString(task));
219 } 232 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceImpl.java
@@ -12,12 +12,15 @@ import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferStatusRespE @@ -12,12 +12,15 @@ import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferStatusRespE
12 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO; 12 import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
13 import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateReqVO; 13 import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateReqVO;
14 import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferPageReqVO; 14 import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferPageReqVO;
  15 +import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
15 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; 16 import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
16 import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO; 17 import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
17 import cn.iocoder.yudao.module.pay.dal.mysql.transfer.PayTransferMapper; 18 import cn.iocoder.yudao.module.pay.dal.mysql.transfer.PayTransferMapper;
18 import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; 19 import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO;
  20 +import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
19 import cn.iocoder.yudao.module.pay.service.app.PayAppService; 21 import cn.iocoder.yudao.module.pay.service.app.PayAppService;
20 import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; 22 import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
  23 +import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
21 import lombok.extern.slf4j.Slf4j; 24 import lombok.extern.slf4j.Slf4j;
22 import org.springframework.stereotype.Service; 25 import org.springframework.stereotype.Service;
23 import org.springframework.transaction.annotation.Transactional; 26 import org.springframework.transaction.annotation.Transactional;
@@ -51,6 +54,8 @@ public class PayTransferServiceImpl implements PayTransferService { @@ -51,6 +54,8 @@ public class PayTransferServiceImpl implements PayTransferService {
51 @Resource 54 @Resource
52 private PayChannelService channelService; 55 private PayChannelService channelService;
53 @Resource 56 @Resource
  57 + private PayNotifyService notifyService;
  58 + @Resource
54 private PayNoRedisDAO noRedisDAO; 59 private PayNoRedisDAO noRedisDAO;
55 @Resource 60 @Resource
56 private Validator validator; 61 private Validator validator;
@@ -73,7 +78,7 @@ public class PayTransferServiceImpl implements PayTransferService { @@ -73,7 +78,7 @@ public class PayTransferServiceImpl implements PayTransferService {
73 // 1.1 校验转账单是否可以提交 78 // 1.1 校验转账单是否可以提交
74 validateTransferCanCreate(reqDTO.getAppId(), reqDTO.getMerchantTransferId()); 79 validateTransferCanCreate(reqDTO.getAppId(), reqDTO.getMerchantTransferId());
75 // 1.2 校验 App 80 // 1.2 校验 App
76 - appService.validPayApp(reqDTO.getAppId()); 81 + PayAppDO payApp = appService.validPayApp(reqDTO.getAppId());
77 // 1.3 校验支付渠道是否有效 82 // 1.3 校验支付渠道是否有效
78 PayChannelDO channel = channelService.validPayChannel(reqDTO.getAppId(), reqDTO.getChannelCode()); 83 PayChannelDO channel = channelService.validPayChannel(reqDTO.getAppId(), reqDTO.getChannelCode());
79 PayClient client = channelService.getPayClient(channel.getId()); 84 PayClient client = channelService.getPayClient(channel.getId());
@@ -86,7 +91,7 @@ public class PayTransferServiceImpl implements PayTransferService { @@ -86,7 +91,7 @@ public class PayTransferServiceImpl implements PayTransferService {
86 PayTransferDO transfer = INSTANCE.convert(reqDTO) 91 PayTransferDO transfer = INSTANCE.convert(reqDTO)
87 .setChannelId(channel.getId()) 92 .setChannelId(channel.getId())
88 .setNo(no).setStatus(WAITING.getStatus()) 93 .setNo(no).setStatus(WAITING.getStatus())
89 - .setNotifyUrl("http://127.0.0.1:48080/admin-api/pay/todo"); // TODO 需要加个transfer Notify url 94 + .setNotifyUrl(payApp.getTransferNotifyUrl());
90 transferMapper.insert(transfer); 95 transferMapper.insert(transfer);
91 PayTransferRespDTO unifiedTransferResp = null; 96 PayTransferRespDTO unifiedTransferResp = null;
92 try { 97 try {
@@ -145,22 +150,13 @@ public class PayTransferServiceImpl implements PayTransferService { @@ -145,22 +150,13 @@ public class PayTransferServiceImpl implements PayTransferService {
145 } 150 }
146 151
147 private void notifyTransferSuccess(PayChannelDO channel, PayTransferRespDTO notify) { 152 private void notifyTransferSuccess(PayChannelDO channel, PayTransferRespDTO notify) {
148 - // 1. 更新 PayTransferDO 转账成功  
149 - Boolean transferred = updateTransferSuccess(channel, notify);  
150 - if (transferred) {  
151 - return;  
152 - }  
153 - // 2. TODO 插入转账通知记录  
154 - }  
155 -  
156 - private Boolean updateTransferSuccess(PayChannelDO channel, PayTransferRespDTO notify) {  
157 // 1.校验 153 // 1.校验
158 PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo()); 154 PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo());
159 if (transfer == null) { 155 if (transfer == null) {
160 throw exception(PAY_TRANSFER_NOT_FOUND); 156 throw exception(PAY_TRANSFER_NOT_FOUND);
161 } 157 }
162 if (isSuccess(transfer.getStatus())) { // 如果已成功,直接返回,不用重复更新 158 if (isSuccess(transfer.getStatus())) { // 如果已成功,直接返回,不用重复更新
163 - return Boolean.TRUE; 159 + return;
164 } 160 }
165 if (!isPendingStatus(transfer.getStatus())) { 161 if (!isPendingStatus(transfer.getStatus())) {
166 throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING); 162 throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING);
@@ -176,10 +172,13 @@ public class PayTransferServiceImpl implements PayTransferService { @@ -176,10 +172,13 @@ public class PayTransferServiceImpl implements PayTransferService {
176 throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING); 172 throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING);
177 } 173 }
178 log.info("[updateTransferSuccess][transfer({}) 更新为已转账]", transfer.getId()); 174 log.info("[updateTransferSuccess][transfer({}) 更新为已转账]", transfer.getId());
179 - return Boolean.FALSE; 175 +
  176 + // 3. 插入转账通知记录
  177 + notifyService.createPayNotifyTask(PayNotifyTypeEnum.TRANSFER.getType(),
  178 + transfer.getId());
180 } 179 }
181 180
182 - private void updateTransferClosed(PayChannelDO channel, PayTransferRespDTO notify) { 181 + private void notifyTransferClosed(PayChannelDO channel, PayTransferRespDTO notify) {
183 // 1.校验 182 // 1.校验
184 PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo()); 183 PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo());
185 if (transfer == null) { 184 if (transfer == null) {
@@ -192,6 +191,7 @@ public class PayTransferServiceImpl implements PayTransferService { @@ -192,6 +191,7 @@ public class PayTransferServiceImpl implements PayTransferService {
192 if (!isPendingStatus(transfer.getStatus())) { 191 if (!isPendingStatus(transfer.getStatus())) {
193 throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING); 192 throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING);
194 } 193 }
  194 +
195 // 2.更新 195 // 2.更新
196 int updateCount = transferMapper.updateByIdAndStatus(transfer.getId(), 196 int updateCount = transferMapper.updateByIdAndStatus(transfer.getId(),
197 CollUtil.newArrayList(WAITING.getStatus(), IN_PROGRESS.getStatus()), 197 CollUtil.newArrayList(WAITING.getStatus(), IN_PROGRESS.getStatus()),
@@ -203,11 +203,11 @@ public class PayTransferServiceImpl implements PayTransferService { @@ -203,11 +203,11 @@ public class PayTransferServiceImpl implements PayTransferService {
203 throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING); 203 throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING);
204 } 204 }
205 log.info("[updateTransferClosed][transfer({}) 更新为关闭状态]", transfer.getId()); 205 log.info("[updateTransferClosed][transfer({}) 更新为关闭状态]", transfer.getId());
206 - }  
207 206
208 - private void notifyTransferClosed(PayChannelDO channel, PayTransferRespDTO notify) {  
209 - // 更新 PayTransferDO 转账关闭  
210 - updateTransferClosed(channel, notify); 207 + // 3. 插入转账通知记录
  208 + notifyService.createPayNotifyTask(PayNotifyTypeEnum.TRANSFER.getType(),
  209 + transfer.getId());
  210 +
211 } 211 }
212 212
213 /** 213 /**