🆕 #3474 【微信支付】增加2025.1.15正式上线的商户转账新版本的相关接口

This commit is contained in:
allovine 2025-01-16 13:46:02 +08:00 committed by GitHub
parent 83bd92d260
commit be0dd8b692
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 317 additions and 0 deletions

View File

@ -0,0 +1,79 @@
package com.github.binarywang.wxpay.bean.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;
/**
* <pre>
* 商家转账到零钱接口将转账结果通知用户
* 文档地址https://pay.weixin.qq.com/doc/v3/merchant/4012716434
* </pre>
*/
@Data
public class TransferBillsNotifyResult implements Serializable, WxPayBaseNotifyV3Result<TransferBillsNotifyResult.DecryptNotifyResult> {
/**
* 源数据
*/
private OriginNotifyResponse rawData;
/**
* 解密后的数据
*/
private TransferBillsNotifyResult.DecryptNotifyResult result;
@Data
@NoArgsConstructor
public static class DecryptNotifyResult implements Serializable {
/**
* 商户号
*/
@SerializedName(value = "mch_id")
private String mchId;
/**
* 商家批次单号
*/
@SerializedName(value = "out_bill_no")
private String outBillNo;
/**
* 微信批次单号
*/
@SerializedName(value = "transfer_bill_no")
private String transferBillNo;
/**
* 批次状态
*/
@SerializedName(value = "state")
private String state;
/**
* 转账金额
*/
@SerializedName(value = "transfer_amount")
private Integer transferAmount;
/**
* 批次状态
*/
@SerializedName(value = "openid")
private String openid;
/**
* 单据创建时间
*/
@SerializedName(value = "create_time")
private String createTime;
/**
* 最后一次状态变更时间
*/
@SerializedName(value = "update_time")
private String updateTime;
/**
* 错误原因
*/
@SerializedName(value = "fail_reason")
private String failReason;
}
}

View File

@ -0,0 +1,108 @@
package com.github.binarywang.wxpay.bean.transfer;
import com.github.binarywang.wxpay.v3.SpecEncrypt;
import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* 发起商家转账API参数
*
* @author allovine
* created on 2025/1/15
**/
@Data
@Builder(builderMethodName = "newBuilder")
@NoArgsConstructor
@AllArgsConstructor
public class TransferBillsRequest implements Serializable {
private static final long serialVersionUID = -2175582517588397437L;
/**
* 直连商户的appid
*/
@SerializedName("appid")
private String appid;
/**
* 商户系统内部的商家单号
*/
@SerializedName("out_bill_no")
private String outBillNo;
/**
* 转账场景ID
* 商户平台-产品中心-商家转账 申请
* 佣金报酬 ID:1005
*/
@SerializedName("transfer_scene_id")
private String transferSceneId;
/**
* 用户在直连商户应用下的用户标示
*/
@SerializedName("openid")
private String openid;
/**
* 收款用户姓名
*/
@SpecEncrypt
@SerializedName("user_name")
private String userName;
/**
* 转账金额
*/
@SerializedName("transfer_amount")
private Integer transferAmount;
/**
* 转账备注
*/
@SerializedName("transfer_remark")
private String transferRemark;
/**
* 异步接收微信支付结果通知的回调地址通知url必须为公网可访问的url必须为https不能携带参数
*/
@SerializedName("notify_url")
private String notifyUrl;
/**
* 用户收款感知
*/
@SerializedName("user_recv_perception")
private String userRecvPerception;
/**
* 转账场景报备信息
*/
@SerializedName("transfer_scene_report_infos")
private List<TransferSceneReportInfo> transferSceneReportInfos;
@Data
@Builder(builderMethodName = "newBuilder")
@AllArgsConstructor
@NoArgsConstructor
public static class TransferSceneReportInfo {
/**
* 信息类型
*/
@SerializedName("info_type")
private String infoType;
/**
* 信息内容
*/
@SerializedName("info_content")
private String infoContent;
}
}

View File

@ -0,0 +1,55 @@
package com.github.binarywang.wxpay.bean.transfer;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 商家转账结果
*
* @author allovine
* created on 2025/1/15
**/
@Data
@NoArgsConstructor
public class TransferBillsResult implements Serializable {
private static final long serialVersionUID = -2175582517588397437L;
/**
* 商户单号
*/
@SerializedName("out_bill_no")
private String outBillNo;
/**
* 微信转账单号
*/
@SerializedName("transfer_bill_no")
private String transferBillNo;
/**
* 单据创建时间
*/
@SerializedName("create_time")
private String createTime;
/**
* 单据状态
*/
@SerializedName("status")
private String status;
/**
* 失败原因
*/
@SerializedName("fail_reason")
private String failReason;
/**
* 跳转领取页面的package信息
*/
@SerializedName("package_info")
private String packageInfo;
}

View File

@ -111,4 +111,31 @@ public interface TransferService {
*/
TransferBatchDetailResult transferBatchesOutBatchNoDetail(String outBatchNo, String outDetailNo) throws WxPayException;
/**
* <pre>
*
* 2025.1.15 开始新接口 发起商家转账API
*
* 请求方式POSTHTTPS
* 请求地址<a href="https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills">请求地址</a>
*
* 文档地址<a href="https://pay.weixin.qq.com/doc/v3/merchant/4012716434">发起商家转账API</a>
* </pre>
*
* @param request 转账请求参数
* @return TransferBillsResult 转账结果
* @throws WxPayException .
*/
TransferBillsResult transferBills(TransferBillsRequest request) throws WxPayException;
/**
* 2025.1.15 开始新接口 解析商家转账结果
* 详见<a href="https://pay.weixin.qq.com/doc/v3/merchant/4012712115"></a>
*
* @param notifyData 通知数据
* @param header 通知头部数据不传则表示不校验头
* @return the wx transfer notify result
* @throws WxPayException the wx pay exception
*/
TransferBillsNotifyResult parseTransferBillsNotifyResult(String notifyData, SignatureHeader header) throws WxPayException;
}

View File

@ -6,6 +6,7 @@ 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.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.bean.transfer.TransferBillsNotifyResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
@ -991,6 +992,17 @@ public interface WxPayService {
*/
WxPayTransferBatchesNotifyV3Result parseTransferBatchesNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException;
/**
* 解析商家转账批次回调通知
* https://pay.weixin.qq.com/doc/v3/merchant/4012712115
*
* @param notifyData
* @param header
* @return
* @throws WxPayException
*/
TransferBillsNotifyResult parseTransferBillsNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException;
/**
* 解析服务商模式退款结果通知
* 详见https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_1_11.shtml

View File

@ -11,6 +11,7 @@ import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;
import com.github.binarywang.wxpay.bean.request.*;
import com.github.binarywang.wxpay.bean.result.*;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.bean.transfer.TransferBillsNotifyResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.config.WxPayConfigHolder;
import com.github.binarywang.wxpay.constant.WxPayConstants;
@ -442,6 +443,11 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
return this.baseParseOrderNotifyV3Result(notifyData, header, WxPayTransferBatchesNotifyV3Result.class, WxPayTransferBatchesNotifyV3Result.DecryptNotifyResult.class);
}
@Override
public TransferBillsNotifyResult parseTransferBillsNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException {
return this.baseParseOrderNotifyV3Result(notifyData, header, TransferBillsNotifyResult.class, TransferBillsNotifyResult.DecryptNotifyResult.class);
}
@Override
public WxPayPartnerRefundNotifyV3Result parsePartnerRefundNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException {
return this.baseParseOrderNotifyV3Result(notifyData, header, WxPayPartnerRefundNotifyV3Result.class, WxPayPartnerRefundNotifyV3Result.DecryptNotifyResult.class);

View File

@ -85,4 +85,20 @@ public class TransferServiceImpl implements TransferService {
String result = this.payService.getV3(url);
return GSON.fromJson(result, TransferBatchDetailResult.class);
}
@Override
public TransferBillsResult transferBills(TransferBillsRequest request) throws WxPayException {
String url = String.format("%s/v3/fund-app/mch-transfer/transfer-bills", this.payService.getPayBaseUrl());
if (request.getUserName() != null && request.getUserName().length() > 0) {
X509Certificate validCertificate = this.payService.getConfig().getVerifier().getValidCertificate();
RsaCryptoUtil.encryptFields(request, validCertificate);
}
String result = this.payService.postV3WithWechatpaySerial(url, GSON.toJson(request));
return GSON.fromJson(result, TransferBillsResult.class);
}
@Override
public TransferBillsNotifyResult parseTransferBillsNotifyResult(String notifyData, SignatureHeader header) throws WxPayException {
return this.payService.baseParseOrderNotifyV3Result(notifyData, header, TransferBillsNotifyResult.class, TransferBillsNotifyResult.DecryptNotifyResult.class);
}
}

View File

@ -2,6 +2,7 @@ package com.github.binarywang.wxpay.service.impl;
import com.github.binarywang.wxpay.bean.transfer.QueryTransferBatchesRequest;
import com.github.binarywang.wxpay.bean.transfer.TransferBatchesRequest;
import com.github.binarywang.wxpay.bean.transfer.TransferBillsRequest;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.testbase.ApiTestModule;
@ -73,4 +74,17 @@ public class TransferServiceImplTest {
public void testTransferBatchesOutBatchNoDetail() throws WxPayException {
log.info("商家明细单号查询明细单:{}", this.payService.getTransferService().transferBatchesOutBatchNoDetail("1655447999520", "1655447989156"));
}
@Test
public void testTransferBills() throws WxPayException {
TransferBillsRequest transferBillsRequest = TransferBillsRequest.newBuilder()
.appid("wxf636efh5xxxxx")
.outBillNo("1655447989156")
.transferSceneId("1005")
.transferAmount(100)
.transferRemark("测试转账")
.openid("oX_7Jzr9gSZz4X_Xc9-_7HGf8XzI")
.userName("测试用户").build();
log.info("发起商家转账:{}", this.payService.getTransferService().transferBills(transferBillsRequest));
}
}