【功能优化】完成转账回调接口
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
package cn.iocoder.yudao.module.pay.api.transfer;
|
||||
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.convert.transfer.PayTransferConvert;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
|
||||
import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@@ -24,4 +27,10 @@ public class PayTransferApiImpl implements PayTransferApi {
|
||||
return payTransferService.createTransfer(reqDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayTransferRespDTO getTransfer(Long id) {
|
||||
PayTransferDO transfer = payTransferService.getTransfer(id);
|
||||
return PayTransferConvert.INSTANCE.convert3(transfer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskDetailRespVO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskRespVO;
|
||||
@@ -18,6 +19,7 @@ import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
|
||||
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
|
||||
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.transfer.PayTransferService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@@ -49,6 +51,8 @@ public class PayNotifyController {
|
||||
@Resource
|
||||
private PayRefundService refundService;
|
||||
@Resource
|
||||
private PayTransferService payTransferService;
|
||||
@Resource
|
||||
private PayNotifyService notifyService;
|
||||
@Resource
|
||||
private PayAppService appService;
|
||||
@@ -95,6 +99,26 @@ public class PayNotifyController {
|
||||
return "success";
|
||||
}
|
||||
|
||||
@PostMapping(value = "/transfer/{channelId}")
|
||||
@Operation(summary = "支付渠道的统一【转账】回调")
|
||||
@PermitAll
|
||||
public String notifyTransfer(@PathVariable("channelId") Long channelId,
|
||||
@RequestParam(required = false) Map<String, String> params,
|
||||
@RequestBody(required = false) String body) {
|
||||
log.info("[notifyRefund][channelId({}) 回调数据({}/{})]", channelId, params, body);
|
||||
// 1. 校验支付渠道是否存在
|
||||
PayClient payClient = channelService.getPayClient(channelId);
|
||||
if (payClient == null) {
|
||||
log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId);
|
||||
throw exception(CHANNEL_NOT_FOUND);
|
||||
}
|
||||
|
||||
// 2. 解析通知数据
|
||||
PayTransferRespDTO notify = payClient.parseTransferNotify(params, body);
|
||||
payTransferService.notifyTransfer(channelId, notify);
|
||||
return "success";
|
||||
}
|
||||
|
||||
@GetMapping("/get-detail")
|
||||
@Operation(summary = "获得回调通知的明细")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
|
||||
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.pay.convert.transfer;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.transfer.PayDemoTransferCreateReqVO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferCreateReqVO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferPageItemRespVO;
|
||||
@@ -24,7 +25,9 @@ public interface PayTransferConvert {
|
||||
|
||||
PayTransferCreateReqDTO convert(PayDemoTransferCreateReqVO vo);
|
||||
|
||||
PayTransferRespVO convert(PayTransferDO bean);
|
||||
PayTransferRespVO convert(PayTransferDO bean);
|
||||
|
||||
PayTransferRespDTO convert3(PayTransferDO bean);
|
||||
|
||||
PageResult<PayTransferPageItemRespVO> convertPage(PageResult<PayTransferDO> pageResult);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.transfer.vo.PayTransferPageReqVO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@@ -44,6 +45,12 @@ public interface PayTransferMapper extends BaseMapperX<PayTransferDO> {
|
||||
default List<PayTransferDO> selectListByStatus(Integer status){
|
||||
return selectList(PayTransferDO::getStatus, status);
|
||||
}
|
||||
|
||||
default PayTransferDO selectByAppIdAndNo(Long appId, String no){
|
||||
return selectOne(new LambdaQueryWrapperX<PayTransferDO>()
|
||||
.eq(PayTransferDO::getAppId, appId)
|
||||
.eq(PayTransferDO::getNo, no));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -39,6 +39,15 @@ public class PayProperties {
|
||||
@URL(message = "支付回调地址的格式必须是 URL")
|
||||
private String refundNotifyUrl;
|
||||
|
||||
/**
|
||||
* 转账回调地址
|
||||
*
|
||||
* 实际上,对应的 PayNotifyController 的 notifyTransfer 方法的 URL
|
||||
*
|
||||
* 回调顺序:支付渠道(支付宝支付、微信支付) => yudao-module-pay 的 transferNotifyUrl 地址 => 业务的 PayAppDO.transferNotifyUrl 地址
|
||||
*/
|
||||
private String transferNotifyUrl;
|
||||
|
||||
/**
|
||||
* 支付订单 no 的前缀
|
||||
*/
|
||||
|
||||
@@ -177,6 +177,11 @@ public class WalletPayClient extends AbstractPayClient<NonePayClientConfig> {
|
||||
throw new IllegalStateException(String.format("支付退款单[%s] 状态不正确", outRefundNo));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body) throws Throwable {
|
||||
throw new UnsupportedOperationException("未实现");
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
|
||||
throw new UnsupportedOperationException("待实现");
|
||||
|
||||
@@ -78,5 +78,4 @@ public interface PayRefundService {
|
||||
* @return 同步到状态的退款数量,包括退款成功、退款失败
|
||||
*/
|
||||
int syncRefund();
|
||||
|
||||
}
|
||||
|
||||
@@ -193,6 +193,8 @@ public class PayRefundServiceImpl implements PayRefundService {
|
||||
TenantUtils.execute(channel.getTenantId(), () -> getSelf().notifyRefund(channel, notify));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 通知并更新订单的退款结果
|
||||
*
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.module.pay.service.transfer;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
|
||||
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.PayTransferPageReqVO;
|
||||
@@ -54,4 +55,12 @@ public interface PayTransferService {
|
||||
* @return 同步到状态的转账数量,包括转账成功、转账失败、转账中的
|
||||
*/
|
||||
int syncTransfer();
|
||||
|
||||
/**
|
||||
* 渠道的转账通知
|
||||
*
|
||||
* @param channelId 渠道编号
|
||||
* @param notify 通知
|
||||
*/
|
||||
void notifyTransfer(Long channelId, PayTransferRespDTO notify);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ 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.enums.notify.PayNotifyTypeEnum;
|
||||
import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum;
|
||||
import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties;
|
||||
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.notify.PayNotifyService;
|
||||
@@ -28,6 +29,7 @@ import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Validator;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
@@ -50,6 +52,9 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||
|
||||
private static final String TRANSFER_NO_PREFIX = "T";
|
||||
|
||||
@Resource
|
||||
private PayProperties payProperties;
|
||||
|
||||
@Resource
|
||||
private PayTransferMapper transferMapper;
|
||||
@Resource
|
||||
@@ -104,7 +109,7 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||
// 3. 调用三方渠道发起转账
|
||||
PayTransferUnifiedReqDTO transferUnifiedReq = INSTANCE.convert2(transfer)
|
||||
.setOutTransferNo(transfer.getNo());
|
||||
transferUnifiedReq.setNotifyUrl(payApp.getTransferNotifyUrl());
|
||||
transferUnifiedReq.setNotifyUrl(genChannelTransferNotifyUrl(channel));
|
||||
PayTransferRespDTO unifiedTransferResp = client.unifiedTransfer(transferUnifiedReq);
|
||||
// 4. 通知转账结果
|
||||
getSelf().notifyTransfer(channel, unifiedTransferResp);
|
||||
@@ -118,6 +123,16 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||
return transfer.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据支付渠道的编码,生成支付渠道的回调地址
|
||||
*
|
||||
* @param channel 支付渠道
|
||||
* @return 支付渠道的回调地址 配置地址 + "/" + channel id
|
||||
*/
|
||||
private String genChannelTransferNotifyUrl(PayChannelDO channel) {
|
||||
return payProperties.getTransferNotifyUrl() + "/" + channel.getId();
|
||||
}
|
||||
|
||||
private PayTransferDO validateTransferCanCreate(PayTransferCreateReqDTO dto, Long appId) {
|
||||
PayTransferDO transfer = transferMapper.selectByAppIdAndMerchantTransferId(appId, dto.getMerchantTransferId());
|
||||
if (transfer != null) {
|
||||
@@ -156,7 +171,8 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||
|
||||
private void notifyTransferInProgress(PayChannelDO channel, PayTransferRespDTO notify) {
|
||||
// 1.校验
|
||||
PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo());
|
||||
PayTransferDO transfer = transferMapper.selectByAppIdAndNo(
|
||||
channel.getAppId(), notify.getOutTransferNo());
|
||||
if (transfer == null) {
|
||||
throw exception(PAY_TRANSFER_NOT_FOUND);
|
||||
}
|
||||
@@ -174,16 +190,13 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||
throw exception(PAY_TRANSFER_STATUS_IS_NOT_WAITING);
|
||||
}
|
||||
log.info("[notifyTransferInProgress][transfer({}) 更新为转账进行中状态]", transfer.getId());
|
||||
|
||||
// 3. 插入转账通知记录
|
||||
notifyService.createPayNotifyTask(PayNotifyTypeEnum.TRANSFER.getType(),
|
||||
transfer.getId());
|
||||
}
|
||||
|
||||
|
||||
private void notifyTransferSuccess(PayChannelDO channel, PayTransferRespDTO notify) {
|
||||
// 1.校验
|
||||
PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo());
|
||||
PayTransferDO transfer = transferMapper.selectByAppIdAndNo(
|
||||
channel.getAppId(), notify.getOutTransferNo());
|
||||
if (transfer == null) {
|
||||
throw exception(PAY_TRANSFER_NOT_FOUND);
|
||||
}
|
||||
@@ -212,7 +225,8 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||
|
||||
private void notifyTransferClosed(PayChannelDO channel, PayTransferRespDTO notify) {
|
||||
// 1.校验
|
||||
PayTransferDO transfer = transferMapper.selectByNo(notify.getOutTransferNo());
|
||||
PayTransferDO transfer = transferMapper.selectByAppIdAndNo(
|
||||
channel.getAppId(), notify.getOutTransferNo());
|
||||
if (transfer == null) {
|
||||
throw exception(PAY_TRANSFER_NOT_FOUND);
|
||||
}
|
||||
@@ -285,7 +299,7 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyTransfer(Long channelId, PayTransferRespDTO notify) {
|
||||
public void notifyTransfer(Long channelId, PayTransferRespDTO notify) {
|
||||
// 校验渠道是否有效
|
||||
PayChannelDO channel = channelService.validPayChannel(channelId);
|
||||
// 通知转账结果给对应的业务
|
||||
|
||||
Reference in New Issue
Block a user