Skip to content

🎨 【微信支付】v3请求统一加上Wechatpay-Serial请求头 #3553

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Apr 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion solon-plugins/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<description>WxJava 各个模块的 Solon Plugin</description>

<properties>
<solon.version>3.0.1</solon.version>
<solon.version>3.2.0</solon.version>
</properties>

<modules>
Expand Down
92 changes: 92 additions & 0 deletions solon-plugins/wx-java-channel-solon-plugin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# wx-java-channel-solon-plugin

## 快速开始
1. 引入依赖
```xml
<dependencies>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java-channel-solon-plugin</artifactId>
<version>${version}</version>
</dependency>

<!-- 配置存储方式为jedis 则引入jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
</dependency>

<!-- 配置存储方式为redisson 则引入redisson -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>${redisson.version}</version>
</dependency>
</dependencies>
```
2. 添加配置(app.properties)
```properties
# 视频号配置(必填)
## 视频号小店的appId和secret
wx.channel.app-id=@appId
wx.channel.secret=@secret
# 视频号配置 选填
## 设置视频号小店消息服务器配置的token
wx.channel.token=@token
## 设置视频号小店消息服务器配置的EncodingAESKey
wx.channel.aes-key=
## 支持JSON或者XML格式,默认JSON
wx.channel.msg-data-format=JSON
## 是否使用稳定版 Access Token
wx.channel.use-stable-access-token=false


# ConfigStorage 配置(选填)
## 配置类型: memory(默认), jedis, redisson, redis_template
wx.channel.config-storage.type=memory
## 相关redis前缀配置: wx:channel(默认)
wx.channel.config-storage.key-prefix=wx:channel
wx.channel.config-storage.redis.host=127.0.0.1
wx.channel.config-storage.redis.port=6379
wx.channel.config-storage.redis.password=123456


# http 客户端配置(选填)
## # http客户端类型: http_client(默认)
wx.channel.config-storage.http-client-type=http_client
wx.channel.config-storage.http-proxy-host=
wx.channel.config-storage.http-proxy-port=
wx.channel.config-storage.http-proxy-username=
wx.channel.config-storage.http-proxy-password=
## 最大重试次数,默认:5 次,如果小于 0,则为 0
wx.channel.config-storage.max-retry-times=5
## 重试时间间隔步进,默认:1000 毫秒,如果小于 0,则为 1000
wx.channel.config-storage.retry-sleep-millis=1000
```
3. 自动注入的类型
- `WxChannelService`
- `WxChannelConfig`
4. 使用样例

```java
import me.chanjar.weixin.channel.api.WxChannelService;
import me.chanjar.weixin.channel.bean.shop.ShopInfoResponse;
import me.chanjar.weixin.channel.util.JsonUtils;
import me.chanjar.weixin.common.error.WxErrorException;
import org.noear.solon.annotation.Inject;

@Component
public class DemoService {
@Inject
private WxChannelService wxChannelService;

public String getShopInfo() throws WxErrorException {
// 获取店铺基本信息
ShopInfoResponse response = wxChannelService.getBasicService().getShopInfo();
// 此处为演示,如果要返回response的结果,建议自己封装一个VO,避免直接返回response
return JsonUtils.encode(response);
}
}
```

Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ public class WxCpTpXmlMessage implements Serializable {
* The Agent id.
*/
@XStreamAlias("AgentID")
protected String agentID;
protected Integer agentID;

/**
* The Pic url.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public static class NotifyNode implements Serializable {
/**
* 抄送人userid
*/
@XStreamAlias("ItemUserid")
@XStreamAlias("ItemUserId")
@XStreamConverter(value = XStreamCDataConverter.class)
private String itemUserId;

Expand Down Expand Up @@ -190,7 +190,7 @@ public static class Item implements Serializable {
/**
* 分支审批人userid
*/
@XStreamAlias("ItemUserid")
@XStreamAlias("ItemUserId")
@XStreamConverter(value = XStreamCDataConverter.class)
private String itemUserId;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ public static class File implements Serializable {
private String sdkFileId;

@SerializedName("filesize")
private Integer fileSize;
private Long fileSize;

/**
* From json file.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ public void enterAppTest() {
assertEquals(wxXmlMessage.getCreateTime(), Long.valueOf(1408091189));
assertEquals(wxXmlMessage.getEvent(), "enter_agent");
assertEquals(wxXmlMessage.getEventKey(), "");
assertEquals(wxXmlMessage.getAgentID(), Integer.valueOf(1));
assertEquals(wxXmlMessage.getAgentID(), 1);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,11 @@ public class WxPayConfig {
*/
private Verifier verifier;

/**
* 是否将全部v3接口的请求都添加Wechatpay-Serial请求头,默认不添加
*/
private boolean strictlyNeedWechatPaySerial = false;

/**
* 返回所设置的微信支付接口请求地址域名.
*
Expand Down Expand Up @@ -295,13 +300,13 @@ public CloseableHttpClient initApiV3HttpClient() throws WxPayException {
this.certSerialNo = certificate.getSerialNumber().toString(16).toUpperCase();
}
try {
if (merchantPrivateKey == null) {
if (merchantPrivateKey == null && StringUtils.isNotBlank(this.getPrivateKeyPath())) {
try (InputStream keyInputStream = this.loadConfigInputStream(this.getPrivateKeyString(), this.getPrivateKeyPath(),
this.privateKeyContent, "privateKeyPath")) {
merchantPrivateKey = PemUtils.loadPrivateKey(keyInputStream);
}
}
if (certificate == null && StringUtils.isBlank(this.getCertSerialNo())) {
if (certificate == null && StringUtils.isBlank(this.getCertSerialNo()) && StringUtils.isNotBlank(this.getPrivateCertPath())) {
try (InputStream certInputStream = this.loadConfigInputStream(this.getPrivateCertString(), this.getPrivateCertPath(),
this.privateCertContent, "privateCertPath")) {
certificate = PemUtils.loadCertificate(certInputStream);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ public WxPayRefundResult refundV2(WxPayRefundRequest request) throws WxPayExcept
@Override
public WxPayRefundV3Result refundV3(WxPayRefundV3Request request) throws WxPayException {
String url = String.format("%s/v3/refund/domestic/refunds", this.getPayBaseUrl());
String response = this.postV3(url, GSON.toJson(request));
String response = this.postV3WithWechatpaySerial(url, GSON.toJson(request));
return GSON.fromJson(response, WxPayRefundV3Result.class);
}

Expand Down Expand Up @@ -294,21 +294,21 @@ public WxPayRefundQueryResult refundQueryV2(WxPayRefundQueryRequest request) thr
@Override
public WxPayRefundQueryV3Result refundQueryV3(String outRefundNo) throws WxPayException {
String url = String.format("%s/v3/refund/domestic/refunds/%s", this.getPayBaseUrl(), outRefundNo);
String response = this.getV3(url);
String response = this.getV3WithWechatPaySerial(url);
return GSON.fromJson(response, WxPayRefundQueryV3Result.class);
}

@Override
public WxPayRefundQueryV3Result refundQueryV3(WxPayRefundQueryV3Request request) throws WxPayException {
String url = String.format("%s/v3/refund/domestic/refunds/%s", this.getPayBaseUrl(), request.getOutRefundNo());
String response = this.getV3(url);
String response = this.getV3WithWechatPaySerial(url);
return GSON.fromJson(response, WxPayRefundQueryV3Result.class);
}

@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 response = this.getV3(url);
String response = this.getV3WithWechatPaySerial(url);
return GSON.fromJson(response, WxPayRefundQueryV3Result.class);
}

Expand Down Expand Up @@ -523,7 +523,7 @@ public WxPayOrderQueryV3Result queryOrderV3(WxPayOrderQueryV3Request request) th
url = String.format("%s/v3/pay/transactions/id/%s", this.getPayBaseUrl(), request.getTransactionId());
}
String query = String.format("?mchid=%s", request.getMchid());
String response = this.getV3(url + query);
String response = this.getV3WithWechatPaySerial(url + query);
return GSON.fromJson(response, WxPayOrderQueryV3Result.class);
}

Expand All @@ -548,14 +548,14 @@ public WxPayPartnerOrderQueryV3Result queryPartnerOrderV3(WxPayPartnerOrderQuery
url = String.format("%s/v3/pay/partner/transactions/id/%s", this.getPayBaseUrl(), request.getTransactionId());
}
String query = String.format("?sp_mchid=%s&sub_mchid=%s", request.getSpMchId(), request.getSubMchId());
String response = this.getV3(url + query);
String response = this.getV3WithWechatPaySerial(url + query);
return GSON.fromJson(response, WxPayPartnerOrderQueryV3Result.class);
}

@Override
public CombineQueryResult queryCombine(String combineOutTradeNo) throws WxPayException {
String url = String.format("%s/v3/combine-transactions/out-trade-no/%s", this.getPayBaseUrl(), combineOutTradeNo);
String response = this.getV3(url);
String response = this.getV3WithWechatPaySerial(url);
return GSON.fromJson(response, CombineQueryResult.class);
}

Expand Down Expand Up @@ -609,7 +609,7 @@ public void closeOrderV3(WxPayOrderCloseV3Request request) throws WxPayException
request.setMchid(this.getConfig().getMchId());
}
String url = String.format("%s/v3/pay/transactions/out-trade-no/%s/close", this.getPayBaseUrl(), request.getOutTradeNo());
this.postV3(url, GSON.toJson(request));
this.postV3WithWechatpaySerial(url, GSON.toJson(request));
}

@Override
Expand All @@ -621,13 +621,13 @@ public void closePartnerOrderV3(WxPayPartnerOrderCloseV3Request request) throws
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));
this.postV3WithWechatpaySerial(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());
this.postV3(url, GSON.toJson(request));
this.postV3WithWechatpaySerial(url, GSON.toJson(request));
}

@Override
Expand Down Expand Up @@ -771,7 +771,7 @@ public WxPayUnifiedOrderV3Result unifiedPartnerOrderV3(TradeTypeEnum tradeType,
}

String url = this.getPayBaseUrl() + tradeType.getBasePartnerUrl();
String response = this.postV3(url, GSON.toJson(request));
String response = this.postV3WithWechatpaySerial(url, GSON.toJson(request));
return GSON.fromJson(response, WxPayUnifiedOrderV3Result.class);
}

Expand All @@ -788,7 +788,7 @@ public WxPayUnifiedOrderV3Result unifiedOrderV3(TradeTypeEnum tradeType, WxPayUn
}

String url = this.getPayBaseUrl() + tradeType.getPartnerUrl();
String response = this.postV3(url, GSON.toJson(request));
String response = this.postV3WithWechatpaySerial(url, GSON.toJson(request));
return GSON.fromJson(response, WxPayUnifiedOrderV3Result.class);
}

Expand All @@ -801,7 +801,7 @@ public CombineTransactionsResult combine(TradeTypeEnum tradeType, CombineTransac
request.setCombineMchid(this.getConfig().getMchId());
}
String url = this.getPayBaseUrl() + tradeType.getCombineUrl();
String response = this.postV3(url, GSON.toJson(request));
String response = this.postV3WithWechatpaySerial(url, GSON.toJson(request));
return GSON.fromJson(response, CombineTransactionsResult.class);
}

Expand Down Expand Up @@ -1114,7 +1114,7 @@ public WxPayApplyBillV3Result applyTradeBill(WxPayApplyTradeBillV3Request reques
} else {
url = String.format("%s/v3/bill/tradebill?bill_date=%s&bill_type=%s&tar_type=%s", this.getPayBaseUrl(), request.getBillDate(), request.getBillType(), request.getTarType());
}
String response = this.getV3(url);
String response = this.getV3WithWechatPaySerial(url);
return GSON.fromJson(response, WxPayApplyBillV3Result.class);
}

Expand All @@ -1126,7 +1126,7 @@ public WxPayApplyBillV3Result applyFundFlowBill(WxPayApplyFundFlowBillV3Request
} else {
url = String.format("%s/v3/bill/fundflowbill?bill_date=%s&account_type=%s&tar_type=%s", this.getPayBaseUrl(), request.getBillDate(), request.getAccountType(), request.getTarType());
}
String response = this.getV3(url);
String response = this.getV3WithWechatPaySerial(url);
return GSON.fromJson(response, WxPayApplyBillV3Result.class);
}

Expand Down Expand Up @@ -1155,7 +1155,7 @@ public WxPayCodepayResult codepay(WxPayCodepayRequest request) throws WxPayExcep
request.setMchid(this.getConfig().getMchId());
}
String url = String.format("%s/v3/pay/transactions/codepay", this.getPayBaseUrl());
String body = this.postV3(url, GSON.toJson(request));
String body = this.postV3WithWechatpaySerial(url, GSON.toJson(request));
return GSON.fromJson(body, WxPayCodepayResult.class);
}

Expand All @@ -1181,7 +1181,7 @@ public WxPayOrderReverseV3Result reverseOrderV3(WxPayOrderReverseV3Request reque
}
// 拼接参数请求路径并发送
String url = String.format("%s/v3/pay/transactions/out-trade-no/%s/reverse", this.getPayBaseUrl(), request.getOutTradeNo());
String response = this.postV3(url, GSON.toJson(request));
String response = this.postV3WithWechatpaySerial(url, GSON.toJson(request));
return GSON.fromJson(response, WxPayOrderReverseV3Result.class);
}

Expand Down
Loading