转账 - 增加转账通知

This commit is contained in:
jason 2023-11-06 11:33:08 +08:00
parent cf114409b0
commit 09d45e6393
17 changed files with 160 additions and 31 deletions

View File

@ -246,3 +246,11 @@ VALUES (
'转账订单', '', 2, 3, 1117, '转账订单', '', 2, 3, 1117,
'transfer', 'ep:credit-card', 'pay/transfer/index', 0, 'PayTransfer' 'transfer', 'ep:credit-card', 'pay/transfer/index', 0, 'PayTransfer'
); );
-- 转账通知脚本
ALTER TABLE `pay_app`
ADD COLUMN `transfer_notify_url` varchar(1024) NOT NULL COMMENT '转账结果的回调地址' AFTER `refund_notify_url`;
ALTER TABLE `pay_notify_task`
MODIFY COLUMN `merchant_order_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '商户订单编号' AFTER `status`,
ADD COLUMN `merchant_transfer_id` varchar(64) COMMENT '商户转账单编号' AFTER `merchant_order_id`;

View File

@ -0,0 +1,27 @@
package cn.iocoder.yudao.module.pay.api.notify.dto;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
/**
* 转账单的通知 Request DTO
*
* @author jason
*/
@Data
public class PayTransferNotifyReqDTO {
/**
* 商户转账单号
*/
@NotEmpty(message = "商户转账单号不能为空")
private String merchantTransferId;
/**
* 转账订单编号
*/
@NotNull(message = "转账订单编号不能为空")
private Long payTransferId;
}

View File

@ -65,12 +65,13 @@ public interface ErrorCodeConstants {
// ========== 转账模块 1-007-009-000 ========== // ========== 转账模块 1-007-009-000 ==========
ErrorCode PAY_TRANSFER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1_007_009_000, "发起转账报错,错误码:{},错误提示:{}"); ErrorCode PAY_TRANSFER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1_007_009_000, "发起转账报错,错误码:{},错误提示:{}");
ErrorCode PAY_TRANSFER_NOT_FOUND = new ErrorCode(1_007_009_001, "转账交易单不存在"); ErrorCode PAY_TRANSFER_NOT_FOUND = new ErrorCode(1_007_009_001, "转账单不存在");
ErrorCode PAY_TRANSFER_STATUS_IS_SUCCESS = new ErrorCode(1_007_009_002, "转账单已成功转账"); ErrorCode PAY_TRANSFER_STATUS_IS_SUCCESS = new ErrorCode(1_007_009_002, "转账单已成功转账");
ErrorCode PAY_TRANSFER_EXISTS = new ErrorCode(1_007_009_003, "已经存在转账单"); ErrorCode PAY_TRANSFER_EXISTS = new ErrorCode(1_007_009_003, "已经存在转账单");
ErrorCode PAY_MERCHANT_TRANSFER_EXISTS = new ErrorCode(1_007_009_004, "该笔业务的转账已经存在,请查询转账订单相关状态"); ErrorCode PAY_MERCHANT_TRANSFER_EXISTS = new ErrorCode(1_007_009_004, "该笔业务的转账已经存在,请查询转账订单相关状态");
ErrorCode PAY_TRANSFER_STATUS_IS_NOT_WAITING = new ErrorCode(1_007_009_005, "转账单不处于待转账"); ErrorCode PAY_TRANSFER_STATUS_IS_NOT_WAITING = new ErrorCode(1_007_009_005, "转账单不处于待转账");
ErrorCode PAY_TRANSFER_STATUS_IS_NOT_PENDING = new ErrorCode(1_007_009_006, "转账单不处于待转账或转账中"); ErrorCode PAY_TRANSFER_STATUS_IS_NOT_PENDING = new ErrorCode(1_007_009_006, "转账单不处于待转账或转账中");
// ========== 示例订单 1-007-900-000 ========== // ========== 示例订单 1-007-900-000 ==========
ErrorCode DEMO_ORDER_NOT_FOUND = new ErrorCode(1_007_900_000, "示例订单不存在"); ErrorCode DEMO_ORDER_NOT_FOUND = new ErrorCode(1_007_900_000, "示例订单不存在");
ErrorCode DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1_007_900_001, "示例订单更新支付状态失败,订单不是【未支付】状态"); ErrorCode DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1_007_900_001, "示例订单更新支付状态失败,订单不是【未支付】状态");
@ -84,4 +85,8 @@ public interface ErrorCodeConstants {
ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR = new ErrorCode(1_007_900_009, "发起退款失败,退款单编号不匹配"); ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR = new ErrorCode(1_007_900_009, "发起退款失败,退款单编号不匹配");
ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_PRICE_NOT_MATCH = new ErrorCode(1_007_900_010, "发起退款失败,退款单金额不匹配"); ErrorCode DEMO_ORDER_REFUND_FAIL_REFUND_PRICE_NOT_MATCH = new ErrorCode(1_007_900_010, "发起退款失败,退款单金额不匹配");
// ========== 示例转账订单 1-007-901-001 ==========
ErrorCode DEMO_TRANSFER_NOT_FOUND = new ErrorCode(1_007_901_001, "示例转账单不存在");
ErrorCode DEMO_TRANSFER_FAIL_TRANSFER_ID_ERROR = new ErrorCode(1_007_901_002, "转账失败,转账单编号不匹配");
ErrorCode DEMO_TRANSFER_FAIL_PRICE_NOT_MATCH = new ErrorCode(1_007_901_003, "转账失败,转账单金额不匹配");
} }

View File

@ -14,6 +14,7 @@ public enum PayNotifyTypeEnum {
ORDER(1, "支付单"), ORDER(1, "支付单"),
REFUND(2, "退款单"), REFUND(2, "退款单"),
TRANSFER(3, "转账单")
; ;
/** /**

View File

@ -6,8 +6,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO; import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO; import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO;
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO; import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.order.PayDemoOrderCreateReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderRespVO; import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.order.PayDemoOrderRespVO;
import cn.iocoder.yudao.module.pay.convert.demo.PayDemoOrderConvert; import cn.iocoder.yudao.module.pay.convert.demo.PayDemoOrderConvert;
import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO; import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
import cn.iocoder.yudao.module.pay.service.demo.PayDemoOrderService; import cn.iocoder.yudao.module.pay.service.demo.PayDemoOrderService;

View File

@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.pay.controller.admin.demo;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.pay.api.notify.dto.PayTransferNotifyReqDTO;
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO; import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferRespVO; import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferRespVO;
import cn.iocoder.yudao.module.pay.convert.demo.PayDemoTransferConvert; import cn.iocoder.yudao.module.pay.convert.demo.PayDemoTransferConvert;
@ -14,6 +16,7 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.validation.Valid; import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -33,9 +36,19 @@ public class PayDemoTransferController {
} }
@GetMapping("/page") @GetMapping("/page")
@Operation(summary = "获得示例订单分页") @Operation(summary = "获得示例转账订单分页")
public CommonResult<PageResult<PayDemoTransferRespVO>> getDemoTransferPage(@Valid PageParam pageVO) { public CommonResult<PageResult<PayDemoTransferRespVO>> getDemoTransferPage(@Valid PageParam pageVO) {
PageResult<PayDemoTransferDO> pageResult = demoTransferService.getDemoTransferPage(pageVO); PageResult<PayDemoTransferDO> pageResult = demoTransferService.getDemoTransferPage(pageVO);
return success(PayDemoTransferConvert.INSTANCE.convertPage(pageResult)); return success(PayDemoTransferConvert.INSTANCE.convertPage(pageResult));
} }
@PostMapping("/update-status")
@Operation(summary = "更新示例转账订单的转账状态") // pay-module 转账服务进行回调
@PermitAll // 无需登录安全由 PayDemoTransferService 内部校验实现
@OperateLog(enable = false) // 禁用操作日志因为没有操作人
public CommonResult<Boolean> updateDemoTransferStatus(@RequestBody PayTransferNotifyReqDTO notifyReqDTO) {
demoTransferService.updateDemoTransferStatus(Long.valueOf(notifyReqDTO.getMerchantTransferId()),
notifyReqDTO.getPayTransferId());
return success(true);
}
} }

View File

@ -1,9 +1,8 @@
package cn.iocoder.yudao.module.pay.controller.admin.demo.vo; package cn.iocoder.yudao.module.pay.controller.admin.demo.vo.order;
import lombok.*;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 示例订单创建 Request VO") @Schema(description = "管理后台 - 示例订单创建 Request VO")

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.pay.controller.admin.demo.vo; package cn.iocoder.yudao.module.pay.controller.admin.demo.vo.order;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;

View File

@ -1,8 +1,8 @@
package cn.iocoder.yudao.module.pay.convert.demo; package cn.iocoder.yudao.module.pay.convert.demo;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO; import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.order.PayDemoOrderCreateReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderRespVO; import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.order.PayDemoOrderRespVO;
import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO; import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;

View File

@ -54,4 +54,9 @@ public class PayAppDO extends BaseDO {
*/ */
private String refundNotifyUrl; private String refundNotifyUrl;
/**
* 转账结果的回调地址
*/
private String transferNotifyUrl;
} }

View File

@ -66,6 +66,10 @@ public class PayNotifyTaskDO extends TenantBaseDO {
* 商户订单编号 * 商户订单编号
*/ */
private String merchantOrderId; private String merchantOrderId;
/**
* 商户转账单编号
*/
private String merchantTransferId;
/** /**
* 通知状态 * 通知状态
* *

View File

@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.pay.service.demo;
import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO; import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.order.PayDemoOrderCreateReqVO;
import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO; import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
import javax.validation.Valid; import javax.validation.Valid;

View File

@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi; import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi;
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO; import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO;
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO; import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.order.PayDemoOrderCreateReqVO;
import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO; import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoOrderMapper; import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoOrderMapper;
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;

View File

@ -28,4 +28,12 @@ public interface PayDemoTransferService {
* @param pageVO 分页查询参数 * @param pageVO 分页查询参数
*/ */
PageResult<PayDemoTransferDO> getDemoTransferPage(PageParam pageVO); PageResult<PayDemoTransferDO> getDemoTransferPage(PageParam pageVO);
/**
* 更新转账业务示例订单的转账状态
*
* @param id 编号
* @param payTransferId 转账单编号
*/
void updateDemoTransferStatus(Long id, Long payTransferId);
} }

View File

@ -1,18 +1,25 @@
package cn.iocoder.yudao.module.pay.service.demo; package cn.iocoder.yudao.module.pay.service.demo;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO; import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO;
import cn.iocoder.yudao.module.pay.convert.demo.PayDemoTransferConvert; import cn.iocoder.yudao.module.pay.convert.demo.PayDemoTransferConvert;
import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoTransferDO; import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoTransferDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoTransferMapper; import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoTransferMapper;
import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum;
import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.validation.Valid; import javax.validation.Valid;
import javax.validation.Validator; import javax.validation.Validator;
import java.util.Objects;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum.WAITING; import static cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum.WAITING;
/** /**
@ -33,6 +40,8 @@ public class PayDemoTransferServiceImpl implements PayDemoTransferService {
@Resource @Resource
private PayDemoTransferMapper demoTransferMapper; private PayDemoTransferMapper demoTransferMapper;
@Resource @Resource
private PayTransferService payTransferService;
@Resource
private Validator validator; private Validator validator;
@Override @Override
@ -50,4 +59,41 @@ public class PayDemoTransferServiceImpl implements PayDemoTransferService {
public PageResult<PayDemoTransferDO> getDemoTransferPage(PageParam pageVO) { public PageResult<PayDemoTransferDO> getDemoTransferPage(PageParam pageVO) {
return demoTransferMapper.selectPage(pageVO); return demoTransferMapper.selectPage(pageVO);
} }
@Override
public void updateDemoTransferStatus(Long id, Long payTransferId) {
PayTransferDO payTransfer = validateDemoTransferStatusCanUpdate(id, payTransferId);
// 更新示例订单状态
if (payTransfer != null) {
demoTransferMapper.updateById(new PayDemoTransferDO().setId(id)
.setPayTransferId(payTransferId)
.setPayChannelCode(payTransfer.getChannelCode())
.setTransferStatus(payTransfer.getStatus())
.setTransferTime(payTransfer.getSuccessTime()));
}
}
private PayTransferDO validateDemoTransferStatusCanUpdate(Long id, Long payTransferId) {
PayDemoTransferDO demoTransfer = demoTransferMapper.selectById(id);
if (demoTransfer == null) {
throw exception(DEMO_TRANSFER_NOT_FOUND);
}
if (PayTransferStatusEnum.isSuccess(demoTransfer.getTransferStatus())
|| PayTransferStatusEnum.isClosed(demoTransfer.getTransferStatus())) {
// 无需更新返回 null
return null;
}
PayTransferDO transfer = payTransferService.getTransfer(payTransferId);
if (transfer == null) {
throw exception(PAY_TRANSFER_NOT_FOUND);
}
if (!Objects.equals(demoTransfer.getPrice(), transfer.getPrice())) {
throw exception(DEMO_TRANSFER_FAIL_PRICE_NOT_MATCH);
}
if (ObjectUtil.notEqual(transfer.getMerchantTransferId(), id.toString())) {
throw exception(DEMO_TRANSFER_FAIL_TRANSFER_ID_ERROR);
}
// TODO 校验账号
return transfer;
}
} }

View File

@ -13,11 +13,13 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO; import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO; import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO;
import cn.iocoder.yudao.module.pay.api.notify.dto.PayTransferNotifyReqDTO;
import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO; import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO;
import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO; import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO; import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyLogMapper; import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyLogMapper;
import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper; import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper;
import cn.iocoder.yudao.module.pay.dal.redis.notify.PayNotifyLockRedisDAO; import cn.iocoder.yudao.module.pay.dal.redis.notify.PayNotifyLockRedisDAO;
@ -25,6 +27,7 @@ import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum;
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
import cn.iocoder.yudao.module.pay.service.order.PayOrderService; import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
@ -73,6 +76,9 @@ public class PayNotifyServiceImpl implements PayNotifyService {
@Resource @Resource
@Lazy // 循环依赖避免报错 @Lazy // 循环依赖避免报错
private PayRefundService refundService; private PayRefundService refundService;
@Resource
@Lazy // 循环依赖避免报错
private PayTransferService transferService;
@Resource @Resource
private PayNotifyTaskMapper notifyTaskMapper; private PayNotifyTaskMapper notifyTaskMapper;
@ -100,6 +106,10 @@ public class PayNotifyServiceImpl implements PayNotifyService {
PayRefundDO refundDO = refundService.getRefund(task.getDataId()); PayRefundDO refundDO = refundService.getRefund(task.getDataId());
task.setAppId(refundDO.getAppId()) task.setAppId(refundDO.getAppId())
.setMerchantOrderId(refundDO.getMerchantOrderId()).setNotifyUrl(refundDO.getNotifyUrl()); .setMerchantOrderId(refundDO.getMerchantOrderId()).setNotifyUrl(refundDO.getNotifyUrl());
} else if (Objects.equals(task.getType(), PayNotifyTypeEnum.TRANSFER.getType())) {
PayTransferDO transfer = transferService.getTransfer(task.getDataId());
task.setAppId(transfer.getAppId()).setMerchantTransferId(transfer.getMerchantTransferId())
.setNotifyUrl(transfer.getNotifyUrl());
} }
// 执行插入 // 执行插入
@ -214,6 +224,9 @@ public class PayNotifyServiceImpl implements PayNotifyService {
} else if (Objects.equals(task.getType(), PayNotifyTypeEnum.REFUND.getType())) { } else if (Objects.equals(task.getType(), PayNotifyTypeEnum.REFUND.getType())) {
request = PayRefundNotifyReqDTO.builder().merchantOrderId(task.getMerchantOrderId()) request = PayRefundNotifyReqDTO.builder().merchantOrderId(task.getMerchantOrderId())
.payRefundId(task.getDataId()).build(); .payRefundId(task.getDataId()).build();
} else if (Objects.equals(task.getType(), PayNotifyTypeEnum.TRANSFER.getType())) {
request = new PayTransferNotifyReqDTO().setMerchantTransferId(task.getMerchantTransferId())
.setPayTransferId(task.getDataId());
} else { } else {
throw new RuntimeException("未知的通知任务类型:" + JsonUtils.toJsonString(task)); throw new RuntimeException("未知的通知任务类型:" + JsonUtils.toJsonString(task));
} }

View File

@ -12,12 +12,15 @@ import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferStatusRespE
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO; import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateReqVO; import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferPageReqVO; import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferPageReqVO;
import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO; import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
import cn.iocoder.yudao.module.pay.dal.mysql.transfer.PayTransferMapper; import cn.iocoder.yudao.module.pay.dal.mysql.transfer.PayTransferMapper;
import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO;
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
import cn.iocoder.yudao.module.pay.service.app.PayAppService; import cn.iocoder.yudao.module.pay.service.app.PayAppService;
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -51,6 +54,8 @@ public class PayTransferServiceImpl implements PayTransferService {
@Resource @Resource
private PayChannelService channelService; private PayChannelService channelService;
@Resource @Resource
private PayNotifyService notifyService;
@Resource
private PayNoRedisDAO noRedisDAO; private PayNoRedisDAO noRedisDAO;
@Resource @Resource
private Validator validator; private Validator validator;
@ -73,7 +78,7 @@ public class PayTransferServiceImpl implements PayTransferService {
// 1.1 校验转账单是否可以提交 // 1.1 校验转账单是否可以提交
validateTransferCanCreate(reqDTO.getAppId(), reqDTO.getMerchantTransferId()); validateTransferCanCreate(reqDTO.getAppId(), reqDTO.getMerchantTransferId());
// 1.2 校验 App // 1.2 校验 App
appService.validPayApp(reqDTO.getAppId()); PayAppDO payApp = appService.validPayApp(reqDTO.getAppId());
// 1.3 校验支付渠道是否有效 // 1.3 校验支付渠道是否有效
PayChannelDO channel = channelService.validPayChannel(reqDTO.getAppId(), reqDTO.getChannelCode()); PayChannelDO channel = channelService.validPayChannel(reqDTO.getAppId(), reqDTO.getChannelCode());
PayClient client = channelService.getPayClient(channel.getId()); PayClient client = channelService.getPayClient(channel.getId());
@ -86,7 +91,7 @@ public class PayTransferServiceImpl implements PayTransferService {
PayTransferDO transfer = INSTANCE.convert(reqDTO) PayTransferDO transfer = INSTANCE.convert(reqDTO)
.setChannelId(channel.getId()) .setChannelId(channel.getId())
.setNo(no).setStatus(WAITING.getStatus()) .setNo(no).setStatus(WAITING.getStatus())
.setNotifyUrl("http://127.0.0.1:48080/admin-api/pay/todo"); // TODO 需要加个transfer Notify url .setNotifyUrl(payApp.getTransferNotifyUrl());
transferMapper.insert(transfer); transferMapper.insert(transfer);
PayTransferRespDTO unifiedTransferResp = null; PayTransferRespDTO unifiedTransferResp = null;
try { try {
@ -145,22 +150,13 @@ public class PayTransferServiceImpl implements PayTransferService {
} }
private void notifyTransferSuccess(PayChannelDO channel, PayTransferRespDTO notify) { private void notifyTransferSuccess(PayChannelDO channel, PayTransferRespDTO notify) {
// 1. 更新 PayTransferDO 转账成功
Boolean transferred = updateTransferSuccess(channel, notify);
if (transferred) {
return;
}
// 2. TODO 插入转账通知记录
}
private Boolean updateTransferSuccess(PayChannelDO channel, PayTransferRespDTO notify) {
// 1.校验 // 1.校验
PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo()); PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo());
if (transfer == null) { if (transfer == null) {
throw exception(PAY_TRANSFER_NOT_FOUND); throw exception(PAY_TRANSFER_NOT_FOUND);
} }
if (isSuccess(transfer.getStatus())) { // 如果已成功直接返回不用重复更新 if (isSuccess(transfer.getStatus())) { // 如果已成功直接返回不用重复更新
return Boolean.TRUE; return;
} }
if (!isPendingStatus(transfer.getStatus())) { if (!isPendingStatus(transfer.getStatus())) {
throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING); throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING);
@ -176,10 +172,13 @@ public class PayTransferServiceImpl implements PayTransferService {
throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING); throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING);
} }
log.info("[updateTransferSuccess][transfer({}) 更新为已转账]", transfer.getId()); log.info("[updateTransferSuccess][transfer({}) 更新为已转账]", transfer.getId());
return Boolean.FALSE;
// 3. 插入转账通知记录
notifyService.createPayNotifyTask(PayNotifyTypeEnum.TRANSFER.getType(),
transfer.getId());
} }
private void updateTransferClosed(PayChannelDO channel, PayTransferRespDTO notify) { private void notifyTransferClosed(PayChannelDO channel, PayTransferRespDTO notify) {
// 1.校验 // 1.校验
PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo()); PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo());
if (transfer == null) { if (transfer == null) {
@ -192,6 +191,7 @@ public class PayTransferServiceImpl implements PayTransferService {
if (!isPendingStatus(transfer.getStatus())) { if (!isPendingStatus(transfer.getStatus())) {
throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING); throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING);
} }
// 2.更新 // 2.更新
int updateCount = transferMapper.updateByIdAndStatus(transfer.getId(), int updateCount = transferMapper.updateByIdAndStatus(transfer.getId(),
CollUtil.newArrayList(WAITING.getStatus(), IN_PROGRESS.getStatus()), CollUtil.newArrayList(WAITING.getStatus(), IN_PROGRESS.getStatus()),
@ -203,11 +203,11 @@ public class PayTransferServiceImpl implements PayTransferService {
throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING); throw exception(PAY_TRANSFER_STATUS_IS_NOT_PENDING);
} }
log.info("[updateTransferClosed][transfer({}) 更新为关闭状态]", transfer.getId()); log.info("[updateTransferClosed][transfer({}) 更新为关闭状态]", transfer.getId());
}
private void notifyTransferClosed(PayChannelDO channel, PayTransferRespDTO notify) { // 3. 插入转账通知记录
// 更新 PayTransferDO 转账关闭 notifyService.createPayNotifyTask(PayNotifyTypeEnum.TRANSFER.getType(),
updateTransferClosed(channel, notify); transfer.getId());
} }
/** /**