diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayPartnerOrderCloseV3Request.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayPartnerOrderCloseV3Request.java new file mode 100644 index 000000000..7a62629fb --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayPartnerOrderCloseV3Request.java @@ -0,0 +1,61 @@ +package com.github.binarywang.wxpay.bean.request; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * 服务商关闭订单请求对象类 + * 文档见:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_1_3.shtml + * + * @author Guo Shuai + * @version 1.0 + * @date 2023/3/2 + */ +@Data +@NoArgsConstructor +@Accessors(chain = true) +public class WxPayPartnerOrderCloseV3Request implements Serializable { + private static final long serialVersionUID = 1L; + /** + *
+ * 字段名:服务商商户号 + * 变量名:sp_mchid + * 是否必填:是 + * 类型:string[1,32] + * 描述: + * 服务商商户号,由微信支付生成并下发。 + * 示例值:1230000109 + *+ */ + @SerializedName(value = "sp_mchid") + private String spMchId; + /** + *
+ * 字段名:特约商户商户号 + * 变量名:sp_mchid + * 是否必填:是 + * 类型:string[1,32] + * 描述: + * 特约商户商户号,由微信支付生成并下发。 + * 示例值:1230000109 + *+ */ + @SerializedName(value = "sub_mchid") + private String subMchId; + /** + *
+ * 字段名:商户订单号 + * 变量名:out_trade_no + * 是否必填:是 + * 类型:string[6,32] + * 描述: + * 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一 + * 示例值:1217752501201407033233368018 + *+ */ + private transient String outTradeNo; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayPartnerRefundV3Request.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayPartnerRefundV3Request.java index 89d0e11f5..299cf2a94 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayPartnerRefundV3Request.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayPartnerRefundV3Request.java @@ -21,19 +21,6 @@ import java.util.List; @Accessors(chain = true) public class WxPayPartnerRefundV3Request extends WxPayRefundV3Request implements Serializable { private static final long serialVersionUID = -1L; - /** - *
- * 字段名:子商户的商户号 - * 变量名:sub_mchid - * 是否必填:是 - * 类型:string[1, 32] - * 描述: - * 子商户商户号,由微信支付生成并下发。 - * 示例值:1230000109 - *- */ - @SerializedName(value = "sub_mchid") - private String subMchId; /** *
* 字段名:退款资金来源
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRefundV3Request.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRefundV3Request.java
index 31a41d922..e9f1f3b14 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRefundV3Request.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRefundV3Request.java
@@ -238,6 +238,17 @@ public class WxPayRefundV3Request implements Serializable {
private Integer refundQuantity;
}
+ /**
+ *
+ * 字段名:子商户的商户号
+ * 变量名:sub_mchid
+ * 是否必填:是
+ * 类型:string[1, 32]
+ * 描述:
+ * 子商户商户号,由微信支付生成并下发。
+ * 示例值:1230000109
+ *
+ */
@SerializedName(value = "sub_mchid")
private String subMchid;
}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayUnifiedOrderV3Result.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayUnifiedOrderV3Result.java
index 309fb8e75..f37d26873 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayUnifiedOrderV3Result.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayUnifiedOrderV3Result.java
@@ -1,5 +1,6 @@
package com.github.binarywang.wxpay.bean.result;
+import com.github.binarywang.wxpay.bean.result.enums.PartnerTradeTypeEnum;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.v3.util.SignUtils;
import com.google.gson.annotations.SerializedName;
@@ -132,4 +133,32 @@ public class WxPayUnifiedOrderV3Result implements Serializable {
throw new WxRuntimeException("不支持的支付类型");
}
}
+
+ public T getPartnerPayInfo(PartnerTradeTypeEnum tradeType, String appId, String mchId, PrivateKey privateKey) {
+ String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
+ String nonceStr = SignUtils.genRandomStr();
+ switch (tradeType) {
+ case JSAPI:
+ JsapiResult jsapiResult = new JsapiResult();
+ jsapiResult.setAppId(appId).setTimeStamp(timestamp)
+ .setPackageValue("prepay_id=" + this.prepayId).setNonceStr(nonceStr)
+ //签名类型,默认为RSA,仅支持RSA。
+ .setSignType("RSA").setPaySign(SignUtils.sign(jsapiResult.getSignStr(), privateKey));
+ return (T) jsapiResult;
+ case H5:
+ return (T) this.h5Url;
+ case APP:
+ AppResult appResult = new AppResult();
+ appResult.setAppid(appId).setPrepayId(this.prepayId).setPartnerId(mchId)
+ .setNoncestr(nonceStr).setTimestamp(timestamp)
+ //暂填写固定值Sign=WXPay
+ .setPackageValue("Sign=WXPay")
+ .setSign(SignUtils.sign(appResult.getSignStr(), privateKey));
+ return (T) appResult;
+ case NATIVE:
+ return (T) this.codeUrl;
+ default:
+ throw new WxRuntimeException("不支持的支付类型");
+ }
+ }
}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/enums/PartnerTradeTypeEnum.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/enums/PartnerTradeTypeEnum.java
new file mode 100644
index 000000000..7704bf7d2
--- /dev/null
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/enums/PartnerTradeTypeEnum.java
@@ -0,0 +1,40 @@
+package com.github.binarywang.wxpay.bean.result.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 支付方式
+ *
+ * @author thinsstar
+ */
+@Getter
+@AllArgsConstructor
+public enum PartnerTradeTypeEnum {
+ /**
+ * APP
+ */
+ APP("/v3/pay/partner/transactions/app", "/v3/combine-transactions/app"),
+ /**
+ * JSAPI 或 小程序
+ */
+ JSAPI("/v3/pay/partner/transactions/jsapi", "/v3/combine-transactions/jsapi"),
+ /**
+ * NATIVE
+ */
+ NATIVE("/v3/pay/partner/transactions/native", "/v3/combine-transactions/native"),
+ /**
+ * H5
+ */
+ H5("/v3/pay/partner/transactions/h5", "/v3/combine-transactions/h5");
+
+ /**
+ * 单独下单url
+ */
+ private final String partnerUrl;
+
+ /**
+ * 合并下单url
+ */
+ private final String combineUrl;
+}
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 fd889cf60..0ac0c43cc 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
@@ -5,6 +5,7 @@ import com.github.binarywang.wxpay.bean.coupon.*;
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.PartnerTradeTypeEnum;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.constant.WxPayConstants;
@@ -477,6 +478,23 @@ public interface WxPayService {
*/
void closeOrderV3(String outTradeNo) throws WxPayException;
+ /**
+ *
+ * 服务商关闭订单
+ * 应用场景
+ * 以下情况需要调用关单接口:
+ * 1、商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;
+ * 2、系统下单后,用户支付超时,系统退出不再受理,避免用户继续,请调用关单接口。
+ * 注意:关单没有时间限制,建议在订单生成后间隔几分钟(最短5分钟)再调用关单接口,避免出现订单状态同步不及时导致关单失败。
+ * 接口地址:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_3.shtml
+ *
+ *
+ * @param outTradeNo 商户系统内部的订单号
+ * @return the wx pay order close result
+ * @throws WxPayException the wx pay exception
+ */
+ void closePartnerOrderV3(String outTradeNo) throws WxPayException;
+
/**
*
* 关闭订单
@@ -494,6 +512,23 @@ public interface WxPayService {
*/
void closeOrderV3(WxPayOrderCloseV3Request request) throws WxPayException;
+ /**
+ *
+ * 服务商关闭订单
+ * 应用场景
+ * 以下情况需要调用关单接口:
+ * 1、商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;
+ * 2、系统下单后,用户支付超时,系统退出不再受理,避免用户继续,请调用关单接口。
+ * 注意:关单没有时间限制,建议在订单生成后间隔几分钟(最短5分钟)再调用关单接口,避免出现订单状态同步不及时导致关单失败。
+ * 接口地址:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_3.shtml
+ *
+ *
+ * @param request 关闭订单请求对象
+ * @return the wx pay order close result
+ * @throws WxPayException the wx pay exception
+ */
+ void closePartnerOrderV3(WxPayPartnerOrderCloseV3Request request) throws WxPayException;
+
/**
*
* 合单关闭订单API
@@ -559,7 +594,7 @@ public interface WxPayService {
* @return 返回 {@link com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result}里的内部类或字段
* @throws WxPayException the wx pay exception
*/
- T createPartnerOrderV3(TradeTypeEnum tradeType, WxPayPartnerUnifiedOrderV3Request request) throws WxPayException;
+ T createPartnerOrderV3(PartnerTradeTypeEnum tradeType, WxPayPartnerUnifiedOrderV3Request request) throws WxPayException;
/**
* 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识"
@@ -569,7 +604,7 @@ public interface WxPayService {
* @return the wx pay unified order result
* @throws WxPayException the wx pay exception
*/
- WxPayUnifiedOrderV3Result unifiedPartnerOrderV3(TradeTypeEnum tradeType, WxPayPartnerUnifiedOrderV3Request request) throws WxPayException;
+ WxPayUnifiedOrderV3Result unifiedPartnerOrderV3(PartnerTradeTypeEnum tradeType, WxPayPartnerUnifiedOrderV3Request request) throws WxPayException;
/**
* 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识"
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 a749f51fd..4cc2fc3c1 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
@@ -10,6 +10,7 @@ import com.github.binarywang.wxpay.bean.order.WxPayMwebOrderResult;
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.PartnerTradeTypeEnum;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.config.WxPayConfigHolder;
@@ -538,6 +539,16 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
this.closeOrderV3(request);
}
+ @Override
+ public void closePartnerOrderV3(String outTradeNo) throws WxPayException {
+ if (StringUtils.isBlank(outTradeNo)) {
+ throw new WxPayException("out_trade_no不能为空");
+ }
+ WxPayPartnerOrderCloseV3Request request = new WxPayPartnerOrderCloseV3Request();
+ request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
+ this.closePartnerOrderV3(request);
+ }
+
@Override
public void closeOrderV3(WxPayOrderCloseV3Request request) throws WxPayException {
if (StringUtils.isBlank(request.getMchid())) {
@@ -547,6 +558,18 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
this.postV3(url, GSON.toJson(request));
}
+ @Override
+ public void closePartnerOrderV3(WxPayPartnerOrderCloseV3Request request) throws WxPayException {
+ if (StringUtils.isBlank(request.getSpMchId())) {
+ request.setSpMchId(this.getConfig().getMchId());
+ }
+ if (StringUtils.isBlank(request.getSubMchId())) {
+ request.setSubMchId(this.getConfig().getSubMchId());
+ }
+ String url = String.format("%s/v3/pay/partner/transactions/out-trade-no/%s/close", this.getPayBaseUrl(), request.getOutTradeNo());
+ this.postV3(url, GSON.toJson(request));
+ }
+
@Override
public void closeCombine(CombineCloseRequest request) throws WxPayException {
String url = String.format("%s/v3/combine-transactions/out-trade-no/%s/close", this.getPayBaseUrl(), request.getCombineOutTradeNo());
@@ -664,34 +687,19 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
}
@Override
- public T createPartnerOrderV3(TradeTypeEnum tradeType, WxPayPartnerUnifiedOrderV3Request request) throws WxPayException {
+ public T createPartnerOrderV3(PartnerTradeTypeEnum tradeType, WxPayPartnerUnifiedOrderV3Request request) throws WxPayException {
WxPayUnifiedOrderV3Result result = this.unifiedPartnerOrderV3(tradeType, request);
//获取应用ID
String appId = StringUtils.isBlank(request.getSubAppid()) ? request.getSpAppid() : request.getSubAppid();
- return result.getPayInfo(tradeType, appId, request.getSubMchId(), this.getConfig().getPrivateKey());
+ return result.getPartnerPayInfo(tradeType, appId, request.getSubMchId(), this.getConfig().getPrivateKey());
}
@Override
- public WxPayUnifiedOrderV3Result unifiedPartnerOrderV3(TradeTypeEnum tradeType, WxPayPartnerUnifiedOrderV3Request request) throws WxPayException {
- if (StringUtils.isBlank(request.getSpAppid())) {
- request.setSpAppid(this.getConfig().getAppId());
- }
- if (StringUtils.isBlank(request.getSpMchId())) {
- request.setSpMchId(this.getConfig().getMchId());
- }
- if (StringUtils.isBlank(request.getNotifyUrl())) {
- request.setNotifyUrl(this.getConfig().getNotifyUrl());
- }
- if (StringUtils.isBlank(request.getSubAppid())) {
- request.setSubAppid(this.getConfig().getSubAppId());
- }
- if (StringUtils.isBlank(request.getSubMchId())) {
- request.setSubMchId(this.getConfig().getSubMchId());
- }
-
- String url = this.getPayBaseUrl() + tradeType.getPartnerUrl();
- String response = this.postV3(url, GSON.toJson(request));
- return GSON.fromJson(response, WxPayUnifiedOrderV3Result.class);
+ public WxPayUnifiedOrderV3Result unifiedPartnerOrderV3(PartnerTradeTypeEnum tradeType, WxPayPartnerUnifiedOrderV3Request request) throws WxPayException {
+ WxPayUnifiedOrderV3Result result = this.unifiedPartnerOrderV3(tradeType, request);
+ //获取应用ID
+ String appId = StringUtils.isBlank(request.getSubAppid()) ? request.getSpAppid() : request.getSubAppid();
+ return result.getPartnerPayInfo(tradeType, appId, request.getSubMchId(), this.getConfig().getPrivateKey());
}
@Override