diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsCancelResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsCancelResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..9e59fecf73bf85b79dfae7249843611634d38f7c
--- /dev/null
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsCancelResult.java
@@ -0,0 +1,48 @@
+package com.github.binarywang.wxpay.bean.transfer;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ *
+ * 商家转账到零钱撤销转账接口
+ * 文档地址:https://pay.weixin.qq.com/doc/v3/merchant/4012716458
+ *
+ *
+ * @author Nor
+ * @date 2025/1/17
+ */
+@Data
+@NoArgsConstructor
+public class TransferBillsCancelResult implements Serializable {
+ private static final long serialVersionUID = -4935840810530008418L;
+
+ /**
+ * 【商户单号】 商户系统内部的商家单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一
+ */
+ @SerializedName("out_bill_no")
+ private String outBillNo;
+
+ /**
+ * 【微信转账单号】 微信转账单号,微信商家转账系统返回的唯一标识
+ */
+ @SerializedName("transfer_bill_no")
+ private String transferBillNo;
+
+ /**
+ * 【单据状态】 商家转账订单状态
+ * 可选取值
+ * CANCELING: 商户撤销请求受理成功,该笔转账正在撤销中
+ * CANCELLED: 转账撤销完成
+ */
+ private String state;
+
+ /**
+ * 【最后一次单据状态变更时间】 按照使用rfc3339所定义的格式,格式为yyyy-MM-DDThh:mm:ss+TIMEZONE
+ */
+ @SerializedName("update_time")
+ private String updateTime;
+}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsGetResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsGetResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..2e24a4a3c647a21a962573e2134b743c8ee82f80
--- /dev/null
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsGetResult.java
@@ -0,0 +1,103 @@
+package com.github.binarywang.wxpay.bean.transfer;
+
+import com.github.binarywang.wxpay.constant.WxPayConstants;
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ *
+ * 商家转账到零钱查询转账单接口
+ * 文档地址:https://pay.weixin.qq.com/doc/v3/merchant/4012716457 https://pay.weixin.qq.com/doc/v3/merchant/4012716437
+ *
+ *
+ * @author Nor
+ * @date 2025/1/17
+ */
+@Data
+@NoArgsConstructor
+public class TransferBillsGetResult implements Serializable {
+ private static final long serialVersionUID = -6376955113492371763L;
+
+ /**
+ * 【商户号】 微信支付分配的商户号
+ */
+ @SerializedName("mch_id")
+ private String mchId;
+
+ /**
+ * 【商户单号】 商户系统内部的商家单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一
+ */
+ @SerializedName("out_bill_no")
+ private String outBillNo;
+
+ /**
+ * 【商家转账订单号】 商家转账订单的主键,唯一定义此资源的标识
+ */
+ @SerializedName("transfer_bill_no")
+ private String transferBillNo;
+
+ /**
+ * 【商户AppID】 申请商户号的AppID或商户号绑定的AppID(企业号corpid即为此AppID)
+ */
+ private String appid;
+
+ /**
+ * 【单据状态】
+ * 可选取值
+ * ACCEPTED: 转账已受理
+ * PROCESSING: 转账处理中,转账结果尚未明确,如一直处于此状态,建议检查账户余额是否足够
+ * WAIT_USER_CONFIRM: 待收款用户确认,可拉起微信收款确认页面进行收款确认
+ * TRANSFERING: 转账结果尚未明确,可拉起微信收款确认页面再次重试确认收款
+ * SUCCESS: 转账成功
+ * FAIL: 转账失败
+ * CANCELING: 商户撤销请求受理成功,该笔转账正在撤销中
+ * CANCELLED: 转账撤销完成
+ *
+ * @see WxPayConstants.TransformBillState
+ */
+ private String state;
+
+ /**
+ * 【转账金额】 转账金额单位为“分”。
+ */
+ @SerializedName("transfer_amount")
+ private String transferAmount;
+
+ /**
+ * 【转账备注】 单条转账备注(微信用户会收到该备注),UTF8编码,最多允许32个字符
+ */
+ @SerializedName("transfer_remark")
+ private String transferRemark;
+
+ /**
+ * 【失败原因】 订单已失败或者已退资金时,返回失败原因
+ */
+ @SerializedName("fail_reason")
+ private String failReason;
+
+ /**
+ * 【收款用户OpenID】 商户AppID下,某用户的OpenID
+ */
+ private String openid;
+
+ /**
+ * 【收款用户姓名】 收款方真实姓名。支持标准RSA算法和国密算法,公钥由微信侧提供转账金额 >= 2,000元时,该笔明细必须填写若商户传入收款用户姓名,微信支付会校验用户OpenID与姓名是否一致,并提供电子回单
+ */
+ @SerializedName("user_name")
+ private String userName;
+
+ /**
+ * 【单据创建时间】 单据受理成功时返回,按照使用rfc3339所定义的格式,格式为yyyy-MM-DDThh:mm:ss+TIMEZONE
+ */
+ @SerializedName("create_time")
+ private String createTime;
+
+ /**
+ * 【最后一次状态变更时间】 单据最后更新时间,按照使用rfc3339所定义的格式,格式为yyyy-MM-DDThh:mm:ss+TIMEZONE
+ */
+ @SerializedName("update_time")
+ private String updateTime;
+}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsResult.java
index 9f7aac7fbb40343d3ecbc636c226e6d8ba10786f..78e0aec6abb2d2ba49df61623ee197e27018de83 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsResult.java
@@ -1,5 +1,6 @@
package com.github.binarywang.wxpay.bean.transfer;
+import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
@@ -37,9 +38,11 @@ public class TransferBillsResult implements Serializable {
/**
* 单据状态
+ *
+ * @see WxPayConstants.TransformBillState
*/
- @SerializedName("status")
- private String status;
+ @SerializedName("state")
+ private String state;
/**
* 失败原因
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java
index 819cdfe731d1e0d5d2145fa6d0b8bce932c33e2b..e8a6b6acb35116628628bbfbfac3b46218a2b9b2 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java
@@ -6,6 +6,7 @@ import com.github.binarywang.wxpay.bean.order.WxPayMwebOrderResult;
import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;
import com.github.binarywang.wxpay.bean.result.WxPayMicropayResult;
import com.google.common.collect.Lists;
+import lombok.experimental.UtilityClass;
import org.apache.commons.lang3.time.FastDateFormat;
import java.text.Format;
@@ -353,4 +354,86 @@ public class WxPayConstants {
public static final String PERSONAL_SUB_OPENID = "PERSONAL_SUB_OPENID";
}
+ /**
+ * 微信商户转账订单状态
+ */
+ @UtilityClass
+ public static class TransformBillState {
+ /**
+ * 转账已受理
+ */
+ public static final String ACCEPTED = "ACCEPTED";
+
+ /**
+ * 转账处理中,转账结果尚未明确,如一直处于此状态,建议检查账户余额是否足够
+ */
+ public static final String PROCESSING = "PROCESSING";
+
+ /**
+ * 待收款用户确认,可拉起微信收款确认页面进行收款确认
+ */
+ public static final String WAIT_USER_CONFIRM = "WAIT_USER_CONFIRM";
+
+ /**
+ * 转账结果尚未明确,可拉起微信收款确认页面再次重试确认收款
+ */
+ public static final String TRANSFERING = "TRANSFERING";
+
+ /**
+ * 转账成功
+ */
+ public static final String SUCCESS = "SUCCESS";
+
+ /**
+ * 转账失败
+ */
+ public static final String FAIL = "FAIL";
+
+ /**
+ * 商户撤销请求受理成功,该笔转账正在撤销中
+ */
+ public static final String CANCELING = "CANCELING";
+
+ /**
+ * 转账撤销完成
+ */
+ public static final String CANCELLED = "CANCELLED";
+
+ }
+
+ /**
+ * 【转账场景ID】 该笔转账使用的转账场景,可前往“商户平台-产品中心-商家转账”中申请。
+ */
+ @UtilityClass
+ public static class TransformSceneId {
+ /**
+ * 现金营销
+ */
+ public static final String CASH_MARKETING = "1001";
+ }
+
+ /**
+ * 用户收款感知
+ *
+ * @see 官方文档
+ */
+ @UtilityClass
+ public static class UserRecvPerception {
+ /**
+ * 转账场景 现金营销
+ * 场景介绍 向参与营销活动的用户发放现金奖励
+ */
+ public static class CASH_MARKETING {
+ /**
+ * 默认展示
+ */
+ public static final String ACTIVITY = "活动奖励";
+
+ /**
+ * 需在发起转账时,“用户收款感知”字段主动传入“现金奖励”才可展示
+ */
+ public static final String CASH = "现金奖励";
+ }
+
+ }
}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/TransferService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/TransferService.java
index c02430a960ea8a5ac147f93990a254955857e5a7..01113c95065a624dc6855d5490f072449cb4c149 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/TransferService.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/TransferService.java
@@ -128,6 +128,57 @@ public interface TransferService {
*/
TransferBillsResult transferBills(TransferBillsRequest request) throws WxPayException;
+ /**
+ *
+ *
+ * 2025.1.15 开始新接口 撤销转账API
+ *
+ * 请求方式:POST(HTTPS)
+ * 请求地址:请求地址
+ *
+ * 文档地址:商户撤销转账API
+ *
+ *
+ * @param outBillNo 【商户单号】 商户系统内部的商家单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一
+ * @return TransformBillsGetResult 转账单
+ * @throws WxPayException .
+ */
+ TransferBillsCancelResult transformBillsCancel(String outBillNo) throws WxPayException;
+
+ /**
+ *
+ *
+ * 2025.1.15 开始新接口 发起商家转账API
+ *
+ * 请求方式:GET(HTTPS)
+ * 请求地址:请求地址
+ *
+ * 文档地址:商户单号查询转账单API
+ *
+ *
+ * @param outBillNo 【商户单号】 商户系统内部的商家单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一
+ * @return TransformBillsGetResult 转账单
+ * @throws WxPayException .
+ */
+ TransferBillsGetResult getBillsByOutBillNo(String outBillNo) throws WxPayException;
+
+ /**
+ *
+ *
+ * 2025.1.15 开始新接口 微信单号查询转账单API
+ *
+ * 请求方式:GET(HTTPS)
+ * 请求地址:请求地址
+ *
+ * 文档地址:商户单号查询转账单API
+ *
+ *
+ * @param transferBillNo 【微信转账单号】 微信转账单号,微信商家转账系统返回的唯一标识
+ * @return TransformBillsGetResult 转账单
+ * @throws WxPayException .
+ */
+ TransferBillsGetResult getBillsByTransferBillNo(String transferBillNo) throws WxPayException;
+
/**
* 2025.1.15 开始新接口 解析商家转账结果
* 详见
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java
index 19b4ed0a07a38d1d1a5ce2e20ed522b21086b5d3..8ceac2b6ba69b8f38cd93060ab819cf3917070db 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java
@@ -39,16 +39,18 @@ public interface WxPayService {
* Map里 加入新的 {@link WxPayConfig},适用于动态添加新的微信商户配置.
*
* @param mchId 商户id
+ * @param appId 微信应用id
* @param wxPayConfig 新的微信配置
*/
- void addConfig(String mchId, WxPayConfig wxPayConfig);
+ void addConfig(String mchId, String appId, WxPayConfig wxPayConfig);
/**
- * 从 Map中 移除 {@link String mchId} 所对应的 {@link WxPayConfig},适用于动态移除微信商户配置.
+ * 从 Map中 移除 {@link String mchId} 和 {@link String appId} 所对应的 {@link WxPayConfig},适用于动态移除微信商户配置.
*
* @param mchId 对应商户的标识
+ * @param appId 微信应用id
*/
- void removeConfig(String mchId);
+ void removeConfig(String mchId, String appId);
/**
* 注入多个 {@link WxPayConfig} 的实现. 并为每个 {@link WxPayConfig} 赋予不同的 {@link String mchId} 值
@@ -70,17 +72,19 @@ public interface WxPayService {
* 进行相应的商户切换.
*
* @param mchId 商户标识
+ * @param appId 微信应用id
* @return 切换是否成功 boolean
*/
- boolean switchover(String mchId);
+ boolean switchover(String mchId, String appId);
/**
* 进行相应的商户切换.
*
* @param mchId 商户标识
+ * @param appId 微信应用id
* @return 切换成功 ,则返回当前对象,方便链式调用,否则抛出异常
*/
- WxPayService switchoverTo(String mchId);
+ WxPayService switchoverTo(String mchId, String appId);
/**
* 发送post请求,得到响应字节数组.
@@ -617,10 +621,10 @@ public interface WxPayService {
/**
* 调用统一下单接口,并组装生成支付所需参数对象.
*
- * @param 请使用{@link com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result}里的内部类或字段
+ * @param 请使用{@link WxPayUnifiedOrderV3Result}里的内部类或字段
* @param tradeType the trade type
* @param request 统一下单请求参数
- * @return 返回 {@link com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result}里的内部类或字段
+ * @return 返回 {@link WxPayUnifiedOrderV3Result}里的内部类或字段
* @throws WxPayException the wx pay exception
*/
T createOrderV3(TradeTypeEnum tradeType, WxPayUnifiedOrderV3Request request) throws WxPayException;
@@ -628,10 +632,10 @@ public interface WxPayService {
/**
* 服务商模式调用统一下单接口,并组装生成支付所需参数对象.
*
- * @param 请使用{@link com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result}里的内部类或字段
+ * @param 请使用{@link WxPayUnifiedOrderV3Result}里的内部类或字段
* @param tradeType the trade type
* @param request 统一下单请求参数
- * @return 返回 {@link com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result}里的内部类或字段
+ * @return 返回 {@link WxPayUnifiedOrderV3Result}里的内部类或字段
* @throws WxPayException the wx pay exception
*/
T createPartnerOrderV3(TradeTypeEnum tradeType, WxPayPartnerUnifiedOrderV3Request request) throws WxPayException;
@@ -1615,7 +1619,8 @@ public interface WxPayService {
/**
* 获取服务商直股份签约计划服务类
- * @return the partner pay score sign plan service
+ *
+ * @return the partner pay score sign plan service
*/
PartnerPayScoreSignPlanService getPartnerPayScoreSignPlanService();
}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java
index 7c2055cec30070b0f3fbc031288818af4ad7e6fd..1fa2f8dc80e5d53f91c38e377d00c3b0ec9437f1 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java
@@ -14,7 +14,6 @@ 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;
import com.github.binarywang.wxpay.constant.WxPayConstants.SignType;
import com.github.binarywang.wxpay.constant.WxPayConstants.TradeType;
import com.github.binarywang.wxpay.exception.WxPayException;
@@ -46,6 +45,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.zip.ZipException;
import static com.github.binarywang.wxpay.constant.WxPayConstants.QUERY_COMMENT_DATE_FORMAT;
@@ -122,7 +122,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
private final PartnerPayScoreService partnerPayScoreService = new PartnerPayScoreServiceImpl(this);
@Getter
- private final PartnerPayScoreSignPlanService partnerPayScoreSignPlanService=new PartnerPayScoreSignPlanServiceImpl(this);
+ private final PartnerPayScoreSignPlanService partnerPayScoreSignPlanService = new PartnerPayScoreSignPlanServiceImpl(this);
@Getter
private final MerchantTransferService merchantTransferService = new MerchantTransferServiceImpl(this);
@@ -130,7 +130,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
@Getter
private final BrandMerchantTransferService brandMerchantTransferService = new BrandMerchantTransferServiceImpl(this);
- protected Map configMap = new HashMap<>();
+ protected Map configMap = new ConcurrentHashMap<>();
@Override
public WxPayConfig getConfig() {
@@ -143,38 +143,37 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
@Override
public void setConfig(WxPayConfig config) {
- final String defaultMchId = config.getMchId();
- this.setMultiConfig(ImmutableMap.of(defaultMchId, config), defaultMchId);
+ final String defaultKey = this.getConfigKey(config.getMchId(), config.getAppId());
+ this.setMultiConfig(ImmutableMap.of(defaultKey, config), defaultKey);
}
@Override
- public void addConfig(String mchId, WxPayConfig wxPayConfig) {
+ public void addConfig(String mchId, String appId, WxPayConfig wxPayConfig) {
synchronized (this) {
if (this.configMap == null) {
this.setConfig(wxPayConfig);
} else {
- WxPayConfigHolder.set(mchId);
- this.configMap.put(mchId, wxPayConfig);
+ String configKey = this.getConfigKey(mchId, appId);
+ WxPayConfigHolder.set(configKey);
+ this.configMap.put(configKey, wxPayConfig);
}
}
}
@Override
- public void removeConfig(String mchId) {
+ public void removeConfig(String mchId, String appId) {
synchronized (this) {
- if (this.configMap.size() == 1) {
- this.configMap.remove(mchId);
- log.warn("已删除最后一个商户号配置:{},须立即使用setConfig或setMultiConfig添加配置", mchId);
+ String configKey = this.getConfigKey(mchId, appId);
+ this.configMap.remove(configKey);
+ if (this.configMap.isEmpty()) {
+ log.warn("已删除最后一个商户号配置:mchId[{}],appid[{}],须立即使用setConfig或setMultiConfig添加配置", mchId, appId);
return;
}
- if (WxPayConfigHolder.get().equals(mchId)) {
- this.configMap.remove(mchId);
- final String defaultMpId = this.configMap.keySet().iterator().next();
- WxPayConfigHolder.set(defaultMpId);
- log.warn("已删除默认商户号配置,商户号【{}】被设为默认配置", defaultMpId);
- return;
+ if (WxPayConfigHolder.get().equals(configKey)) {
+ final String nextConfigKey = this.configMap.keySet().iterator().next();
+ WxPayConfigHolder.set(nextConfigKey);
+ log.warn("已删除默认商户号配置,商户号【{}】被设为默认配置", nextConfigKey);
}
- this.configMap.remove(mchId);
}
}
@@ -184,28 +183,34 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
}
@Override
- public void setMultiConfig(Map wxPayConfigs, String defaultMchId) {
+ public void setMultiConfig(Map wxPayConfigs, String defaultConfigKey) {
this.configMap = Maps.newHashMap(wxPayConfigs);
- WxPayConfigHolder.set(defaultMchId);
+ WxPayConfigHolder.set(defaultConfigKey);
}
@Override
- public boolean switchover(String mchId) {
- if (this.configMap.containsKey(mchId)) {
- WxPayConfigHolder.set(mchId);
+ public boolean switchover(String mchId, String appId) {
+ String configKey = this.getConfigKey(mchId, appId);
+ if (this.configMap.containsKey(configKey)) {
+ WxPayConfigHolder.set(configKey);
return true;
}
- log.error("无法找到对应【{}】的商户号配置信息,请核实!", mchId);
+ log.error("无法找到对应mchId=【{}】,appId=【{}】的商户号配置信息,请核实!", mchId, appId);
return false;
}
@Override
- public WxPayService switchoverTo(String mchId) {
- if (this.configMap.containsKey(mchId)) {
- WxPayConfigHolder.set(mchId);
+ public WxPayService switchoverTo(String mchId, String appId) {
+ String configKey = this.getConfigKey(mchId, appId);
+ if (this.configMap.containsKey(configKey)) {
+ WxPayConfigHolder.set(configKey);
return this;
}
- throw new WxRuntimeException(String.format("无法找到对应【%s】的商户号配置信息,请核实!", mchId));
+ throw new WxRuntimeException(String.format("无法找到对应mchId=【%s】,appId=【%s】的商户号配置信息,请核实!", mchId, appId));
+ }
+
+ private String getConfigKey(String mchId, String appId) {
+ return mchId + "_" + appId;
}
@Override
@@ -302,7 +307,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
@Override
public WxPayRefundQueryV3Result refundPartnerQueryV3(WxPayRefundQueryV3Request request) throws WxPayException {
- String url = String.format("%s/v3/refund/domestic/refunds/%s?sub_mchid=%s", this.getPayBaseUrl(), request.getOutRefundNo(),request.getSubMchid());
+ String url = String.format("%s/v3/refund/domestic/refunds/%s?sub_mchid=%s", this.getPayBaseUrl(), request.getOutRefundNo(), request.getSubMchid());
String response = this.getV3(url);
return GSON.fromJson(response, WxPayRefundQueryV3Result.class);
}
@@ -324,7 +329,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
} else if (configMap.get(result.getMchId()).getSignType() != null) {
// 如果配置中signType有值,则使用它进行验签
signType = configMap.get(result.getMchId()).getSignType();
- this.switchover(result.getMchId());
+ this.switchover(result.getMchId(), result.getAppid());
}
}
@@ -347,7 +352,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
*/
private boolean verifyNotifySign(SignatureHeader header, String data) throws WxSignTestException {
String wxPaySign = header.getSignature();
- if(wxPaySign.startsWith("WECHATPAY/SIGNTEST/")){
+ if (wxPaySign.startsWith("WECHATPAY/SIGNTEST/")) {
throw new WxSignTestException("微信支付签名探测流量");
}
String beforeSign = String.format("%s\n%s\n%s\n",
@@ -421,7 +426,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
WxPayRefundNotifyResult result;
if (XmlConfig.fastMode) {
result = BaseWxPayResult.fromXML(xmlData, WxPayRefundNotifyResult.class);
- this.switchover(result.getMchId());
+ this.switchover(result.getMchId(), result.getAppid());
result.decryptReqInfo(this.getConfig().getMchKey());
} else {
result = WxPayRefundNotifyResult.fromXML(xmlData, this.getConfig().getMchKey());
@@ -458,7 +463,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
try {
log.debug("扫码支付回调通知请求参数:{}", xmlData);
WxScanPayNotifyResult result = BaseWxPayResult.fromXML(xmlData, WxScanPayNotifyResult.class);
- this.switchover(result.getMchId());
+ this.switchover(result.getMchId(), result.getAppid());
log.debug("扫码支付回调通知解析后的对象:{}", result);
result.checkResult(this, this.getConfig().getSignType(), false);
return result;
@@ -1306,7 +1311,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
@Override
public WxPayFaceAuthInfoResult getWxPayFaceAuthInfo(WxPayFaceAuthInfoRequest request) throws WxPayException {
if (StringUtils.isEmpty(request.getSignType())) {
- request.setSignType(WxPayConstants.SignType.MD5);
+ request.setSignType(SignType.MD5);
}
request.checkAndSign(this.getConfig());
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/TransferServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/TransferServiceImpl.java
index 23bf7b13eef703246c081f1baf461fcab22fe50c..f43c887c16746a5b03638ce7a68b1d16c5eda461 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/TransferServiceImpl.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/TransferServiceImpl.java
@@ -48,8 +48,7 @@ public class TransferServiceImpl implements TransferService {
if (request.getNeedQueryDetail()) {
url = String.format("%s/v3/transfer/batches/batch-id/%s?need_query_detail=true&offset=%s&limit=%s&detail_status=%s",
this.payService.getPayBaseUrl(), request.getBatchId(), request.getOffset(), request.getLimit(), request.getDetailStatus());
- }
- else {
+ } else {
url = String.format("%s/v3/transfer/batches/batch-id/%s?need_query_detail=false",
this.payService.getPayBaseUrl(), request.getBatchId());
}
@@ -70,8 +69,7 @@ public class TransferServiceImpl implements TransferService {
if (request.getNeedQueryDetail()) {
url = String.format("%s/v3/transfer/batches/out-batch-no/%s?need_query_detail=true&offset=%s&limit=%s&detail_status=%s",
this.payService.getPayBaseUrl(), request.getOutBatchNo(), request.getOffset(), request.getLimit(), request.getDetailStatus());
- }
- else {
+ } else {
url = String.format("%s/v3/transfer/batches/out-batch-no/%s?need_query_detail=false",
this.payService.getPayBaseUrl(), request.getOutBatchNo());
}
@@ -97,6 +95,31 @@ public class TransferServiceImpl implements TransferService {
return GSON.fromJson(result, TransferBillsResult.class);
}
+ @Override
+ public TransferBillsCancelResult transformBillsCancel(String outBillNo) throws WxPayException {
+ String url = String.format("%s/v3/fund-app/mch-transfer/transfer-bills/out-bill-no/%s/cancel",
+ this.payService.getPayBaseUrl(), outBillNo);
+ String result = this.payService.postV3(url, "");
+
+ return GSON.fromJson(result, TransferBillsCancelResult.class);
+ }
+
+ @Override
+ public TransferBillsGetResult getBillsByOutBillNo(String outBillNo) throws WxPayException {
+ String url = String.format("%s/v3/fund-app/mch-transfer/transfer-bills/out-bill-no/%s",
+ this.payService.getPayBaseUrl(), outBillNo);
+ String result = this.payService.getV3(url);
+ return GSON.fromJson(result, TransferBillsGetResult.class);
+ }
+
+ @Override
+ public TransferBillsGetResult getBillsByTransferBillNo(String transferBillNo) throws WxPayException {
+ String url = String.format("%s/v3/fund-app/mch-transfer/transfer-bills/transfer-bill-no/%s",
+ this.payService.getPayBaseUrl(), transferBillNo);
+ String result = this.payService.getV3(url);
+ return GSON.fromJson(result, TransferBillsGetResult.class);
+ }
+
@Override
public TransferBillsNotifyResult parseTransferBillsNotifyResult(String notifyData, SignatureHeader header) throws WxPayException {
return this.payService.baseParseOrderNotifyV3Result(notifyData, header, TransferBillsNotifyResult.class, TransferBillsNotifyResult.DecryptNotifyResult.class);
diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/TransferServiceImplTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/TransferServiceImplTest.java
index cd607dff03caec89658aacddf804354b08cb5014..10c2a5da66c6cd8c07bb7ef24670ce6aec4811ee 100644
--- a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/TransferServiceImplTest.java
+++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/TransferServiceImplTest.java
@@ -87,4 +87,19 @@ public class TransferServiceImplTest {
.userName("测试用户").build();
log.info("发起商家转账:{}", this.payService.getTransferService().transferBills(transferBillsRequest));
}
+
+ @Test
+ public void testTransformBillsCancel() throws WxPayException {
+ log.info("撤销商家转账:{}", this.payService.getTransferService().transformBillsCancel("123456"));
+ }
+
+ @Test
+ public void testGetBillsByOutBillNo() throws WxPayException {
+ log.info("商户单号查询转账单:{}", this.payService.getTransferService().getBillsByOutBillNo("123456"));
+ }
+
+ @Test
+ public void testGetBillsByTransferBillNo() throws WxPayException {
+ log.info("微信单号查询转账单:{}", this.payService.getTransferService().getBillsByTransferBillNo("123456"));
+ }
}