feat:【MALL 商城】商城分佣提现,初步对接成功微信支付

This commit is contained in:
YunaiV
2025-05-11 08:12:42 +08:00
parent b91a30dd3e
commit 4d25e810e3
22 changed files with 162 additions and 225 deletions

View File

@@ -14,7 +14,7 @@ import java.util.Map;
*
* @author 芋道源码
*/
public interface PayClient {
public interface PayClient<Config> {
/**
* 获得渠道编号
@@ -23,6 +23,13 @@ public interface PayClient {
*/
Long getId();
/**
* 获得渠道配置
*
* @return 渠道配置
*/
Config getConfig();
// ============ 支付相关 ==========
/**

View File

@@ -1,129 +0,0 @@
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;
// TODO @luchi这个可以复用 wxjava 里的类么?
@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

@@ -23,7 +23,7 @@ import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString
* @author 芋道源码
*/
@Slf4j
public abstract class AbstractPayClient<Config extends PayClientConfig> implements PayClient {
public abstract class AbstractPayClient<Config extends PayClientConfig> implements PayClient<Config> {
/**
* 渠道编号
@@ -74,6 +74,11 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
return channelId;
}
@Override
public Config getConfig() {
return config;
}
// ============ 支付相关 ==========
@Override

View File

@@ -15,13 +15,13 @@ 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 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.TransferBillsGetResult;
import com.github.binarywang.wxpay.bean.transfer.TransferBillsNotifyResult;
import com.github.binarywang.wxpay.bean.transfer.TransferBillsRequest;
import com.github.binarywang.wxpay.bean.transfer.TransferBillsResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
@@ -354,34 +354,6 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
return PayRefundRespDTO.failureOf(result.getOutRefundNo(), response);
}
@Override
public PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body, Map<String, String> headers) throws WxPayException {
switch (config.getApiVersion()) {
case API_VERSION_V3:
return parseTransferNotifyV3(body, headers);
case API_VERSION_V2:
throw new UnsupportedOperationException("V2 版本暂不支持,建议使用 V3 版本");
default:
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
}
}
private PayTransferRespDTO parseTransferNotifyV3(String body, Map<String, String> headers) throws WxPayException {
// 1. 解析回调
SignatureHeader signatureHeader = getRequestHeader(headers);
// TODO @luchi这个可以复用 wxjava 里的类么?
WxPayTransferPartnerNotifyV3Result response = client.baseParseOrderNotifyV3Result(body, signatureHeader, 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 {
@@ -522,6 +494,37 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
response.getOutBillNo(), response);
}
@Override
public PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body, Map<String, String> headers) throws WxPayException {
switch (config.getApiVersion()) {
case API_VERSION_V3:
return parseTransferNotifyV3(body, headers);
case API_VERSION_V2:
throw new UnsupportedOperationException("V2 版本暂不支持,建议使用 V3 版本");
default:
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
}
}
private PayTransferRespDTO parseTransferNotifyV3(String body, Map<String, String> headers) throws WxPayException {
// 1. 解析回调
SignatureHeader signatureHeader = getRequestHeader(headers);
TransferBillsNotifyResult response = client.getTransferService().parseTransferBillsNotifyResult(body, signatureHeader);
TransferBillsNotifyResult.DecryptNotifyResult result = response.getResult();
// 2. 创建返回结果
String state = result.getState();
if (ObjectUtils.equalsAny(state, "ACCEPTED", "PROCESSING", "WAIT_USER_CONFIRM", "TRANSFERING")) {
return PayTransferRespDTO.processingOf(result.getTransferBillNo(), result.getOutBillNo(), response);
}
if (Objects.equals("SUCCESS", state)) {
return PayTransferRespDTO.successOf(result.getTransferBillNo(), parseDateV3(result.getUpdateTime()),
result.getOutBillNo(), response);
}
return PayTransferRespDTO.closedOf(state, result.getFailReason(),
result.getOutBillNo(), response);
}
// ========== 各种工具方法 ==========
/**