feat:【MALL 商城】商城分佣提现,初步对接成功微信支付
This commit is contained in:
@@ -70,5 +70,12 @@ public class PayTransferRespDTO {
|
||||
* @see <a href="https://pay.weixin.qq.com/doc/v3/merchant/4012716430">JSAPI 调起用户确认收款</a>
|
||||
*/
|
||||
private String channelPackageInfo;
|
||||
/**
|
||||
* 渠道商户号
|
||||
*
|
||||
* 特殊:目前只有微信转账有这个东西!!!
|
||||
* @see <a href="https://pay.weixin.qq.com/doc/v3/merchant/4012716430">JSAPI 调起用户确认收款</a>
|
||||
*/
|
||||
private String channelMchId;
|
||||
|
||||
}
|
||||
|
@@ -1,10 +1,13 @@
|
||||
package cn.iocoder.yudao.module.pay.api.transfer;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.impl.weixin.WxPayClientConfig;
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO;
|
||||
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.service.channel.PayChannelService;
|
||||
import cn.iocoder.yudao.module.pay.service.transfer.PayTransferService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -21,6 +24,8 @@ public class PayTransferApiImpl implements PayTransferApi {
|
||||
|
||||
@Resource
|
||||
private PayTransferService payTransferService;
|
||||
@Resource
|
||||
private PayChannelService payChannelService;
|
||||
|
||||
@Override
|
||||
public PayTransferCreateRespDTO createTransfer(PayTransferCreateReqDTO reqDTO) {
|
||||
@@ -30,7 +35,15 @@ public class PayTransferApiImpl implements PayTransferApi {
|
||||
@Override
|
||||
public PayTransferRespDTO getTransfer(Long id) {
|
||||
PayTransferDO transfer = payTransferService.getTransfer(id);
|
||||
return BeanUtils.toBean(transfer, PayTransferRespDTO.class);
|
||||
if (transfer == null) {
|
||||
return null;
|
||||
}
|
||||
PayChannelDO channel = payChannelService.getChannel(transfer.getChannelId());
|
||||
String mchId = null;
|
||||
if (channel != null && channel.getConfig() instanceof WxPayClientConfig) {
|
||||
mchId = ((WxPayClientConfig) channel.getConfig()).getMchId();
|
||||
}
|
||||
return BeanUtils.toBean(transfer, PayTransferRespDTO.class).setChannelMchId(mchId);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -80,12 +80,5 @@ public class PayDemoWithdrawDO extends BaseDO {
|
||||
* 转账错误提示
|
||||
*/
|
||||
private String transferErrorMsg;
|
||||
/**
|
||||
* 渠道 package 信息
|
||||
*
|
||||
* 特殊:目前只有微信转账有这个东西!!!
|
||||
* @see <a href="https://pay.weixin.qq.com/doc/v3/merchant/4012716430">JSAPI 调起用户确认收款</a>
|
||||
*/
|
||||
private String transferChannelPackageInfo;
|
||||
|
||||
}
|
@@ -88,8 +88,7 @@ public class PayDemoTransferServiceImpl implements PayDemoWithdrawService {
|
||||
|
||||
// 2.2 更新转账单到 demo 示例提现单,并将状态更新为转账中
|
||||
demoTransferMapper.updateByIdAndStatus(withdraw.getId(), withdraw.getStatus(),
|
||||
new PayDemoWithdrawDO().setPayTransferId(transferRespDTO.getId())
|
||||
.setTransferChannelPackageInfo(transferRespDTO.getChannelPackageInfo()));
|
||||
new PayDemoWithdrawDO().setPayTransferId(transferRespDTO.getId()));
|
||||
return transferRespDTO.getId();
|
||||
}
|
||||
|
||||
|
@@ -174,7 +174,7 @@ public class PayTransferServiceImpl implements PayTransferService {
|
||||
int updateCounts = transferMapper.updateByIdAndStatus(transfer.getId(),
|
||||
PayTransferStatusEnum.WAITING.getStatus(),
|
||||
new PayTransferDO().setStatus(PayTransferStatusEnum.PROCESSING.getStatus())
|
||||
.setChannelPackageInfo(transfer.getChannelPackageInfo()));
|
||||
.setChannelPackageInfo(notify.getChannelPackageInfo()));
|
||||
if (updateCounts == 0) {
|
||||
throw exception(PAY_TRANSFER_NOTIFY_FAIL_STATUS_IS_NOT_WAITING);
|
||||
}
|
||||
|
@@ -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();
|
||||
|
||||
// ============ 支付相关 ==========
|
||||
|
||||
/**
|
||||
|
@@ -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;
|
||||
|
||||
}
|
||||
}
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
// ========== 各种工具方法 ==========
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user