【功能优化】完成转账回调接口

This commit is contained in:
痴货
2024-10-05 21:32:36 +08:00
parent ae1cf9e098
commit 325d5e6b12
33 changed files with 378 additions and 42 deletions

View File

@@ -79,6 +79,8 @@ public interface PayClient {
*/
PayRefundRespDTO getRefund(String outTradeNo, String outRefundNo);
// ============ 转账相关 ==========
/**
* 调用渠道,进行转账
*
@@ -95,4 +97,13 @@ public interface PayClient {
* @return 转账信息
*/
PayTransferRespDTO getTransfer(String outTradeNo, PayTransferTypeEnum type);
/**
* 解析 transfer 回调数据
*
* @param params HTTP 回调接口 content type 为 application/x-www-form-urlencoded 的所有参数
* @param body HTTP 回调接口的 request body
* @return 转账信息
*/
PayTransferRespDTO parseTransferNotify(Map<String, String> params, String body);
}

View File

@@ -0,0 +1,128 @@
package cn.iocoder.yudao.framework.pay.core.client.dto.transfer;
import com.github.binarywang.wxpay.bean.notify.OriginNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayBaseNotifyV3Result;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@NoArgsConstructor
public class WxPayTransferPartnerNotifyV3Result implements Serializable, WxPayBaseNotifyV3Result<WxPayTransferPartnerNotifyV3Result.TransferNotifyResult> {
private static final long serialVersionUID = -1L;
/**
* 源数据
*/
private OriginNotifyResponse rawData;
/**
* 解密后的数据
*/
private TransferNotifyResult result;
@Override
public void setRawData(OriginNotifyResponse rawData) {
this.rawData = rawData;
}
@Override
public void setResult(TransferNotifyResult data) {
this.result = data;
}
public TransferNotifyResult getResult() {
return result;
}
public OriginNotifyResponse getRawData() {
return rawData;
}
@Data
@NoArgsConstructor
public static class TransferNotifyResult implements Serializable {
private static final long serialVersionUID = 1L;
/*********************** 公共字段 ********************
/**
* 商家批次单号
*/
@SerializedName(value = "out_batch_no")
protected String outBatchNo;
/**
* 微信批次单号
*/
@SerializedName(value = "batch_id")
protected String batchId;
/**
* 批次状态
*/
@SerializedName(value = "batch_status")
protected String batchStatus;
/**
* 批次总笔数
*/
@SerializedName(value = "total_num")
protected Integer totalNum;
/**
* 批次总金额
*/
@SerializedName(value = "total_amount")
protected Integer totalAmount;
/**
* 批次更新时间
*/
@SerializedName(value = "update_time")
private String updateTime;
/*********************** FINISHED ********************
/**
* 转账成功金额
*/
@SerializedName(value = "success_amount")
protected Integer successAmount;
/**
* 转账成功笔数
*/
@SerializedName(value = "success_num")
protected Integer successNum;
/**
* 转账失败金额
*/
@SerializedName(value = "fail_amount")
protected Integer failAmount;
/**
* 转账失败笔数
*/
@SerializedName(value = "fail_num")
protected Integer failNum;
/*********************** CLOSED ********************
/**
* 商户号
*/
@SerializedName(value = "mchid")
protected String mchId;
/**
* 批次关闭原因
*/
@SerializedName(value = "close_reason")
protected String closeReason;
}
}

View File

@@ -219,6 +219,22 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
}
}
@Override
public final PayTransferRespDTO parseTransferNotify(Map<String, String> params, String body) {
try {
return doParseTransferNotify(params, body);
} catch (ServiceException ex) { // 业务异常,都是实现类已经翻译,所以直接抛出即可
throw ex;
} catch (Throwable ex) {
log.error("[doParseTransferNotify][客户端({}) params({}) body({}) 解析失败]",
getId(), params, body, ex);
throw buildPayException(ex);
}
}
protected abstract PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body)
throws Throwable;
@Override
public final PayTransferRespDTO getTransfer(String outTradeNo, PayTransferTypeEnum type) {
try {

View File

@@ -325,6 +325,11 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
}
}
@Override
protected PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body) throws Throwable {
throw new UnsupportedOperationException("未实现");
}
// ========== 各种工具方法 ==========
protected String formatAmount(Integer amount) {

View File

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
import com.alipay.api.AlipayApiException;
@@ -56,4 +57,5 @@ public class AlipayAppPayClient extends AbstractAlipayPayClient {
return PayOrderRespDTO.waitingOf(displayMode, response.getBody(),
reqDTO.getOutTradeNo(), response);
}
}

View File

@@ -5,6 +5,7 @@ import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
import com.alipay.api.AlipayApiException;
@@ -82,4 +83,5 @@ public class AlipayBarPayClient extends AbstractAlipayPayClient {
return PayOrderRespDTO.waitingOf(displayMode, "",
reqDTO.getOutTradeNo(), response);
}
}

View File

@@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.Method;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
import com.alipay.api.AlipayApiException;
@@ -66,4 +67,5 @@ public class AlipayPcPayClient extends AbstractAlipayPayClient {
return PayOrderRespDTO.waitingOf(displayMode, response.getBody(),
reqDTO.getOutTradeNo(), response);
}
}

View File

@@ -57,6 +57,11 @@ public class MockPayClient extends AbstractPayClient<NonePayClientConfig> {
outRefundNo, MOCK_RESP_SUCCESS_DATA);
}
@Override
protected PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body) throws Throwable {
throw new UnsupportedOperationException("未实现");
}
@Override
protected PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body) {
throw new UnsupportedOperationException("模拟支付无退款回调");

View File

@@ -14,14 +14,11 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.WxPayTransferPartnerNotifyV3Result;
import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum;
import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
import com.binarywang.spring.starter.wxjava.miniapp.properties.WxMaProperties;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyV3Result;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyV3Result;
import com.github.binarywang.wxpay.bean.notify.*;
import com.github.binarywang.wxpay.bean.request.*;
import com.github.binarywang.wxpay.bean.result.*;
import com.github.binarywang.wxpay.bean.transfer.TransferBatchesRequest;
@@ -31,7 +28,6 @@ import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.TransferService;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import java.time.LocalDateTime;
@@ -355,6 +351,29 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
return PayRefundRespDTO.failureOf(result.getOutRefundNo(), response);
}
@Override
public PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body) throws WxPayException {
switch (config.getApiVersion()) {
case API_VERSION_V3:
return parseTransferNotifyV3(body);
default:
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
}
}
private PayTransferRespDTO parseTransferNotifyV3(String body) throws WxPayException {
WxPayTransferPartnerNotifyV3Result response = client.baseParseOrderNotifyV3Result(body, null, WxPayTransferPartnerNotifyV3Result.class, WxPayTransferPartnerNotifyV3Result.TransferNotifyResult.class);
WxPayTransferPartnerNotifyV3Result.TransferNotifyResult result = response.getResult();
// 2. 构建结果
if (Objects.equals("FINISHED", result.getBatchStatus())) {
if(result.getFailNum() <= 0){
return PayTransferRespDTO.successOf(result.getBatchId(), parseDateV3(result.getUpdateTime()),
result.getOutBatchNo(), response);
}
}
return PayTransferRespDTO.closedOf(result.getBatchStatus(), result.getCloseReason(), result.getOutBatchNo(), response);
}
@Override
protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) throws WxPayException {
try {
@@ -452,7 +471,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
.transferDetailList(transferDetailList).build();
transferBatches.setNotifyUrl(reqDTO.getNotifyUrl());
TransferBatchesResult transferBatchesResult = transferService.transferBatches(transferBatches);
return PayTransferRespDTO.waitingOf(reqDTO.getOutTransferNo(), transferBatchesResult.getBatchId() ,transferBatchesResult);
return PayTransferRespDTO.dealingOf(transferBatchesResult.getBatchId(), reqDTO.getOutTransferNo(), transferBatchesResult);
}
@Override