From 1bf4dfa2731b6e476212cd4037cadabeacd95430 Mon Sep 17 00:00:00 2001 From: altusea Date: Tue, 3 Jun 2025 20:00:15 +0800 Subject: [PATCH 01/31] fix unit test --- .../me/chanjar/weixin/common/util/http/HttpResponseProxy.java | 2 +- .../weixin/common/util/http/apache/ApacheHttpResponseProxy.java | 2 +- .../common/util/http/hc5/ApacheHttpClient5ResponseProxy.java | 2 +- .../weixin/common/util/http/jodd/JoddHttpResponseProxy.java | 2 +- .../weixin/common/util/http/okhttp/OkHttpResponseProxy.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpResponseProxy.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpResponseProxy.java index 6a014d19b6..4cdca78960 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpResponseProxy.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpResponseProxy.java @@ -40,7 +40,7 @@ static OkHttpResponseProxy from(okhttp3.Response response) { String getFileName() throws WxErrorException; - default String extractFileNameFromContentString(String content) throws WxErrorException { + static String extractFileNameFromContentString(String content) throws WxErrorException { if (content == null || content.isEmpty()) { throw new WxErrorException("无法获取到文件名,content为空"); } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpResponseProxy.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpResponseProxy.java index 432b2cd249..06439d3879 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpResponseProxy.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpResponseProxy.java @@ -20,6 +20,6 @@ public String getFileName() throws WxErrorException { throw new WxErrorException("无法获取到文件名,Content-disposition为空"); } - return extractFileNameFromContentString(contentDispositionHeader[0].getValue()); + return HttpResponseProxy.extractFileNameFromContentString(contentDispositionHeader[0].getValue()); } } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheHttpClient5ResponseProxy.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheHttpClient5ResponseProxy.java index ec6bd9368c..f5c057f1ea 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheHttpClient5ResponseProxy.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheHttpClient5ResponseProxy.java @@ -20,6 +20,6 @@ public String getFileName() throws WxErrorException { throw new WxErrorException("无法获取到文件名,Content-disposition为空"); } - return extractFileNameFromContentString(contentDispositionHeader[0].getValue()); + return HttpResponseProxy.extractFileNameFromContentString(contentDispositionHeader[0].getValue()); } } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpResponseProxy.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpResponseProxy.java index 7a9461b62f..1bda38a497 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpResponseProxy.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddHttpResponseProxy.java @@ -15,6 +15,6 @@ public JoddHttpResponseProxy(HttpResponse httpResponse) { @Override public String getFileName() throws WxErrorException { String content = response.header("Content-disposition"); - return extractFileNameFromContentString(content); + return HttpResponseProxy.extractFileNameFromContentString(content); } } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpResponseProxy.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpResponseProxy.java index e1a94d68e6..95c290735c 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpResponseProxy.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpResponseProxy.java @@ -15,6 +15,6 @@ public OkHttpResponseProxy(Response response) { @Override public String getFileName() throws WxErrorException { String content = this.response.header("Content-disposition"); - return extractFileNameFromContentString(content); + return HttpResponseProxy.extractFileNameFromContentString(content); } } From 0d18b6dfe2ca771cc4f0062d13c5af5943f64c37 Mon Sep 17 00:00:00 2001 From: altusea Date: Tue, 3 Jun 2025 20:08:02 +0800 Subject: [PATCH 02/31] rename WxCpServiceApacheHttpClient5Impl to WxCpServiceHttpClient5Impl --- .../configuration/services/AbstractWxCpConfiguration.java | 8 ++++---- .../wxjava/cp_multi/properties/WxCpMultiProperties.java | 4 ++++ .../chanjar/weixin/common/util/http/HttpClientType.java | 2 +- ...tpClient5Impl.java => WxCpServiceHttpClient5Impl.java} | 4 ++-- 4 files changed, 11 insertions(+), 7 deletions(-) rename weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/{WxCpServiceApacheHttpClient5Impl.java => WxCpServiceHttpClient5Impl.java} (95%) diff --git a/solon-plugins/wx-java-cp-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/cp_multi/configuration/services/AbstractWxCpConfiguration.java b/solon-plugins/wx-java-cp-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/cp_multi/configuration/services/AbstractWxCpConfiguration.java index 8710bba3ca..d88a8f42b0 100644 --- a/solon-plugins/wx-java-cp-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/cp_multi/configuration/services/AbstractWxCpConfiguration.java +++ b/solon-plugins/wx-java-cp-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/cp_multi/configuration/services/AbstractWxCpConfiguration.java @@ -7,10 +7,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.cp.api.WxCpService; -import me.chanjar.weixin.cp.api.impl.WxCpServiceApacheHttpClientImpl; -import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; -import me.chanjar.weixin.cp.api.impl.WxCpServiceJoddHttpImpl; -import me.chanjar.weixin.cp.api.impl.WxCpServiceOkHttpImpl; +import me.chanjar.weixin.cp.api.impl.*; import me.chanjar.weixin.cp.config.WxCpConfigStorage; import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl; import org.apache.commons.lang3.StringUtils; @@ -96,6 +93,9 @@ private WxCpService wxCpService(WxCpConfigStorage wxCpConfigStorage, WxCpMultiPr case HTTP_CLIENT: wxCpService = new WxCpServiceApacheHttpClientImpl(); break; + case HTTP_CLIENT_5: + wxCpService = new WxCpServiceHttpClient5Impl(); + break; default: wxCpService = new WxCpServiceImpl(); break; diff --git a/solon-plugins/wx-java-cp-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/cp_multi/properties/WxCpMultiProperties.java b/solon-plugins/wx-java-cp-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/cp_multi/properties/WxCpMultiProperties.java index 5544a92e00..c89ef8486f 100644 --- a/solon-plugins/wx-java-cp-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/cp_multi/properties/WxCpMultiProperties.java +++ b/solon-plugins/wx-java-cp-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/cp_multi/properties/WxCpMultiProperties.java @@ -117,6 +117,10 @@ public enum HttpClientType { * HttpClient */ HTTP_CLIENT, + /** + * HttpClient5 + */ + HTTP_CLIENT_5, /** * OkHttp */ diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpClientType.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpClientType.java index eaa84c6a47..3c21add2e8 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpClientType.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpClientType.java @@ -19,5 +19,5 @@ public enum HttpClientType { /** * apache httpclient5. */ - APACHE_HTTP_5 + HTTP_CLIENT_5 } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceApacheHttpClient5Impl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceHttpClient5Impl.java similarity index 95% rename from weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceApacheHttpClient5Impl.java rename to weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceHttpClient5Impl.java index 2ab7987d0c..17b2b6b3c8 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceApacheHttpClient5Impl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceHttpClient5Impl.java @@ -23,7 +23,7 @@ * * @author altusea */ -public class WxCpServiceApacheHttpClient5Impl extends BaseWxCpServiceImpl { +public class WxCpServiceHttpClient5Impl extends BaseWxCpServiceImpl { private CloseableHttpClient httpClient; private HttpHost httpProxy; @@ -40,7 +40,7 @@ public HttpHost getRequestHttpProxy() { @Override public HttpClientType getRequestType() { - return HttpClientType.APACHE_HTTP; + return HttpClientType.HTTP_CLIENT_5; } @Override From 56bf115ff863c96a02b8fc9443a7403a80d3e23d Mon Sep 17 00:00:00 2001 From: altusea Date: Tue, 3 Jun 2025 20:16:13 +0800 Subject: [PATCH 03/31] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20WxChannelServiceHttp?= =?UTF-8?q?Client5Impl=20=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AbstractWxChannelConfiguration.java | 4 + .../wxjava/channel/enums/HttpClientType.java | 4 + weixin-java-channel/pom.xml | 5 + .../impl/WxChannelServiceHttpClient5Impl.java | 112 ++++++++++++++++++ 4 files changed, 125 insertions(+) create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelServiceHttpClient5Impl.java diff --git a/solon-plugins/wx-java-channel-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/channel/configuration/services/AbstractWxChannelConfiguration.java b/solon-plugins/wx-java-channel-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/channel/configuration/services/AbstractWxChannelConfiguration.java index 8531d92658..0032ecd41e 100644 --- a/solon-plugins/wx-java-channel-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/channel/configuration/services/AbstractWxChannelConfiguration.java +++ b/solon-plugins/wx-java-channel-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/channel/configuration/services/AbstractWxChannelConfiguration.java @@ -8,6 +8,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.channel.api.WxChannelService; +import me.chanjar.weixin.channel.api.impl.WxChannelServiceHttpClient5Impl; import me.chanjar.weixin.channel.api.impl.WxChannelServiceHttpClientImpl; import me.chanjar.weixin.channel.api.impl.WxChannelServiceImpl; import me.chanjar.weixin.channel.config.WxChannelConfig; @@ -84,6 +85,9 @@ public WxChannelService wxChannelService(WxChannelConfig wxChannelConfig, WxChan case HTTP_CLIENT: wxChannelService = new WxChannelServiceHttpClientImpl(); break; + case HTTP_CLIENT_5: + wxChannelService = new WxChannelServiceHttpClient5Impl(); + break; default: wxChannelService = new WxChannelServiceImpl(); break; diff --git a/solon-plugins/wx-java-channel-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/channel/enums/HttpClientType.java b/solon-plugins/wx-java-channel-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/channel/enums/HttpClientType.java index 1899e9e9f6..2bf6da63ef 100644 --- a/solon-plugins/wx-java-channel-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/channel/enums/HttpClientType.java +++ b/solon-plugins/wx-java-channel-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/channel/enums/HttpClientType.java @@ -11,6 +11,10 @@ public enum HttpClientType { * HttpClient */ HTTP_CLIENT, + /** + * HttpClient5 + */ + HTTP_CLIENT_5 // WxChannelServiceOkHttpImpl 实现经测试无法正常完成业务固暂不支持OK_HTTP方式 // /** // * OkHttp. diff --git a/weixin-java-channel/pom.xml b/weixin-java-channel/pom.xml index ac1d8f4c83..a7cc2a4ddc 100644 --- a/weixin-java-channel/pom.xml +++ b/weixin-java-channel/pom.xml @@ -29,6 +29,11 @@ jodd-http provided + + org.apache.httpcomponents.client5 + httpclient5 + provided + com.fasterxml.jackson.core diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelServiceHttpClient5Impl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelServiceHttpClient5Impl.java new file mode 100644 index 0000000000..aa76a7dd7d --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelServiceHttpClient5Impl.java @@ -0,0 +1,112 @@ +package me.chanjar.weixin.channel.api.impl; + +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.channel.bean.token.StableTokenParam; +import me.chanjar.weixin.channel.config.WxChannelConfig; +import me.chanjar.weixin.channel.util.JsonUtils; +import me.chanjar.weixin.common.util.http.HttpClientType; +import me.chanjar.weixin.common.util.http.hc5.ApacheBasicResponseHandler; +import me.chanjar.weixin.common.util.http.hc5.ApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.hc5.DefaultApacheHttpClientBuilder; +import org.apache.commons.lang3.StringUtils; +import org.apache.hc.client5.http.classic.HttpClient; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.io.entity.StringEntity; + +import java.io.IOException; + +import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.GET_ACCESS_TOKEN_URL; +import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.GET_STABLE_ACCESS_TOKEN_URL; + +/** + * @author altusea + */ +@Slf4j +public class WxChannelServiceHttpClient5Impl extends BaseWxChannelServiceImpl { + + private CloseableHttpClient httpClient; + private HttpHost httpProxy; + + @Override + public void initHttp() { + WxChannelConfig config = this.getConfig(); + ApacheHttpClientBuilder apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get(); + + apacheHttpClientBuilder.httpProxyHost(config.getHttpProxyHost()) + .httpProxyPort(config.getHttpProxyPort()) + .httpProxyUsername(config.getHttpProxyUsername()) + .httpProxyPassword(config.getHttpProxyPassword().toCharArray()); + + if (config.getHttpProxyHost() != null && config.getHttpProxyPort() > 0) { + this.httpProxy = new HttpHost(config.getHttpProxyHost(), config.getHttpProxyPort()); + } + + this.httpClient = apacheHttpClientBuilder.build(); + } + + @Override + public CloseableHttpClient getRequestHttpClient() { + return httpClient; + } + + @Override + public HttpHost getRequestHttpProxy() { + return httpProxy; + } + + @Override + public HttpClientType getRequestType() { + return HttpClientType.APACHE_HTTP; + } + + @Override + protected String doGetAccessTokenRequest() throws IOException { + WxChannelConfig config = this.getConfig(); + String url = StringUtils.isNotEmpty(config.getAccessTokenUrl()) ? config.getAccessTokenUrl() : + StringUtils.isNotEmpty(config.getApiHostUrl()) ? + GET_ACCESS_TOKEN_URL.replace("https://api.weixin.qq.com", config.getApiHostUrl()) : GET_ACCESS_TOKEN_URL; + + url = String.format(url, config.getAppid(), config.getSecret()); + + HttpGet httpGet = new HttpGet(url); + if (this.getRequestHttpProxy() != null) { + RequestConfig requestConfig = RequestConfig.custom().setProxy(this.getRequestHttpProxy()).build(); + httpGet.setConfig(requestConfig); + } + return getRequestHttpClient().execute(httpGet, ApacheBasicResponseHandler.INSTANCE); + } + + /** + * 获取稳定版接口调用凭据 + * + * @param forceRefresh false 为普通模式, true为强制刷新模式 + * @return 返回json的字符串 + * @throws IOException the io exception + */ + @Override + protected String doGetStableAccessTokenRequest(boolean forceRefresh) throws IOException { + WxChannelConfig config = this.getConfig(); + String url = GET_STABLE_ACCESS_TOKEN_URL; + + HttpPost httpPost = new HttpPost(url); + if (this.getRequestHttpProxy() != null) { + RequestConfig requestConfig = RequestConfig.custom().setProxy(this.getRequestHttpProxy()).build(); + httpPost.setConfig(requestConfig); + } + StableTokenParam requestParam = new StableTokenParam(); + requestParam.setAppId(config.getAppid()); + requestParam.setSecret(config.getSecret()); + requestParam.setGrantType("client_credential"); + requestParam.setForceRefresh(forceRefresh); + String requestJson = JsonUtils.encode(requestParam); + assert requestJson != null; + + httpPost.setEntity(new StringEntity(requestJson, ContentType.APPLICATION_JSON)); + return getRequestHttpClient().execute(httpPost, ApacheBasicResponseHandler.INSTANCE); + } +} From ea9e1bab933bb6381e86740b1cab39b958f07451 Mon Sep 17 00:00:00 2001 From: altusea Date: Tue, 3 Jun 2025 20:24:38 +0800 Subject: [PATCH 04/31] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20WxMpServiceHttpClien?= =?UTF-8?q?t5Impl=20=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../services/AbstractWxMpConfiguration.java | 8 +- .../mp/properties/WxMpMultiProperties.java | 4 + .../impl/WxChannelServiceHttpClient5Impl.java | 2 +- weixin-java-mp/pom.xml | 5 + .../api/impl/WxMpServiceHttpClient5Impl.java | 94 +++++++++++++++++++ 5 files changed, 108 insertions(+), 5 deletions(-) create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceHttpClient5Impl.java diff --git a/spring-boot-starters/wx-java-mp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/configuration/services/AbstractWxMpConfiguration.java b/spring-boot-starters/wx-java-mp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/configuration/services/AbstractWxMpConfiguration.java index 4e55fb4580..ece0956171 100644 --- a/spring-boot-starters/wx-java-mp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/configuration/services/AbstractWxMpConfiguration.java +++ b/spring-boot-starters/wx-java-mp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/configuration/services/AbstractWxMpConfiguration.java @@ -7,10 +7,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.mp.api.WxMpService; -import me.chanjar.weixin.mp.api.impl.WxMpServiceHttpClientImpl; -import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; -import me.chanjar.weixin.mp.api.impl.WxMpServiceJoddHttpImpl; -import me.chanjar.weixin.mp.api.impl.WxMpServiceOkHttpImpl; +import me.chanjar.weixin.mp.api.impl.*; import me.chanjar.weixin.mp.config.WxMpConfigStorage; import me.chanjar.weixin.mp.config.WxMpHostConfig; import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl; @@ -91,6 +88,9 @@ public WxMpService wxMpService(WxMpConfigStorage configStorage, WxMpMultiPropert case HTTP_CLIENT: wxMpService = new WxMpServiceHttpClientImpl(); break; + case HTTP_CLIENT_5: + wxMpService = new WxMpServiceHttpClient5Impl(); + break; default: wxMpService = new WxMpServiceImpl(); break; diff --git a/spring-boot-starters/wx-java-mp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/properties/WxMpMultiProperties.java b/spring-boot-starters/wx-java-mp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/properties/WxMpMultiProperties.java index c0d331382f..668af31a13 100644 --- a/spring-boot-starters/wx-java-mp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/properties/WxMpMultiProperties.java +++ b/spring-boot-starters/wx-java-mp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/properties/WxMpMultiProperties.java @@ -142,6 +142,10 @@ public enum HttpClientType { * HttpClient */ HTTP_CLIENT, + /** + * HttpClient5 + */ + HTTP_CLIENT_5, /** * OkHttp */ diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelServiceHttpClient5Impl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelServiceHttpClient5Impl.java index aa76a7dd7d..1764d772e9 100644 --- a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelServiceHttpClient5Impl.java +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelServiceHttpClient5Impl.java @@ -61,7 +61,7 @@ public HttpHost getRequestHttpProxy() { @Override public HttpClientType getRequestType() { - return HttpClientType.APACHE_HTTP; + return HttpClientType.HTTP_CLIENT_5; } @Override diff --git a/weixin-java-mp/pom.xml b/weixin-java-mp/pom.xml index 22ec60f381..69ac9b6c80 100644 --- a/weixin-java-mp/pom.xml +++ b/weixin-java-mp/pom.xml @@ -31,6 +31,11 @@ okhttp provided + + org.apache.httpcomponents.client5 + httpclient5 + provided + org.testng diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceHttpClient5Impl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceHttpClient5Impl.java new file mode 100644 index 0000000000..e1f9d35e67 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceHttpClient5Impl.java @@ -0,0 +1,94 @@ +package me.chanjar.weixin.mp.api.impl; + +import me.chanjar.weixin.common.util.http.HttpClientType; +import me.chanjar.weixin.common.util.http.hc5.ApacheBasicResponseHandler; +import me.chanjar.weixin.common.util.http.hc5.ApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.hc5.DefaultApacheHttpClientBuilder; +import me.chanjar.weixin.mp.bean.WxMpStableAccessTokenRequest; +import me.chanjar.weixin.mp.config.WxMpConfigStorage; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.io.entity.StringEntity; + +import java.io.IOException; + +import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Other.GET_ACCESS_TOKEN_URL; +import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Other.GET_STABLE_ACCESS_TOKEN_URL; + +/** + * apache http client方式实现. + * + * @author altusea + */ +public class WxMpServiceHttpClient5Impl extends BaseWxMpServiceImpl { + private CloseableHttpClient httpClient; + private HttpHost httpProxy; + + @Override + public CloseableHttpClient getRequestHttpClient() { + return httpClient; + } + + @Override + public HttpHost getRequestHttpProxy() { + return httpProxy; + } + + @Override + public HttpClientType getRequestType() { + return HttpClientType.HTTP_CLIENT_5; + } + + @Override + public void initHttp() { + WxMpConfigStorage configStorage = this.getWxMpConfigStorage(); + ApacheHttpClientBuilder apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get(); + + apacheHttpClientBuilder.httpProxyHost(configStorage.getHttpProxyHost()) + .httpProxyPort(configStorage.getHttpProxyPort()) + .httpProxyUsername(configStorage.getHttpProxyUsername()) + .httpProxyPassword(configStorage.getHttpProxyPassword().toCharArray()); + + if (configStorage.getHttpProxyHost() != null && configStorage.getHttpProxyPort() > 0) { + this.httpProxy = new HttpHost(configStorage.getHttpProxyHost(), configStorage.getHttpProxyPort()); + } + + this.httpClient = apacheHttpClientBuilder.build(); + } + + @Override + protected String doGetAccessTokenRequest() throws IOException { + String url = String.format(GET_ACCESS_TOKEN_URL.getUrl(getWxMpConfigStorage()), getWxMpConfigStorage().getAppId(), getWxMpConfigStorage().getSecret()); + + HttpGet httpGet = new HttpGet(url); + if (this.getRequestHttpProxy() != null) { + RequestConfig config = RequestConfig.custom().setProxy(this.getRequestHttpProxy()).build(); + httpGet.setConfig(config); + } + return getRequestHttpClient().execute(httpGet, ApacheBasicResponseHandler.INSTANCE); + } + + @Override + protected String doGetStableAccessTokenRequest(boolean forceRefresh) throws IOException { + String url = GET_STABLE_ACCESS_TOKEN_URL.getUrl(getWxMpConfigStorage()); + + HttpPost httpPost = new HttpPost(url); + if (this.getRequestHttpProxy() != null) { + RequestConfig config = RequestConfig.custom().setProxy(this.getRequestHttpProxy()).build(); + httpPost.setConfig(config); + } + WxMpStableAccessTokenRequest wxMaAccessTokenRequest = new WxMpStableAccessTokenRequest(); + wxMaAccessTokenRequest.setAppid(this.getWxMpConfigStorage().getAppId()); + wxMaAccessTokenRequest.setSecret(this.getWxMpConfigStorage().getSecret()); + wxMaAccessTokenRequest.setGrantType("client_credential"); + wxMaAccessTokenRequest.setForceRefresh(forceRefresh); + + httpPost.setEntity(new StringEntity(wxMaAccessTokenRequest.toJson(), ContentType.APPLICATION_JSON)); + return getRequestHttpClient().execute(httpPost, ApacheBasicResponseHandler.INSTANCE); + } + +} From 878cffb667509b767622df75baa6590ab33ee635 Mon Sep 17 00:00:00 2001 From: altusea Date: Tue, 3 Jun 2025 20:29:33 +0800 Subject: [PATCH 05/31] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20WxCpCgServiceHttpCli?= =?UTF-8?q?ent5Impl=20=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/WxCpCgServiceHttpClient5Impl.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpCgServiceHttpClient5Impl.java diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpCgServiceHttpClient5Impl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpCgServiceHttpClient5Impl.java new file mode 100644 index 0000000000..2b30614b3b --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpCgServiceHttpClient5Impl.java @@ -0,0 +1,47 @@ +package me.chanjar.weixin.cp.corpgroup.service.impl; + +import me.chanjar.weixin.common.util.http.HttpClientType; +import me.chanjar.weixin.common.util.http.hc5.ApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.hc5.DefaultApacheHttpClientBuilder; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.core5.http.HttpHost; + +/** + * @author altusea + */ +public class WxCpCgServiceHttpClient5Impl extends BaseWxCpCgServiceImpl { + private CloseableHttpClient httpClient; + private HttpHost httpProxy; + + @Override + public CloseableHttpClient getRequestHttpClient() { + return httpClient; + } + + @Override + public HttpHost getRequestHttpProxy() { + return httpProxy; + } + + @Override + public HttpClientType getRequestType() { + return HttpClientType.HTTP_CLIENT_5; + } + + @Override + public void initHttp() { + ApacheHttpClientBuilder apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get(); + + apacheHttpClientBuilder.httpProxyHost(this.configStorage.getHttpProxyHost()) + .httpProxyPort(this.configStorage.getHttpProxyPort()) + .httpProxyUsername(this.configStorage.getHttpProxyUsername()) + .httpProxyPassword(this.configStorage.getHttpProxyPassword().toCharArray()); + + if (this.configStorage.getHttpProxyHost() != null && this.configStorage.getHttpProxyPort() > 0) { + this.httpProxy = new HttpHost(this.configStorage.getHttpProxyHost(), this.configStorage.getHttpProxyPort()); + } + + this.httpClient = apacheHttpClientBuilder.build(); + } + +} From 52c64611f94ee2948c0de7a6f7a32e77409853c0 Mon Sep 17 00:00:00 2001 From: altusea Date: Tue, 3 Jun 2025 20:33:54 +0800 Subject: [PATCH 06/31] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20CommonUploadMultiReq?= =?UTF-8?q?uestExecutorHttpClient5Impl=20=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- weixin-java-open/pom.xml | 5 ++ .../CommonUploadMultiRequestExecutor.java | 2 + ...adMultiRequestExecutorHttpClient5Impl.java | 89 +++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutorHttpClient5Impl.java diff --git a/weixin-java-open/pom.xml b/weixin-java-open/pom.xml index 1588287bc5..11392222ca 100644 --- a/weixin-java-open/pom.xml +++ b/weixin-java-open/pom.xml @@ -48,6 +48,11 @@ okhttp provided + + org.apache.httpcomponents.client5 + httpclient5 + provided + org.testng diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutor.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutor.java index 4812dd325c..4b623860e1 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutor.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutor.java @@ -42,6 +42,8 @@ public static RequestExecutor create(RequestHttp return new CommonUploadMultiRequestExecutorJoddHttpImpl(requestHttp); case OK_HTTP: return new CommonUploadMultiRequestExecutorOkHttpImpl(requestHttp); + case HTTP_CLIENT_5: + return new CommonUploadMultiRequestExecutorHttpClient5Impl(requestHttp); default: throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType()); } diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutorHttpClient5Impl.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutorHttpClient5Impl.java new file mode 100644 index 0000000000..bba2d0ae3f --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutorHttpClient5Impl.java @@ -0,0 +1,89 @@ +package me.chanjar.weixin.open.executor; + +import lombok.Getter; +import me.chanjar.weixin.common.bean.CommonUploadData; +import me.chanjar.weixin.common.bean.CommonUploadParam; +import me.chanjar.weixin.common.enums.WxType; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler; +import me.chanjar.weixin.open.bean.CommonUploadMultiParam; +import org.apache.commons.lang3.StringUtils; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.entity.mime.HttpMultipartMode; +import org.apache.hc.client5.http.entity.mime.InputStreamBody; +import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder; +import org.apache.hc.client5.http.entity.mime.StringBody; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.HttpHost; +import org.springframework.util.CollectionUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.List; + +/** + * @author altusea + */ +public class CommonUploadMultiRequestExecutorHttpClient5Impl extends CommonUploadMultiRequestExecutor { + + public CommonUploadMultiRequestExecutorHttpClient5Impl(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public String execute(String uri, CommonUploadMultiParam param, WxType wxType) throws WxErrorException, IOException { + HttpPost httpPost = new HttpPost(uri); + if (requestHttp.getRequestHttpProxy() != null) { + RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build(); + httpPost.setConfig(config); + } + if (param != null) { + MultipartEntityBuilder entity = MultipartEntityBuilder.create(); + + List normalParams = param.getNormalParams(); + if (!CollectionUtils.isEmpty(normalParams)) { + for (CommonUploadMultiParam.NormalParam normalParam : normalParams) { + entity.addPart(normalParam.getName(), new StringBody(normalParam.getValue(), ContentType.create("multipart/form-data", StandardCharsets.UTF_8))); + } + } + + CommonUploadParam uploadParam = param.getUploadParam(); + if (uploadParam != null) { + CommonUploadData data = uploadParam.getData(); + InnerStreamBody part = new InnerStreamBody(data.getInputStream(), ContentType.DEFAULT_BINARY, data.getFileName(), data.getLength()); + entity.addPart(uploadParam.getName(), part) + .setMode(HttpMultipartMode.EXTENDED); + } + + httpPost.setEntity(entity.build()); + } + String responseContent = requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE); + if (StringUtils.isEmpty(responseContent)) { + throw new WxErrorException(String.format("上传失败,服务器响应空 url:%s param:%s", uri, param)); + } + WxError error = WxError.fromJson(responseContent, wxType); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return responseContent; + } + + /** + * 内部流 请求体 + */ + @Getter + public static class InnerStreamBody extends InputStreamBody { + + private final long contentLength; + + public InnerStreamBody(final InputStream in, final ContentType contentType, final String filename, long contentLength) { + super(in, contentType, filename); + this.contentLength = contentLength; + } + } +} From 76c70763bea40cc68128b79f2e7611618fc30eb5 Mon Sep 17 00:00:00 2001 From: altusea Date: Tue, 3 Jun 2025 20:34:48 +0800 Subject: [PATCH 07/31] =?UTF-8?q?=E5=B0=86=20okhttp=20=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E4=BB=8E=204.5.0=20=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=E5=88=B0=204.12.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c49ee14c83..cf84451605 100644 --- a/pom.xml +++ b/pom.xml @@ -154,7 +154,7 @@ com.squareup.okhttp3 okhttp - 4.5.0 + 4.12.0 provided From 8e63b26eb45750733805b0244875e3bd3c74612d Mon Sep 17 00:00:00 2001 From: altusea Date: Tue, 3 Jun 2025 20:43:57 +0800 Subject: [PATCH 08/31] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20WxCpTpServiceHttpCli?= =?UTF-8?q?ent5Impl=20=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/impl/WxChannelBasicServiceImpl.java | 8 +- .../impl/WxCpTpServiceHttpClient5Impl.java | 106 ++++++++++++++++++ 2 files changed, 110 insertions(+), 4 deletions(-) create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpServiceHttpClient5Impl.java diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelBasicServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelBasicServiceImpl.java index f408298666..6eb699da23 100644 --- a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelBasicServiceImpl.java +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelBasicServiceImpl.java @@ -56,7 +56,7 @@ public ChannelImageInfo uploadImg(int respType, String imgUrl) throws WxErrorExc public ChannelImageInfo uploadImg(int respType, File file, int height, int width) throws WxErrorException { String url = IMG_UPLOAD_URL + "?upload_type=0&resp_type=" + respType + "&height=" + height + "&width=" + width; RequestExecutor executor = ChannelFileUploadRequestExecutor.create(shopService); - String resJson = (String) shopService.execute(executor, url, file); + String resJson = shopService.execute(executor, url, file); UploadImageResponse response = ResponseUtils.decode(resJson, UploadImageResponse.class); return response.getImgInfo(); } @@ -64,19 +64,19 @@ public ChannelImageInfo uploadImg(int respType, File file, int height, int width @Override public QualificationFileResponse uploadQualificationFile(File file) throws WxErrorException { RequestExecutor executor = ChannelFileUploadRequestExecutor.create(shopService); - String resJson = (String) shopService.execute(executor, UPLOAD_QUALIFICATION_FILE, file); + String resJson = shopService.execute(executor, UPLOAD_QUALIFICATION_FILE, file); return ResponseUtils.decode(resJson, QualificationFileResponse.class); } @Override public ChannelImageResponse getImg(String mediaId) throws WxErrorException { String appId = shopService.getConfig().getAppid(); - ChannelImageResponse rs = null; + ChannelImageResponse rs; try { String url = GET_IMG_URL + "?media_id=" + mediaId; RequestExecutor executor = ChannelMediaDownloadRequestExecutor.create(shopService, Files.createTempDirectory("wxjava-channel-" + appId).toFile()); - rs = (ChannelImageResponse) shopService.execute(executor, url, null); + rs = shopService.execute(executor, url, null); } catch (IOException e) { throw new WxErrorException(WxError.builder().errorMsg(e.getMessage()).build(), e); } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpServiceHttpClient5Impl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpServiceHttpClient5Impl.java new file mode 100644 index 0000000000..9499d070fc --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpServiceHttpClient5Impl.java @@ -0,0 +1,106 @@ +package me.chanjar.weixin.cp.tp.service.impl; + +import com.google.gson.JsonObject; +import me.chanjar.weixin.common.enums.WxType; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.error.WxRuntimeException; +import me.chanjar.weixin.common.util.http.HttpClientType; +import me.chanjar.weixin.common.util.http.hc5.ApacheBasicResponseHandler; +import me.chanjar.weixin.common.util.http.hc5.ApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.hc5.DefaultApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.json.GsonParser; +import me.chanjar.weixin.cp.config.WxCpTpConfigStorage; +import me.chanjar.weixin.cp.constant.WxCpApiPathConsts; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.io.entity.StringEntity; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +/** + * The type Wx cp tp service apache http client. + * + * @author altusea + */ +public class WxCpTpServiceHttpClient5Impl extends BaseWxCpTpServiceImpl { + private CloseableHttpClient httpClient; + private HttpHost httpProxy; + + @Override + public CloseableHttpClient getRequestHttpClient() { + return httpClient; + } + + @Override + public HttpHost getRequestHttpProxy() { + return httpProxy; + } + + @Override + public HttpClientType getRequestType() { + return HttpClientType.HTTP_CLIENT_5; + } + + @Override + public String getSuiteAccessToken(boolean forceRefresh) throws WxErrorException { + if (!this.configStorage.isSuiteAccessTokenExpired() && !forceRefresh) { + return this.configStorage.getSuiteAccessToken(); + } + + synchronized (this.globalSuiteAccessTokenRefreshLock) { + try { + HttpPost httpPost = new HttpPost(configStorage.getApiUrl(WxCpApiPathConsts.Tp.GET_SUITE_TOKEN)); + if (this.httpProxy != null) { + RequestConfig config = RequestConfig.custom() + .setProxy(this.httpProxy).build(); + httpPost.setConfig(config); + } + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("suite_id", this.configStorage.getSuiteId()); + jsonObject.addProperty("suite_secret", this.configStorage.getSuiteSecret()); + jsonObject.addProperty("suite_ticket", this.getSuiteTicket()); + StringEntity entity = new StringEntity(jsonObject.toString(), StandardCharsets.UTF_8); + httpPost.setEntity(entity); + + String resultContent = getRequestHttpClient().execute(httpPost, ApacheBasicResponseHandler.INSTANCE); + WxError error = WxError.fromJson(resultContent, WxType.CP); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + jsonObject = GsonParser.parse(resultContent); + String suiteAccussToken = jsonObject.get("suite_access_token").getAsString(); + int expiresIn = jsonObject.get("expires_in").getAsInt(); + this.configStorage.updateSuiteAccessToken(suiteAccussToken, expiresIn); + } catch (IOException e) { + throw new WxRuntimeException(e); + } + } + return this.configStorage.getSuiteAccessToken(); + } + + @Override + public void initHttp() { + ApacheHttpClientBuilder apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get(); + + apacheHttpClientBuilder.httpProxyHost(this.configStorage.getHttpProxyHost()) + .httpProxyPort(this.configStorage.getHttpProxyPort()) + .httpProxyUsername(this.configStorage.getHttpProxyUsername()) + .httpProxyPassword(this.configStorage.getHttpProxyPassword().toCharArray()); + + if (this.configStorage.getHttpProxyHost() != null && this.configStorage.getHttpProxyPort() > 0) { + this.httpProxy = new HttpHost(this.configStorage.getHttpProxyHost(), this.configStorage.getHttpProxyPort()); + } + + this.httpClient = apacheHttpClientBuilder.build(); + } + + @Override + public WxCpTpConfigStorage getWxCpTpConfigStorage() { + return this.configStorage; + } + +} From d6d24739f123a676704a6c38ec9f23ebf2cc64bf Mon Sep 17 00:00:00 2001 From: altusea Date: Tue, 3 Jun 2025 20:49:58 +0800 Subject: [PATCH 09/31] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20QrCodeHttpClient5Req?= =?UTF-8?q?uestExecutor=20=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../QrCodeHttpClient5RequestExecutor.java | 67 +++++++++++++++++++ .../qrcode/QrCodeRequestExecutor.java | 6 +- 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeHttpClient5RequestExecutor.java diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeHttpClient5RequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeHttpClient5RequestExecutor.java new file mode 100644 index 0000000000..ccbc6af35a --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeHttpClient5RequestExecutor.java @@ -0,0 +1,67 @@ +package me.chanjar.weixin.mp.util.requestexecuter.qrcode; + +import me.chanjar.weixin.common.enums.WxType; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.fs.FileUtils; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.hc5.InputStreamResponseHandler; +import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler; +import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; +import org.apache.hc.client5.http.ClientProtocolException; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpException; +import org.apache.hc.core5.http.HttpHost; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URLEncoder; +import java.util.UUID; + +/** + * @author altusea + */ +public class QrCodeHttpClient5RequestExecutor extends QrCodeRequestExecutor { + public QrCodeHttpClient5RequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public File execute(String uri, WxMpQrCodeTicket ticket, WxType wxType) throws WxErrorException, IOException { + if (ticket != null) { + if (uri.indexOf('?') == -1) { + uri += '?'; + } + uri += uri.endsWith("?") + ? "ticket=" + URLEncoder.encode(ticket.getTicket(), "UTF-8") + : "&ticket=" + URLEncoder.encode(ticket.getTicket(), "UTF-8"); + } + + HttpGet httpGet = new HttpGet(uri); + if (requestHttp.getRequestHttpProxy() != null) { + RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build(); + httpGet.setConfig(config); + } + + try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpGet); + InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response)) { + Header[] contentTypeHeader = response.getHeaders("Content-Type"); + if (contentTypeHeader != null && contentTypeHeader.length > 0) { + // 出错 + if (ContentType.TEXT_PLAIN.getMimeType().equals(ContentType.parse(contentTypeHeader[0].getValue()).getMimeType())) { + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MP)); + } + } + return FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), "jpg"); + } catch (final HttpException httpException) { + throw new ClientProtocolException(httpException.getMessage(), httpException); + } + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeRequestExecutor.java index 860f84bbf7..ac2e5ffced 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeRequestExecutor.java @@ -37,11 +37,15 @@ public void execute(String uri, WxMpQrCodeTicket data, ResponseHandler han public static RequestExecutor create(RequestHttp requestHttp) throws WxErrorException { switch (requestHttp.getRequestType()) { case APACHE_HTTP: - return new QrCodeApacheHttpRequestExecutor((RequestHttp) requestHttp); + return new QrCodeApacheHttpRequestExecutor( + (RequestHttp) requestHttp); case JODD_HTTP: return new QrCodeJoddHttpRequestExecutor((RequestHttp) requestHttp); case OK_HTTP: return new QrCodeOkhttpRequestExecutor((RequestHttp) requestHttp); + case HTTP_CLIENT_5: + return new QrCodeHttpClient5RequestExecutor( + (RequestHttp) requestHttp); default: throw new WxErrorException("不支持的http框架"); } From 2dac5704a899fee90250a7a2b675efcedf7fbf20 Mon Sep 17 00:00:00 2001 From: altusea Date: Tue, 3 Jun 2025 21:01:00 +0800 Subject: [PATCH 10/31] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20WxQidianServiceHttpC?= =?UTF-8?q?lient5Impl=20=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- weixin-java-qidian/pom.xml | 5 + .../impl/WxQidianServiceHttpClient5Impl.java | 99 +++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 weixin-java-qidian/src/main/java/me/chanjar/weixin/qidian/api/impl/WxQidianServiceHttpClient5Impl.java diff --git a/weixin-java-qidian/pom.xml b/weixin-java-qidian/pom.xml index 08bdfa0af6..4dbc6b7c98 100644 --- a/weixin-java-qidian/pom.xml +++ b/weixin-java-qidian/pom.xml @@ -31,6 +31,11 @@ okhttp provided + + org.apache.httpcomponents.client5 + httpclient5 + provided + org.testng diff --git a/weixin-java-qidian/src/main/java/me/chanjar/weixin/qidian/api/impl/WxQidianServiceHttpClient5Impl.java b/weixin-java-qidian/src/main/java/me/chanjar/weixin/qidian/api/impl/WxQidianServiceHttpClient5Impl.java new file mode 100644 index 0000000000..cad20239a6 --- /dev/null +++ b/weixin-java-qidian/src/main/java/me/chanjar/weixin/qidian/api/impl/WxQidianServiceHttpClient5Impl.java @@ -0,0 +1,99 @@ +package me.chanjar.weixin.qidian.api.impl; + +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.error.WxRuntimeException; +import me.chanjar.weixin.common.util.http.HttpClientType; +import me.chanjar.weixin.common.util.http.hc5.ApacheBasicResponseHandler; +import me.chanjar.weixin.common.util.http.hc5.ApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.hc5.DefaultApacheHttpClientBuilder; +import me.chanjar.weixin.qidian.config.WxQidianConfigStorage; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.core5.http.HttpHost; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; + +import static me.chanjar.weixin.qidian.enums.WxQidianApiUrl.Other.GET_ACCESS_TOKEN_URL; + +/** + * apache http client5 方式实现. + * + * @author altusea + */ +public class WxQidianServiceHttpClient5Impl extends BaseWxQidianServiceImpl { + private CloseableHttpClient httpClient; + private HttpHost httpProxy; + + @Override + public CloseableHttpClient getRequestHttpClient() { + return httpClient; + } + + @Override + public HttpHost getRequestHttpProxy() { + return httpProxy; + } + + @Override + public HttpClientType getRequestType() { + return HttpClientType.HTTP_CLIENT_5; + } + + @Override + public void initHttp() { + WxQidianConfigStorage configStorage = this.getWxMpConfigStorage(); + ApacheHttpClientBuilder apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get(); + + apacheHttpClientBuilder.httpProxyHost(configStorage.getHttpProxyHost()) + .httpProxyPort(configStorage.getHttpProxyPort()).httpProxyUsername(configStorage.getHttpProxyUsername()) + .httpProxyPassword(configStorage.getHttpProxyPassword().toCharArray()); + + if (configStorage.getHttpProxyHost() != null && configStorage.getHttpProxyPort() > 0) { + this.httpProxy = new HttpHost(configStorage.getHttpProxyHost(), configStorage.getHttpProxyPort()); + } + + this.httpClient = apacheHttpClientBuilder.build(); + } + + @Override + public String getAccessToken(boolean forceRefresh) throws WxErrorException { + final WxQidianConfigStorage config = this.getWxMpConfigStorage(); + if (!config.isAccessTokenExpired() && !forceRefresh) { + return config.getAccessToken(); + } + + Lock lock = config.getAccessTokenLock(); + boolean locked = false; + try { + do { + locked = lock.tryLock(100, TimeUnit.MILLISECONDS); + if (!forceRefresh && !config.isAccessTokenExpired()) { + return config.getAccessToken(); + } + } while (!locked); + + String url = String.format(GET_ACCESS_TOKEN_URL.getUrl(config), config.getAppId(), config.getSecret()); + try { + HttpGet httpGet = new HttpGet(url); + if (this.getRequestHttpProxy() != null) { + RequestConfig requestConfig = RequestConfig.custom().setProxy(this.getRequestHttpProxy()).build(); + httpGet.setConfig(requestConfig); + } + String responseContent = getRequestHttpClient().execute(httpGet, ApacheBasicResponseHandler.INSTANCE); + return this.extractAccessToken(responseContent); + } catch (IOException e) { + throw new WxRuntimeException(e); + } + } catch (InterruptedException e) { + throw new WxRuntimeException(e); + } finally { + if (locked) { + lock.unlock(); + } + } + } + +} From ecd2f557b764e56a251ad3a76a49c16cf6e48f45 Mon Sep 17 00:00:00 2001 From: altusea Date: Tue, 3 Jun 2025 21:18:49 +0800 Subject: [PATCH 11/31] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20WxPayServiceHttpClie?= =?UTF-8?q?nt5Impl=20=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- weixin-java-pay/pom.xml | 5 + .../impl/WxPayServiceHttpClient5Impl.java | 367 ++++++++++++++++++ 2 files changed, 372 insertions(+) create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceHttpClient5Impl.java diff --git a/weixin-java-pay/pom.xml b/weixin-java-pay/pom.xml index c396980a50..ce2501763d 100644 --- a/weixin-java-pay/pom.xml +++ b/weixin-java-pay/pom.xml @@ -34,6 +34,11 @@ jodd-util 6.1.0 + + org.apache.httpcomponents.client5 + httpclient5 + provided + org.apache.commons diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceHttpClient5Impl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceHttpClient5Impl.java new file mode 100644 index 0000000000..5845a8338a --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceHttpClient5Impl.java @@ -0,0 +1,367 @@ +package com.github.binarywang.wxpay.service.impl; + +import com.github.binarywang.wxpay.bean.WxPayApiData; +import com.github.binarywang.wxpay.config.WxPayConfig; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.v3.WxPayV3DownloadHttpGet; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.util.http.apache.ByteArrayResponseHandler; +import me.chanjar.weixin.common.util.json.GsonParser; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.*; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.*; +import org.apache.http.conn.ssl.DefaultHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +import javax.net.ssl.SSLContext; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Objects; +import java.util.Optional; + +/** + * 微信支付请求实现类,apache httpclient5 实现. + * + * @author altusea + */ +@Slf4j +public class WxPayServiceHttpClient5Impl extends BaseWxPayServiceImpl { + + private static final String ACCEPT = "Accept"; + private static final String CONTENT_TYPE = "Content-Type"; + private static final String APPLICATION_JSON = "application/json"; + private static final String WECHAT_PAY_SERIAL = "Wechatpay-Serial"; + + @Override + public byte[] postForBytes(String url, String requestStr, boolean useKey) throws WxPayException { + try { + HttpClientBuilder httpClientBuilder = createHttpClientBuilder(useKey); + HttpPost httpPost = this.createHttpPost(url, requestStr); + try (CloseableHttpClient httpClient = httpClientBuilder.build()) { + final byte[] bytes = httpClient.execute(httpPost, ByteArrayResponseHandler.INSTANCE); + final String responseData = Base64.getEncoder().encodeToString(bytes); + this.logRequestAndResponse(url, requestStr, responseData); + wxApiData.set(new WxPayApiData(url, requestStr, responseData, null)); + return bytes; + } + } catch (Exception e) { + this.logError(url, requestStr, e); + wxApiData.set(new WxPayApiData(url, requestStr, null, e.getMessage())); + throw new WxPayException(e.getMessage(), e); + } + } + + @Override + public String post(String url, String requestStr, boolean useKey) throws WxPayException { + try { + HttpClientBuilder httpClientBuilder = this.createHttpClientBuilder(useKey); + HttpPost httpPost = this.createHttpPost(url, requestStr); + try (CloseableHttpClient httpClient = httpClientBuilder.build()) { + try (CloseableHttpResponse response = httpClient.execute(httpPost)) { + String responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + this.logRequestAndResponse(url, requestStr, responseString); + if (this.getConfig().isIfSaveApiData()) { + wxApiData.set(new WxPayApiData(url, requestStr, responseString, null)); + } + return responseString; + } + } finally { + httpPost.releaseConnection(); + } + } catch (Exception e) { + this.logError(url, requestStr, e); + if (this.getConfig().isIfSaveApiData()) { + wxApiData.set(new WxPayApiData(url, requestStr, null, e.getMessage())); + } + throw new WxPayException(e.getMessage(), e); + } + } + + @Override + public String postV3(String url, String requestStr) throws WxPayException { + HttpPost httpPost = this.createHttpPost(url, requestStr); + this.configureRequest(httpPost); + return this.requestV3(url, requestStr, httpPost); + } + + private String requestV3(String url, String requestStr, HttpRequestBase httpRequestBase) throws WxPayException { + CloseableHttpClient httpClient = this.createApiV3HttpClient(); + try (CloseableHttpResponse response = httpClient.execute(httpRequestBase)) { + //v3已经改为通过状态码判断200 204 成功 + int statusCode = response.getStatusLine().getStatusCode(); + //post方法有可能会没有返回值的情况 + String responseString = null; + if (response.getEntity() != null) { + responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + } + + if (HttpStatus.SC_OK == statusCode || HttpStatus.SC_NO_CONTENT == statusCode) { + this.logRequestAndResponse(url, requestStr, responseString); + return responseString; + } + + //有错误提示信息返回 + JsonObject jsonObject = GsonParser.parse(responseString); + throw convertException(jsonObject); + } catch (Exception e) { + this.logError(url, requestStr, e); + throw (e instanceof WxPayException) ? (WxPayException) e : new WxPayException(e.getMessage(), e); + } finally { + httpRequestBase.releaseConnection(); + } + } + + @Override + public String patchV3(String url, String requestStr) throws WxPayException { + HttpPatch httpPatch = new HttpPatch(url); + httpPatch.setEntity(createEntry(requestStr)); + return this.requestV3(url, requestStr, httpPatch); + } + + @Override + public String postV3WithWechatpaySerial(String url, String requestStr) throws WxPayException { + HttpPost httpPost = this.createHttpPost(url, requestStr); + this.configureRequest(httpPost); + CloseableHttpClient httpClient = this.createApiV3HttpClient(); + try (CloseableHttpResponse response = httpClient.execute(httpPost)) { + //v3已经改为通过状态码判断200 204 成功 + int statusCode = response.getStatusLine().getStatusCode(); + String responseString = "{}"; + HttpEntity entity = response.getEntity(); + if (entity != null) { + responseString = EntityUtils.toString(entity, StandardCharsets.UTF_8); + } + + if (HttpStatus.SC_OK == statusCode || HttpStatus.SC_NO_CONTENT == statusCode) { + this.logRequestAndResponse(url, requestStr, responseString); + return responseString; + } + + //有错误提示信息返回 + JsonObject jsonObject = GsonParser.parse(responseString); + throw convertException(jsonObject); + } catch (Exception e) { + this.logError(url, requestStr, e); + throw (e instanceof WxPayException) ? (WxPayException) e : new WxPayException(e.getMessage(), e); + } finally { + httpPost.releaseConnection(); + } + } + + @Override + public String postV3(String url, HttpPost httpPost) throws WxPayException { + return this.requestV3(url, httpPost); + } + + @Override + public String requestV3(String url, HttpRequestBase httpRequest) throws WxPayException { + this.configureRequest(httpRequest); + CloseableHttpClient httpClient = this.createApiV3HttpClient(); + try (CloseableHttpResponse response = httpClient.execute(httpRequest)) { + //v3已经改为通过状态码判断200 204 成功 + int statusCode = response.getStatusLine().getStatusCode(); + //post方法有可能会没有返回值的情况 + String responseString = null; + if (response.getEntity() != null) { + responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + } + + if (HttpStatus.SC_OK == statusCode || HttpStatus.SC_NO_CONTENT == statusCode) { + log.info("\n【请求地址】:{}\n【响应数据】:{}", url, responseString); + return responseString; + } + + //有错误提示信息返回 + JsonObject jsonObject = GsonParser.parse(responseString); + throw convertException(jsonObject); + } catch (Exception e) { + log.error("\n【请求地址】:{}\n【异常信息】:{}", url, e.getMessage()); + throw (e instanceof WxPayException) ? (WxPayException) e : new WxPayException(e.getMessage(), e); + } finally { + httpRequest.releaseConnection(); + } + } + + @Override + public String getV3(String url) throws WxPayException { + if (this.getConfig().isStrictlyNeedWechatPaySerial()) { + return getV3WithWechatPaySerial(url); + } + HttpGet httpGet = new HttpGet(url); + return this.requestV3(url, httpGet); + } + + @Override + public String getV3WithWechatPaySerial(String url) throws WxPayException { + HttpGet httpGet = new HttpGet(url); + return this.requestV3(url, httpGet); + } + + @Override + public InputStream downloadV3(String url) throws WxPayException { + HttpGet httpGet = new WxPayV3DownloadHttpGet(url); + this.configureRequest(httpGet); + CloseableHttpClient httpClient = this.createApiV3HttpClient(); + try (CloseableHttpResponse response = httpClient.execute(httpGet)) { + //v3已经改为通过状态码判断200 204 成功 + int statusCode = response.getStatusLine().getStatusCode(); + Header contentType = response.getFirstHeader(HttpHeaders.CONTENT_TYPE); + boolean isJsonContentType = Objects.nonNull(contentType) && ContentType.APPLICATION_JSON.getMimeType() + .equals(ContentType.parse(String.valueOf(contentType.getValue())).getMimeType()); + if ((HttpStatus.SC_OK == statusCode || HttpStatus.SC_NO_CONTENT == statusCode) && !isJsonContentType) { + log.info("\n【请求地址】:{}\n", url); + return response.getEntity().getContent(); + } + + //response里的header有content-type=json说明返回了错误信息 + //有错误提示信息返回 + String responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + JsonObject jsonObject = GsonParser.parse(responseString); + throw convertException(jsonObject); + } catch (Exception e) { + log.error("\n【请求地址】:{}\n【异常信息】:{}", url, e.getMessage()); + throw (e instanceof WxPayException) ? (WxPayException) e : new WxPayException(e.getMessage(), e); + } finally { + httpGet.releaseConnection(); + } + } + + @Override + public String putV3(String url, String requestStr) throws WxPayException { + HttpPut httpPut = new HttpPut(url); + StringEntity entity = createEntry(requestStr); + httpPut.setEntity(entity); + return requestV3(url, httpPut); + } + + @Override + public String deleteV3(String url) throws WxPayException { + HttpDelete httpDelete = new HttpDelete(url); + return requestV3(url, httpDelete); + } + + private void configureRequest(HttpRequestBase request) { + String serialNumber = getWechatPaySerial(getConfig()); + String method = request.getMethod(); + request.addHeader(ACCEPT, APPLICATION_JSON); + if (!method.equals("POST")) { + request.addHeader(CONTENT_TYPE, APPLICATION_JSON); + } + request.addHeader(WECHAT_PAY_SERIAL, serialNumber); + + request.setConfig(RequestConfig.custom() + .setConnectionRequestTimeout(this.getConfig().getHttpConnectionTimeout()) + .setConnectTimeout(this.getConfig().getHttpConnectionTimeout()) + .setSocketTimeout(this.getConfig().getHttpTimeout()) + .build()); + } + + private CloseableHttpClient createApiV3HttpClient() throws WxPayException { + CloseableHttpClient apiV3HttpClient = this.getConfig().getApiV3HttpClient(); + if (null == apiV3HttpClient) { + return this.getConfig().initApiV3HttpClient(); + } + return apiV3HttpClient; + } + + private static StringEntity createEntry(String requestStr) { + return new StringEntity(requestStr, ContentType.create(APPLICATION_JSON, StandardCharsets.UTF_8)); + //return new StringEntity(new String(requestStr.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1)); + } + + private HttpClientBuilder createHttpClientBuilder(boolean useKey) throws WxPayException { + HttpClientBuilder httpClientBuilder = HttpClients.custom(); + if (useKey) { + this.initSSLContext(httpClientBuilder); + } + + if (StringUtils.isNotBlank(this.getConfig().getHttpProxyHost()) && this.getConfig().getHttpProxyPort() > 0) { + if (StringUtils.isEmpty(this.getConfig().getHttpProxyUsername())) { + this.getConfig().setHttpProxyUsername("whatever"); + } + + // 使用代理服务器 需要用户认证的代理服务器 + CredentialsProvider provider = new BasicCredentialsProvider(); + provider.setCredentials(new AuthScope(this.getConfig().getHttpProxyHost(), + this.getConfig().getHttpProxyPort()), + new UsernamePasswordCredentials(this.getConfig().getHttpProxyUsername(), + this.getConfig().getHttpProxyPassword())); + httpClientBuilder.setDefaultCredentialsProvider(provider) + .setProxy(new HttpHost(this.getConfig().getHttpProxyHost(), this.getConfig().getHttpProxyPort())); + } + + // 提供自定义httpClientBuilder的能力 + Optional.ofNullable(getConfig().getHttpClientBuilderCustomizer()).ifPresent(e -> { + e.customize(httpClientBuilder); + }); + + return httpClientBuilder; + } + + private HttpPost createHttpPost(String url, String requestStr) { + HttpPost httpPost = new HttpPost(url); + httpPost.setEntity(createEntry(requestStr)); + + httpPost.setConfig(RequestConfig.custom() + .setConnectionRequestTimeout(this.getConfig().getHttpConnectionTimeout()) + .setConnectTimeout(this.getConfig().getHttpConnectionTimeout()) + .setSocketTimeout(this.getConfig().getHttpTimeout()) + .build()); + + return httpPost; + } + + private void initSSLContext(HttpClientBuilder httpClientBuilder) throws WxPayException { + SSLContext sslContext = this.getConfig().getSslContext(); + if (null == sslContext) { + sslContext = this.getConfig().initSSLContext(); + } + + httpClientBuilder.setSSLSocketFactory(new SSLConnectionSocketFactory(sslContext, + new DefaultHostnameVerifier())); + } + + private WxPayException convertException(JsonObject jsonObject) { + //TODO 这里考虑使用新的适用于V3的异常 + JsonElement codeElement = jsonObject.get("code"); + String code = codeElement == null ? null : codeElement.getAsString(); + String message = jsonObject.get("message").getAsString(); + WxPayException wxPayException = new WxPayException(message); + wxPayException.setErrCode(code); + wxPayException.setErrCodeDes(message); + return wxPayException; + } + + /** + * 兼容微信支付公钥模式 + */ + private String getWechatPaySerial(WxPayConfig wxPayConfig) { + if (StringUtils.isNotBlank(wxPayConfig.getPublicKeyId())) { + return wxPayConfig.getPublicKeyId(); + } + + return wxPayConfig.getVerifier().getValidCertificate().getSerialNumber().toString(16).toUpperCase(); + } + + private void logRequestAndResponse(String url, String requestStr, String responseStr) { + log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据】:{}", url, requestStr, responseStr); + } + + private void logError(String url, String requestStr, Exception e) { + log.error("\n【请求地址】:{}\n【请求数据】:{}\n【异常信息】:{}", url, requestStr, e.getMessage()); + } +} From 2b5a2b1ed03654f857fec18c5ef11a6d76adf078 Mon Sep 17 00:00:00 2001 From: altusea Date: Tue, 3 Jun 2025 21:33:33 +0800 Subject: [PATCH 12/31] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=20serialVersionUID=20?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E5=B9=B6=E4=BC=98=E5=8C=96=E9=83=A8=E5=88=86?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wxpay/bean/marketing/BusiFavorCouponCodeRequest.java | 2 +- .../wxpay/bean/marketing/BusiFavorCouponCodeResult.java | 6 +++--- .../wxpay/bean/marketing/BusiFavorCouponsUrlRequest.java | 6 ++++-- .../wxpay/bean/marketing/BusiFavorCouponsUseRequest.java | 6 ++++-- .../bean/marketing/BusiFavorQueryOneUserCouponsRequest.java | 2 +- .../bean/marketing/BusiFavorQueryOneUserCouponsResult.java | 2 +- .../bean/marketing/BusiFavorQueryUserCouponsRequest.java | 2 +- .../bean/marketing/BusiFavorQueryUserCouponsResult.java | 2 +- .../wxpay/bean/marketing/busifavor/AvailableWeek.java | 4 ++-- .../wxpay/bean/marketing/busifavor/CouponAvailableTime.java | 2 +- .../bean/marketing/busifavor/IrregularyAvaliableTime.java | 2 +- .../wxpay/bean/marketing/transfer/BatchDetailsRequest.java | 2 +- .../wxpay/bean/marketing/transfer/BatchDetailsResult.java | 2 +- .../wxpay/bean/marketing/transfer/BatchNumberRequest.java | 2 +- .../wxpay/bean/marketing/transfer/BatchNumberResult.java | 2 +- .../wxpay/bean/marketing/transfer/BillReceiptResult.java | 2 +- .../wxpay/bean/marketing/transfer/DownloadRequest.java | 2 +- .../bean/marketing/transfer/ElectronicReceiptsRequest.java | 2 +- .../bean/marketing/transfer/ElectronicReceiptsResult.java | 2 +- .../wxpay/bean/marketing/transfer/MerchantBatchRequest.java | 2 +- .../bean/marketing/transfer/PartnerTransferRequest.java | 2 +- .../bean/marketing/transfer/PartnerTransferResult.java | 2 +- .../wxpay/bean/marketing/transfer/ReceiptBillRequest.java | 2 +- .../binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java | 2 +- .../java/com/github/binarywang/wxpay/util/SignUtils.java | 3 +-- .../java/com/github/binarywang/wxpay/util/ZipUtils.java | 2 +- 26 files changed, 35 insertions(+), 32 deletions(-) diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorCouponCodeRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorCouponCodeRequest.java index fa6ca553e9..2ab481849e 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorCouponCodeRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorCouponCodeRequest.java @@ -18,7 +18,7 @@ @Data @NoArgsConstructor public class BusiFavorCouponCodeRequest implements Serializable { - public static final float serialVersionUID = 1L; + private static final long serialVersionUID = 1L; /** *
* 字段名:批次号
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorCouponCodeResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorCouponCodeResult.java
index ca45a091c4..bca9ea932e 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorCouponCodeResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorCouponCodeResult.java
@@ -18,7 +18,7 @@
 @Data
 @NoArgsConstructor
 public class BusiFavorCouponCodeResult implements Serializable {
-  public static final float serialVersionUID = 1L;
+  private static final long serialVersionUID = 1L;
 
   /**
    * 
* 字段名:批次号
@@ -130,8 +130,8 @@ public class BusiFavorCouponCodeResult implements Serializable {
 
   @Data
   @NoArgsConstructor
-  public static class FailCode {
-    public static final float serialVersionUID = 1L;
+  public static class FailCode implements Serializable {
+    private static final long serialVersionUID = 1L;
 
     /**
      * 
* 字段名:上传失败的券code
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorCouponsUrlRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorCouponsUrlRequest.java
index 11319e56b4..8af44901e0 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorCouponsUrlRequest.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorCouponsUrlRequest.java
@@ -4,6 +4,8 @@
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
+import java.io.Serializable;
+
 /**
  * H5发券请求对象
  * 
@@ -14,8 +16,8 @@
  */
 @Data
 @NoArgsConstructor
-public class BusiFavorCouponsUrlRequest {
-  public static final float serialVersionUID = 1L;
+public class BusiFavorCouponsUrlRequest implements Serializable {
+  private static final long serialVersionUID = 1L;
 
   /**
    * 
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorCouponsUseRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorCouponsUseRequest.java
index ab8a8ba2a5..9d365054e9 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorCouponsUseRequest.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorCouponsUseRequest.java
@@ -4,6 +4,8 @@
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
+import java.io.Serializable;
+
 /**
  * 核销用户券请求对象
  * 
@@ -14,8 +16,8 @@
  */
 @Data
 @NoArgsConstructor
-public class BusiFavorCouponsUseRequest {
-  public static final float serialVersionUID = 1L;
+public class BusiFavorCouponsUseRequest implements Serializable {
+  private static final long serialVersionUID = 1L;
 
   /**
    * 
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorQueryOneUserCouponsRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorQueryOneUserCouponsRequest.java
index 3dad3fe5d1..0a53cd33d1 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorQueryOneUserCouponsRequest.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorQueryOneUserCouponsRequest.java
@@ -17,7 +17,7 @@
 @Data
 @NoArgsConstructor
 public class BusiFavorQueryOneUserCouponsRequest implements Serializable {
-  public static final float serialVersionUID = 1L;
+  private static final long serialVersionUID = 1L;
 
   /**
    * 
* 字段名:用户标识
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorQueryOneUserCouponsResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorQueryOneUserCouponsResult.java
index 6db7d303a9..566957eb51 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorQueryOneUserCouponsResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorQueryOneUserCouponsResult.java
@@ -20,7 +20,7 @@
 @Data
 @NoArgsConstructor
 public class BusiFavorQueryOneUserCouponsResult implements Serializable {
-  public static final float serialVersionUID = 1L;
+  private static final long serialVersionUID = 1L;
 
   /**
    * 
* 字段名:批次归属商户号
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorQueryUserCouponsRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorQueryUserCouponsRequest.java
index 600a48c8de..0c417c425a 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorQueryUserCouponsRequest.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorQueryUserCouponsRequest.java
@@ -17,7 +17,7 @@
 @Data
 @NoArgsConstructor
 public class BusiFavorQueryUserCouponsRequest implements Serializable {
-  public static final float serialVersionUID = 1L;
+  private static final long serialVersionUID = 1L;
 
   /**
    * 
* 字段名:用户标识
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorQueryUserCouponsResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorQueryUserCouponsResult.java
index 9b5f57b040..c2906be27e 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorQueryUserCouponsResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/BusiFavorQueryUserCouponsResult.java
@@ -18,7 +18,7 @@
 @Data
 @NoArgsConstructor
 public class BusiFavorQueryUserCouponsResult implements Serializable {
-  public static final float serialVersionUID = 1L;
+  private static final long serialVersionUID = 1L;
 
   /**
    * 
* 字段名:+结果集
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/busifavor/AvailableWeek.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/busifavor/AvailableWeek.java
index 410a285ca2..487291a739 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/busifavor/AvailableWeek.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/busifavor/AvailableWeek.java
@@ -17,7 +17,7 @@
 @Data
 @NoArgsConstructor
 public class AvailableWeek implements Serializable {
-  public static final float serialVersionUID = 1L;
+  private static final long serialVersionUID = 1L;
 
   /**
    * 
@@ -51,7 +51,7 @@ public class AvailableWeek implements Serializable {
   @Data
   @NoArgsConstructor
   public static class AvailableDayTimeItem implements Serializable {
-    public static final float serialVersionUID = 1L;
+    private static final long serialVersionUID = 1L;
 
     /**
      * 
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/busifavor/CouponAvailableTime.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/busifavor/CouponAvailableTime.java
index 31833c1188..f41692c068 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/busifavor/CouponAvailableTime.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/busifavor/CouponAvailableTime.java
@@ -18,7 +18,7 @@
 @Data
 @NoArgsConstructor
 public class CouponAvailableTime implements Serializable {
-  public static final float serialVersionUID = 1L;
+  private static final long serialVersionUID = 1L;
 
   /**
    * 
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/busifavor/IrregularyAvaliableTime.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/busifavor/IrregularyAvaliableTime.java
index 4ddd196e56..0b11010493 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/busifavor/IrregularyAvaliableTime.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/busifavor/IrregularyAvaliableTime.java
@@ -18,7 +18,7 @@
 @NoArgsConstructor
 public class IrregularyAvaliableTime implements Serializable {
 
-  public static final float serialVersionUID = 1L;
+  private static final long serialVersionUID = 1L;
 
   /**
    * 
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BatchDetailsRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BatchDetailsRequest.java
index 9aa51ce742..bbb4e93ab4 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BatchDetailsRequest.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BatchDetailsRequest.java
@@ -23,7 +23,7 @@
 @Data
 @NoArgsConstructor
 public class BatchDetailsRequest implements Serializable {
-  public static final float serialVersionUID = 1L;
+  private static final long serialVersionUID = 1L;
   /**
    * 
    * 字段名:微信支付批次单号
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BatchDetailsResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BatchDetailsResult.java
index 720cd72503..4ca7958ed5 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BatchDetailsResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BatchDetailsResult.java
@@ -25,7 +25,7 @@
 @Data
 @NoArgsConstructor
 public class BatchDetailsResult implements Serializable {
-  public static final float serialVersionUID = 1L;
+  private static final long serialVersionUID = 1L;
 
   @Override
   public String toString() {
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BatchNumberRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BatchNumberRequest.java
index 9f53843d66..127c38cdc6 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BatchNumberRequest.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BatchNumberRequest.java
@@ -18,7 +18,7 @@
 @Data
 @NoArgsConstructor
 public class BatchNumberRequest implements Serializable {
-  public static final float serialVersionUID = 1L;
+  private static final long serialVersionUID = 1L;
 
   /**
    * 
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BatchNumberResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BatchNumberResult.java
index 1defcca943..a59ccbc85f 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BatchNumberResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BatchNumberResult.java
@@ -20,7 +20,7 @@
 @Data
 @NoArgsConstructor
 public class BatchNumberResult implements Serializable {
-  public static final float serialVersionUID = 1L;
+  private static final long serialVersionUID = 1L;
 
   @Override
   public String toString() {
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BillReceiptResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BillReceiptResult.java
index ea83328308..fc0b97d7bb 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BillReceiptResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BillReceiptResult.java
@@ -20,7 +20,7 @@
 @Data
 @NoArgsConstructor
 public class BillReceiptResult implements Serializable {
-  public static final float serialVersionUID = 1L;
+  private static final long serialVersionUID = 1L;
 
   @Override
   public String toString() {
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/DownloadRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/DownloadRequest.java
index 50ca1feac7..3f147abd00 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/DownloadRequest.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/DownloadRequest.java
@@ -21,7 +21,7 @@
 @Data
 @NoArgsConstructor
 public class DownloadRequest implements Serializable {
-  public static final float serialVersionUID = 1L;
+  private static final long serialVersionUID = 1L;
 
   /**
    * 
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/ElectronicReceiptsRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/ElectronicReceiptsRequest.java
index 1f4d8134f4..cc419d3a4f 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/ElectronicReceiptsRequest.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/ElectronicReceiptsRequest.java
@@ -20,7 +20,7 @@
 @Data
 @NoArgsConstructor
 public class ElectronicReceiptsRequest implements Serializable {
-  public static final float serialVersionUID = 1L;
+  private static final long serialVersionUID = 1L;
   /**
    * 
    * 字段名:受理类型
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/ElectronicReceiptsResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/ElectronicReceiptsResult.java
index 114b1982c3..4e0581108c 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/ElectronicReceiptsResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/ElectronicReceiptsResult.java
@@ -20,7 +20,7 @@
 @Data
 @NoArgsConstructor
 public class ElectronicReceiptsResult implements Serializable {
-  public static final float serialVersionUID = 1L;
+  private static final long serialVersionUID = 1L;
   /**
    * 
    * 字段名:受理类型
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/MerchantBatchRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/MerchantBatchRequest.java
index fe6450b22e..a319d3f4b3 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/MerchantBatchRequest.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/MerchantBatchRequest.java
@@ -20,7 +20,7 @@
 @Data
 @NoArgsConstructor
 public class MerchantBatchRequest implements Serializable {
-  public static final float serialVersionUID = 1L;
+  private static final long serialVersionUID = 1L;
   /**
    * 
    * 字段名:商家批次单号
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/PartnerTransferRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/PartnerTransferRequest.java
index bd06b5db4b..0e8418cca9 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/PartnerTransferRequest.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/PartnerTransferRequest.java
@@ -19,7 +19,7 @@
 @Data
 @NoArgsConstructor
 public class PartnerTransferRequest implements Serializable {
-  public static final float serialVersionUID = 1L;
+  private static final long serialVersionUID = 1L;
 
   /**
    * 
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/PartnerTransferResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/PartnerTransferResult.java
index cca369b408..d9c8019462 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/PartnerTransferResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/PartnerTransferResult.java
@@ -18,7 +18,7 @@
 @Data
 @NoArgsConstructor
 public class PartnerTransferResult implements Serializable {
-  public static final float serialVersionUID = 1L;
+  private static final long serialVersionUID = 1L;
   /**
    * 
    * 字段名:商家批次单号
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/ReceiptBillRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/ReceiptBillRequest.java
index deda24d426..1995ac1656 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/ReceiptBillRequest.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/ReceiptBillRequest.java
@@ -18,7 +18,7 @@
 @Data
 @NoArgsConstructor
 public class ReceiptBillRequest implements Serializable {
-  public static final float serialVersionUID = 1L;
+  private static final long serialVersionUID = 1L;
   /**
    * 
    * 字段名:商家批次单号
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 f171a04ed2..ce0fbaf375 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
@@ -64,7 +64,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
 
   private static final Gson GSON = new GsonBuilder().create();
 
-  static ThreadLocal wxApiData = new ThreadLocal<>();
+  static final ThreadLocal wxApiData = new ThreadLocal<>();
 
 
   @Setter
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/SignUtils.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/SignUtils.java
index 9e005a813e..6c0009fd18 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/SignUtils.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/SignUtils.java
@@ -92,8 +92,7 @@ public static String createSign(Map params, String signType, Str
     for (String key : new TreeMap<>(params).keySet()) {
       String value = params.get(key);
       boolean shouldSign = false;
-      if (StringUtils.isNotEmpty(value) && !ArrayUtils.contains(ignoredParams, key)
-        && !NO_SIGN_PARAMS.contains(key)) {
+      if (StringUtils.isNotEmpty(value) && !ArrayUtils.contains(ignoredParams, key) && !NO_SIGN_PARAMS.contains(key)) {
         shouldSign = true;
       }
 
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/ZipUtils.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/ZipUtils.java
index f9c434196a..1bab0432e6 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/ZipUtils.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/ZipUtils.java
@@ -24,7 +24,7 @@ public static File unGzip(final File file) throws IOException {
     resultFile.createNewFile();
 
     try (FileOutputStream fos = new FileOutputStream(resultFile);
-         GZIPInputStream gzis = new GZIPInputStream(new FileInputStream(file));) {
+         GZIPInputStream gzis = new GZIPInputStream(new FileInputStream(file))) {
       IOUtils.copy(gzis, fos);
     }
 

From 516ccc2e45e4cfa80e76f6608680142cadd27551 Mon Sep 17 00:00:00 2001
From: altusea 
Date: Tue, 3 Jun 2025 21:49:50 +0800
Subject: [PATCH 13/31] =?UTF-8?q?=E5=8D=87=E7=BA=A7=20Bouncy=20Castle=20?=
 =?UTF-8?q?=E4=BE=9D=E8=B5=96=E7=89=88=E6=9C=AC=E8=87=B3=201.80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 pom.xml                | 2 +-
 weixin-java-cp/pom.xml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index cf84451605..306677ad84 100644
--- a/pom.xml
+++ b/pom.xml
@@ -333,7 +333,7 @@
       
         org.bouncycastle
         bcpkix-jdk18on
-        1.78.1
+        1.80
       
     
   
diff --git a/weixin-java-cp/pom.xml b/weixin-java-cp/pom.xml
index b8a7ccfc5b..809ac65f4e 100644
--- a/weixin-java-cp/pom.xml
+++ b/weixin-java-cp/pom.xml
@@ -89,7 +89,7 @@
     
       org.bouncycastle
       bcprov-jdk18on
-      1.78.1
+      1.80
     
 
     

From 9e3cf4568fd406fce027fc8208a5995a558c77b9 Mon Sep 17 00:00:00 2001
From: altusea 
Date: Tue, 3 Jun 2025 22:01:53 +0800
Subject: [PATCH 14/31] =?UTF-8?q?=E5=8D=87=E7=BA=A7=20Jackson=20=E4=BE=9D?=
 =?UTF-8?q?=E8=B5=96=E7=89=88=E6=9C=AC=E5=88=B0=202.18.4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 pom.xml                     | 2 +-
 weixin-java-channel/pom.xml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index 306677ad84..96974411b6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -212,7 +212,7 @@
       
         com.fasterxml.jackson
         jackson-bom
-        2.18.1
+        2.18.4
         pom
         import
       
diff --git a/weixin-java-channel/pom.xml b/weixin-java-channel/pom.xml
index a7cc2a4ddc..a31f688147 100644
--- a/weixin-java-channel/pom.xml
+++ b/weixin-java-channel/pom.xml
@@ -14,7 +14,7 @@
   微信视频号/微信小店 Java SDK
 
   
-    2.18.1
+    2.18.4
   
 
   

From 1acdb16742a9aaf553fccc780562fefcbec9e3d7 Mon Sep 17 00:00:00 2001
From: altusea 
Date: Wed, 4 Jun 2025 15:40:57 +0800
Subject: [PATCH 15/31] =?UTF-8?q?=E4=BD=BF=E7=94=A8=20JsonParser=20?=
 =?UTF-8?q?=E7=9A=84=E9=9D=99=E6=80=81=E6=96=B9=E6=B3=95=E6=9B=BF=E4=BB=A3?=
 =?UTF-8?q?=E5=AE=9E=E4=BE=8B=E6=96=B9=E6=B3=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../bean/result/WxMinishopImageUploadCustomizeResult.java  | 2 +-
 .../common/bean/result/WxMinishopImageUploadResult.java    | 2 +-
 .../main/java/me/chanjar/weixin/common/util/DataUtils.java | 3 ++-
 .../me/chanjar/weixin/common/util/json/GsonParser.java     | 7 +++----
 .../me/chanjar/weixin/common/util/res/StringManager.java   | 4 ++--
 .../me/chanjar/weixin/cp/api/impl/WxCpOaServiceImpl.java   | 4 ++--
 .../me/chanjar/weixin/mp/api/impl/WxMpCardServiceImpl.java | 4 ++--
 .../weixin/mp/api/impl/WxMpMemberCardServiceImpl.java      | 4 ++--
 8 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxMinishopImageUploadCustomizeResult.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxMinishopImageUploadCustomizeResult.java
index cd700be7c1..5427d5cada 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxMinishopImageUploadCustomizeResult.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxMinishopImageUploadCustomizeResult.java
@@ -16,7 +16,7 @@ public class WxMinishopImageUploadCustomizeResult implements Serializable {
   private WxMinishopPicFileCustomizeResult imgInfo;
 
   public static WxMinishopImageUploadCustomizeResult fromJson(String json) {
-    JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();
+    JsonObject jsonObject = JsonParser.parseString(json).getAsJsonObject();
     WxMinishopImageUploadCustomizeResult result = new WxMinishopImageUploadCustomizeResult();
     result.setErrcode(jsonObject.get(WxConsts.ERR_CODE).getAsNumber().toString());
     if (result.getErrcode().equals("0")) {
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxMinishopImageUploadResult.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxMinishopImageUploadResult.java
index 324232d0ee..9c2cbaf3ba 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxMinishopImageUploadResult.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/result/WxMinishopImageUploadResult.java
@@ -21,7 +21,7 @@ public class WxMinishopImageUploadResult  implements Serializable {
 
 
   public static WxMinishopImageUploadResult fromJson(String json) {
-    JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();
+    JsonObject jsonObject = JsonParser.parseString(json).getAsJsonObject();
     WxMinishopImageUploadResult result = new WxMinishopImageUploadResult();
     result.setErrcode(jsonObject.get(WxConsts.ERR_CODE).getAsNumber().toString());
     if (result.getErrcode().equals("0")) {
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/DataUtils.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/DataUtils.java
index 983d9a668f..b8fb42e0e9 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/DataUtils.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/DataUtils.java
@@ -1,5 +1,6 @@
 package me.chanjar.weixin.common.util;
 
+import org.apache.commons.lang3.RegExUtils;
 import org.apache.commons.lang3.StringUtils;
 
 /**
@@ -17,7 +18,7 @@ public class DataUtils {
   public static  E handleDataWithSecret(E data) {
     E dataForLog = data;
     if(data instanceof String && StringUtils.contains((String)data, "&secret=")){
-      dataForLog = (E) StringUtils.replaceAll((String)data,"&secret=\\w+&","&secret=******&");
+      dataForLog = (E) RegExUtils.replaceAll((String)data,"&secret=\\w+&","&secret=******&");
     }
     return dataForLog;
   }
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/GsonParser.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/GsonParser.java
index 061a3cb2ee..f2646436c0 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/GsonParser.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/GsonParser.java
@@ -10,17 +10,16 @@
  * @author niefy
  */
 public class GsonParser {
-  private static final JsonParser JSON_PARSER = new JsonParser();
 
   public static JsonObject parse(String json) {
-    return JSON_PARSER.parse(json).getAsJsonObject();
+    return JsonParser.parseString(json).getAsJsonObject();
   }
 
   public static JsonObject parse(Reader json) {
-    return JSON_PARSER.parse(json).getAsJsonObject();
+    return JsonParser.parseReader(json).getAsJsonObject();
   }
 
   public static JsonObject parse(JsonReader json) {
-    return JSON_PARSER.parse(json).getAsJsonObject();
+    return JsonParser.parseReader(json).getAsJsonObject();
   }
 }
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/res/StringManager.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/res/StringManager.java
index e5bdb38804..fd2f13a553 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/res/StringManager.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/res/StringManager.java
@@ -102,7 +102,7 @@ private StringManager(String packageName, Locale locale) {
    *
    * @param packageName The package name
    */
-  public static final synchronized StringManager getManager(
+  public static synchronized StringManager getManager(
     String packageName) {
     return getManager(packageName, Locale.getDefault());
   }
@@ -115,7 +115,7 @@ public static final synchronized StringManager getManager(
    * @param packageName The package name
    * @param locale      The Locale
    */
-  public static final synchronized StringManager getManager(
+  public static synchronized StringManager getManager(
     String packageName, Locale locale) {
 
     Map map = MANAGERS.get(packageName);
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOaServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOaServiceImpl.java
index 53aaa00ca7..59cde79a93 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOaServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOaServiceImpl.java
@@ -140,7 +140,7 @@ public WxCpApprovalInfo getApprovalInfo(@NonNull Date startTime, @NonNull Date e
     if (filters != null && !filters.isEmpty()) {
       JsonArray filterJsonArray = new JsonArray();
       for (WxCpApprovalInfoQueryFilter filter : filters) {
-        filterJsonArray.add(new JsonParser().parse(filter.toJson()));
+        filterJsonArray.add(JsonParser.parseString(filter.toJson()));
       }
       jsonObject.add("filters", filterJsonArray);
     }
@@ -181,7 +181,7 @@ public WxCpApprovalInfo getApprovalInfo(@NonNull Date startTime, @NonNull Date e
     if (filters != null && !filters.isEmpty()) {
       JsonArray filterJsonArray = new JsonArray();
       for (WxCpApprovalInfoQueryFilter filter : filters) {
-        filterJsonArray.add(new JsonParser().parse(filter.toJson()));
+        filterJsonArray.add(JsonParser.parseString(filter.toJson()));
       }
       jsonObject.add("filters", filterJsonArray);
     }
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpCardServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpCardServiceImpl.java
index 6d7d66a782..8fce1d4736 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpCardServiceImpl.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpCardServiceImpl.java
@@ -114,7 +114,7 @@ public WxMpCardResult queryCardCode(String cardId, String code, boolean checkCon
     param.addProperty("code", code);
     param.addProperty("check_consume", checkConsume);
     String responseContent = this.wxMpService.post(WxMpApiUrl.Card.CARD_CODE_GET, param.toString());
-    JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
+    JsonElement tmpJsonElement = JsonParser.parseString(responseContent);
     return WxMpGsonBuilder.create().fromJson(tmpJsonElement,
       new TypeToken() {
       }.getType());
@@ -145,7 +145,7 @@ public void markCardCode(String code, String cardId, String openId, boolean isMa
     param.addProperty("openid", openId);
     param.addProperty("is_mark", isMark);
     String responseContent = this.getWxMpService().post(WxMpApiUrl.Card.CARD_CODE_MARK, param.toString());
-    JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
+    JsonElement tmpJsonElement = JsonParser.parseString(responseContent);
     WxMpCardResult cardResult = WxMpGsonBuilder.create().fromJson(tmpJsonElement,
       new TypeToken() {
       }.getType());
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMemberCardServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMemberCardServiceImpl.java
index 3617c01b51..7a01c6a014 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMemberCardServiceImpl.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMemberCardServiceImpl.java
@@ -217,7 +217,7 @@ public WxMpMemberCardUserInfoResult getUserInfo(String cardId, String code) thro
 
     String responseContent = this.getWxMpService().post(WxMpApiUrl.MemberCard.MEMBER_CARD_USER_INFO_GET, jsonObject.toString());
     log.debug("{}", responseContent);
-    JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
+    JsonElement tmpJsonElement = JsonParser.parseString(responseContent);
     return WxMpGsonBuilder.create().fromJson(tmpJsonElement,
       new TypeToken() {
       }.getType());
@@ -229,7 +229,7 @@ public WxMpMemberCardUpdateResult updateUserMemberCard(WxMpMemberCardUpdateMessa
 
     String responseContent = this.getWxMpService().post(WxMpApiUrl.MemberCard.MEMBER_CARD_UPDATE_USER, GSON.toJson(updateUserMessage));
 
-    JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
+    JsonElement tmpJsonElement = JsonParser.parseString(responseContent);
     return WxMpGsonBuilder.create().fromJson(tmpJsonElement,
       new TypeToken() {
       }.getType());

From 99b0e1af087833145c727bd0262c9fc541778789 Mon Sep 17 00:00:00 2001
From: altusea 
Date: Wed, 4 Jun 2025 19:33:14 +0800
Subject: [PATCH 16/31] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20HttpClient5QrcodeByt?=
 =?UTF-8?q?esRequestExecutor=20=E7=B1=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../ApacheMediaDownloadRequestExecutor.java   |  2 +-
 weixin-java-miniapp/pom.xml                   |  5 ++
 ...HttpClient5QrcodeBytesRequestExecutor.java | 71 +++++++++++++++++++
 .../executor/QrcodeBytesRequestExecutor.java  | 10 +--
 .../QrCodeHttpClient5RequestExecutor.java     |  2 +-
 5 files changed, 83 insertions(+), 7 deletions(-)
 create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5QrcodeBytesRequestExecutor.java

diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheMediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheMediaDownloadRequestExecutor.java
index f58ac2fde1..95e55469cc 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheMediaDownloadRequestExecutor.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheMediaDownloadRequestExecutor.java
@@ -71,7 +71,7 @@ public File execute(String uri, String queryParam, WxType wxType) throws WxError
       }
 
       return FileUtils.createTmpFile(inputStream, baseName, FilenameUtils.getExtension(fileName), super.tmpDirFile);
-    } catch (final HttpException httpException) {
+    } catch (HttpException httpException) {
       throw new ClientProtocolException(httpException.getMessage(), httpException);
     }
   }
diff --git a/weixin-java-miniapp/pom.xml b/weixin-java-miniapp/pom.xml
index 3c3898f3f3..4599190d0a 100644
--- a/weixin-java-miniapp/pom.xml
+++ b/weixin-java-miniapp/pom.xml
@@ -31,6 +31,11 @@
       okhttp
       provided
     
+    
+      org.apache.httpcomponents.client5
+      httpclient5
+      provided
+    
 
     
       org.testng
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5QrcodeBytesRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5QrcodeBytesRequestExecutor.java
new file mode 100644
index 0000000000..5a536560b2
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5QrcodeBytesRequestExecutor.java
@@ -0,0 +1,71 @@
+package cn.binarywang.wx.miniapp.executor;
+
+import cn.binarywang.wx.miniapp.bean.AbstractWxMaQrcodeWrapper;
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxError;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.hc5.InputStreamResponseHandler;
+import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import org.apache.commons.io.IOUtils;
+import org.apache.hc.client5.http.ClientProtocolException;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.io.entity.StringEntity;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * @author altusea
+ */
+public class HttpClient5QrcodeBytesRequestExecutor extends QrcodeBytesRequestExecutor {
+
+
+  public HttpClient5QrcodeBytesRequestExecutor(RequestHttp requestHttp) {
+    super(requestHttp);
+  }
+
+  /**
+   * 执行http请求.
+   *
+   * @param uri           uri
+   * @param qrcodeWrapper 数据
+   * @param wxType        微信模块类型
+   * @return 响应结果
+   * @throws WxErrorException 自定义异常
+   * @throws IOException      io异常
+   */
+  @Override
+  public byte[] execute(String uri, AbstractWxMaQrcodeWrapper qrcodeWrapper, WxType wxType) throws WxErrorException, IOException {
+    HttpPost httpPost = new HttpPost(uri);
+    if (requestHttp.getRequestHttpProxy() != null) {
+      httpPost.setConfig(
+        RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build()
+      );
+    }
+
+    httpPost.setEntity(new StringEntity(qrcodeWrapper.toJson()));
+
+    try (final CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpPost);
+         final InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response)) {
+      Header[] contentTypeHeader = response.getHeaders("Content-Type");
+      if (contentTypeHeader != null && contentTypeHeader.length > 0
+        && ContentType.APPLICATION_JSON.getMimeType()
+        .equals(ContentType.parse(contentTypeHeader[0].getValue()).getMimeType())) {
+        String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
+        throw new WxErrorException(WxError.fromJson(responseContent, wxType));
+      }
+
+      return IOUtils.toByteArray(inputStream);
+    } catch (HttpException httpException) {
+      throw new ClientProtocolException(httpException.getMessage(), httpException);
+    }
+  }
+}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeBytesRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeBytesRequestExecutor.java
index 0fe21055c2..24e97d7b21 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeBytesRequestExecutor.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeBytesRequestExecutor.java
@@ -8,8 +8,6 @@
 import me.chanjar.weixin.common.util.http.ResponseHandler;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
 import okhttp3.OkHttpClient;
-import org.apache.http.HttpHost;
-import org.apache.http.impl.client.CloseableHttpClient;
 
 import java.io.IOException;
 
@@ -33,11 +31,13 @@ public void execute(String uri, AbstractWxMaQrcodeWrapper data, ResponseHandler<
   public static RequestExecutor create(RequestHttp requestHttp) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new ApacheQrcodeBytesRequestExecutor((RequestHttp) requestHttp);
-      case JODD_HTTP:
-        return null;
+        return new ApacheQrcodeBytesRequestExecutor(
+          (RequestHttp) requestHttp);
       case OK_HTTP:
         return new OkHttpQrcodeBytesRequestExecutor((RequestHttp) requestHttp);
+      case HTTP_CLIENT_5:
+        return new HttpClient5QrcodeBytesRequestExecutor(
+          (RequestHttp) requestHttp);
       default:
         return null;
     }
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeHttpClient5RequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeHttpClient5RequestExecutor.java
index ccbc6af35a..aecf7de7f7 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeHttpClient5RequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeHttpClient5RequestExecutor.java
@@ -60,7 +60,7 @@ public File execute(String uri, WxMpQrCodeTicket ticket, WxType wxType) throws W
         }
       }
       return FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), "jpg");
-    } catch (final HttpException httpException) {
+    } catch (HttpException httpException) {
       throw new ClientProtocolException(httpException.getMessage(), httpException);
     }
   }

From 88b87062b4915fad6d072e3efce40195566b8fd5 Mon Sep 17 00:00:00 2001
From: altusea 
Date: Wed, 4 Jun 2025 19:38:55 +0800
Subject: [PATCH 17/31] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20HttpClient5UploadAut?=
 =?UTF-8?q?hMaterialRequestExecutor=20=E7=B1=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 ...ent5UploadAuthMaterialRequestExecutor.java | 51 +++++++++++++++++++
 .../UploadAuthMaterialRequestExecutor.java    | 46 +++++++++--------
 2 files changed, 75 insertions(+), 22 deletions(-)
 create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5UploadAuthMaterialRequestExecutor.java

diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5UploadAuthMaterialRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5UploadAuthMaterialRequestExecutor.java
new file mode 100644
index 0000000000..09528f5c63
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5UploadAuthMaterialRequestExecutor.java
@@ -0,0 +1,51 @@
+package cn.binarywang.wx.miniapp.executor;
+
+import cn.binarywang.wx.miniapp.bean.WxMaUploadAuthMaterialResult;
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxError;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
+import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.core5.http.HttpEntity;
+import org.apache.hc.core5.http.HttpHost;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author altusea
+ */
+public class HttpClient5UploadAuthMaterialRequestExecutor extends UploadAuthMaterialRequestExecutor {
+
+  public HttpClient5UploadAuthMaterialRequestExecutor(RequestHttp requestHttp) {
+    super(requestHttp);
+  }
+
+  @Override
+  public WxMaUploadAuthMaterialResult execute(String uri, File file, WxType wxType) throws WxErrorException, IOException {
+    HttpPost httpPost = new HttpPost(uri);
+    if (requestHttp.getRequestHttpProxy() != null) {
+      RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
+      httpPost.setConfig(config);
+    }
+    if (file != null) {
+      HttpEntity entity = MultipartEntityBuilder
+        .create()
+        .addBinaryBody("media", file)
+        .setMode(HttpMultipartMode.EXTENDED)
+        .build();
+      httpPost.setEntity(entity);
+    }
+    String responseContent = requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
+    WxError error = WxError.fromJson(responseContent, wxType);
+    if (error.getErrorCode() != 0) {
+      throw new WxErrorException(error);
+    }
+    return WxMaUploadAuthMaterialResult.fromJson(responseContent);
+  }
+}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/UploadAuthMaterialRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/UploadAuthMaterialRequestExecutor.java
index 2013359814..a3dcad1d78 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/UploadAuthMaterialRequestExecutor.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/UploadAuthMaterialRequestExecutor.java
@@ -10,8 +10,6 @@
 import me.chanjar.weixin.common.util.http.ResponseHandler;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
 import okhttp3.OkHttpClient;
-import org.apache.http.HttpHost;
-import org.apache.http.impl.client.CloseableHttpClient;
 
 import java.io.File;
 import java.io.IOException;
@@ -25,28 +23,32 @@
  * @since 2024/01/07
  */
 public abstract class UploadAuthMaterialRequestExecutor implements RequestExecutor {
-    protected RequestHttp requestHttp;
+  protected RequestHttp requestHttp;
 
-    public UploadAuthMaterialRequestExecutor(RequestHttp requestHttp) {
-        this.requestHttp = requestHttp;
-    }
+  public UploadAuthMaterialRequestExecutor(RequestHttp requestHttp) {
+    this.requestHttp = requestHttp;
+  }
 
-    @Override
-    public void execute(String uri, File data, ResponseHandler handler, WxType wxType) throws WxErrorException, IOException {
-        handler.handle(this.execute(uri, data, wxType));
-    }
+  @Override
+  public void execute(String uri, File data, ResponseHandler handler, WxType wxType) throws WxErrorException, IOException {
+    handler.handle(this.execute(uri, data, wxType));
+  }
 
-    @SuppressWarnings("unchecked")
-    public static RequestExecutor create(RequestHttp requestHttp) {
-        switch (requestHttp.getRequestType()) {
-            case APACHE_HTTP:
-                return new ApacheUploadAuthMaterialRequestExecutor((RequestHttp) requestHttp);
-            case JODD_HTTP:
-                return new JoddHttpUploadAuthMaterialRequestExecutor((RequestHttp) requestHttp);
-            case OK_HTTP:
-                return new OkHttpUploadAuthMaterialRequestExecutor((RequestHttp) requestHttp);
-            default:
-                return null;
-        }
+  @SuppressWarnings("unchecked")
+  public static RequestExecutor create(RequestHttp requestHttp) {
+    switch (requestHttp.getRequestType()) {
+      case APACHE_HTTP:
+        return new ApacheUploadAuthMaterialRequestExecutor(
+          (RequestHttp) requestHttp);
+      case JODD_HTTP:
+        return new JoddHttpUploadAuthMaterialRequestExecutor((RequestHttp) requestHttp);
+      case OK_HTTP:
+        return new OkHttpUploadAuthMaterialRequestExecutor((RequestHttp) requestHttp);
+      case HTTP_CLIENT_5:
+        return new HttpClient5UploadAuthMaterialRequestExecutor(
+          (RequestHttp) requestHttp);
+      default:
+        return null;
     }
+  }
 }

From 0b4523cb66cb84a1787f5fb6e3ce36726de858c4 Mon Sep 17 00:00:00 2001
From: altusea 
Date: Wed, 4 Jun 2025 21:45:25 +0800
Subject: [PATCH 18/31] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20HttpClient5QrcodeFil?=
 =?UTF-8?q?eRequestExecutor=20=E7=B1=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../HttpClient5QrcodeFileRequestExecutor.java | 79 +++++++++++++++++++
 .../executor/QrcodeRequestExecutor.java       | 12 ++-
 2 files changed, 87 insertions(+), 4 deletions(-)
 create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5QrcodeFileRequestExecutor.java

diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5QrcodeFileRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5QrcodeFileRequestExecutor.java
new file mode 100644
index 0000000000..d11f41b361
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5QrcodeFileRequestExecutor.java
@@ -0,0 +1,79 @@
+package cn.binarywang.wx.miniapp.executor;
+
+import cn.binarywang.wx.miniapp.bean.AbstractWxMaQrcodeWrapper;
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxError;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.fs.FileUtils;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.hc5.InputStreamResponseHandler;
+import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.hc.client5.http.ClientProtocolException;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.io.entity.StringEntity;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Paths;
+import java.util.UUID;
+
+/**
+ * @author altusea
+ */
+public class HttpClient5QrcodeFileRequestExecutor extends QrcodeRequestExecutor {
+
+  private final String filePath;
+
+  public HttpClient5QrcodeFileRequestExecutor(RequestHttp requestHttp, String filePath) {
+    super(requestHttp);
+    this.filePath = filePath;
+  }
+
+  /**
+   * 执行http请求.
+   *
+   * @param uri           uri
+   * @param qrcodeWrapper 数据
+   * @param wxType        微信模块类型
+   * @return 响应结果
+   * @throws WxErrorException 自定义异常
+   * @throws IOException      io异常
+   */
+  @Override
+  public File execute(String uri, AbstractWxMaQrcodeWrapper qrcodeWrapper, WxType wxType) throws WxErrorException, IOException {
+    HttpPost httpPost = new HttpPost(uri);
+    if (requestHttp.getRequestHttpProxy() != null) {
+      httpPost.setConfig(
+        RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build()
+      );
+    }
+
+    httpPost.setEntity(new StringEntity(qrcodeWrapper.toJson(), ContentType.APPLICATION_JSON));
+
+    try (final CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpPost);
+         final InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response)) {
+      Header[] contentTypeHeader = response.getHeaders("Content-Type");
+      if (contentTypeHeader != null && contentTypeHeader.length > 0
+        && ContentType.APPLICATION_JSON.getMimeType()
+        .equals(ContentType.parse(contentTypeHeader[0].getValue()).getMimeType())) {
+        String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
+        throw new WxErrorException(WxError.fromJson(responseContent, wxType));
+      }
+      if (StringUtils.isBlank(filePath)) {
+        return FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), "jpg");
+      }
+      return FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), "jpg", Paths.get(filePath).toFile());
+    } catch (HttpException httpException) {
+      throw new ClientProtocolException(httpException.getMessage(), httpException);
+    }
+  }
+}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeRequestExecutor.java
index f581227f3e..9527b5ce50 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeRequestExecutor.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeRequestExecutor.java
@@ -33,10 +33,13 @@ public void execute(String uri, AbstractWxMaQrcodeWrapper data, ResponseHandler<
   public static RequestExecutor create(RequestHttp requestHttp, String path) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new ApacheQrcodeFileRequestExecutor((RequestHttp) requestHttp, path);
+        return new ApacheQrcodeFileRequestExecutor(
+          (RequestHttp) requestHttp, path);
       case OK_HTTP:
         return new OkHttpQrcodeFileRequestExecutor((RequestHttp) requestHttp, path);
-      case JODD_HTTP:
+      case HTTP_CLIENT_5:
+        return new HttpClient5QrcodeFileRequestExecutor(
+          (RequestHttp) requestHttp, path);
       default:
         return null;
     }
@@ -47,10 +50,11 @@ public static RequestExecutor create(RequestHtt
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
         return new ApacheQrcodeFileRequestExecutor((RequestHttp) requestHttp, null);
-      case JODD_HTTP:
-        return null;
       case OK_HTTP:
         return new OkHttpQrcodeFileRequestExecutor((RequestHttp) requestHttp, null);
+      case HTTP_CLIENT_5:
+        return new HttpClient5QrcodeFileRequestExecutor(
+          (RequestHttp) requestHttp, null);
       default:
         return null;
     }

From 44d8dc06098d598010ad8ac714adff47de846954 Mon Sep 17 00:00:00 2001
From: altusea 
Date: Wed, 4 Jun 2025 21:52:15 +0800
Subject: [PATCH 19/31] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20HttpClient5ApiSignat?=
 =?UTF-8?q?urePostRequestExecutor=20=E7=B1=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 ...ApacheApiSignaturePostRequestExecutor.java |  5 +-
 .../ApiSignaturePostRequestExecutor.java      |  6 +-
 ...lient5ApiSignaturePostRequestExecutor.java | 63 +++++++++++++++++++
 3 files changed, 69 insertions(+), 5 deletions(-)
 create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5ApiSignaturePostRequestExecutor.java

diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApacheApiSignaturePostRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApacheApiSignaturePostRequestExecutor.java
index da9e1a5ad2..3d85a412ec 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApacheApiSignaturePostRequestExecutor.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApacheApiSignaturePostRequestExecutor.java
@@ -20,10 +20,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
-public class ApacheApiSignaturePostRequestExecutor
-    extends ApiSignaturePostRequestExecutor {
-  private static final Logger logger =
-      LoggerFactory.getLogger(ApacheApiSignaturePostRequestExecutor.class);
+public class ApacheApiSignaturePostRequestExecutor extends ApiSignaturePostRequestExecutor {
 
   public ApacheApiSignaturePostRequestExecutor(RequestHttp requestHttp) {
     super(requestHttp);
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApiSignaturePostRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApiSignaturePostRequestExecutor.java
index 8a06f66a88..5a5d21d928 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApiSignaturePostRequestExecutor.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApiSignaturePostRequestExecutor.java
@@ -65,11 +65,15 @@ public WxMaApiResponse handleResponse(
   public static ApiSignaturePostRequestExecutor create(RequestHttp requestHttp) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new ApacheApiSignaturePostRequestExecutor((RequestHttp) requestHttp);
+        return new ApacheApiSignaturePostRequestExecutor(
+          (RequestHttp) requestHttp);
       case JODD_HTTP:
         return new JoddApiSignaturePostRequestExecutor((RequestHttp) requestHttp);
       case OK_HTTP:
         return new OkHttpApiSignaturePostRequestExecutor((RequestHttp) requestHttp);
+      case HTTP_CLIENT_5:
+        return new HttpClient5ApiSignaturePostRequestExecutor(
+          (RequestHttp) requestHttp);
       default:
         throw new IllegalArgumentException("非法请求参数");
     }
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5ApiSignaturePostRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5ApiSignaturePostRequestExecutor.java
new file mode 100644
index 0000000000..b86930f27c
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5ApiSignaturePostRequestExecutor.java
@@ -0,0 +1,63 @@
+package cn.binarywang.wx.miniapp.executor;
+
+import cn.binarywang.wx.miniapp.bean.WxMaApiResponse;
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import org.apache.hc.client5.http.ClientProtocolException;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.io.entity.StringEntity;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
+public class HttpClient5ApiSignaturePostRequestExecutor extends ApiSignaturePostRequestExecutor {
+
+  public HttpClient5ApiSignaturePostRequestExecutor(RequestHttp requestHttp) {
+    super(requestHttp);
+  }
+
+  @Override
+  public WxMaApiResponse execute(
+    String uri, Map headers, String postEntity, WxType wxType)
+    throws WxErrorException, IOException {
+    HttpPost httpPost = new HttpPost(uri);
+    if (requestHttp.getRequestHttpProxy() != null) {
+      RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
+      httpPost.setConfig(config);
+    }
+
+    if (headers != null) {
+      headers.forEach(httpPost::addHeader);
+    }
+
+    if (postEntity != null) {
+      StringEntity entity = new StringEntity(postEntity, ContentType.APPLICATION_JSON.withCharset(StandardCharsets.UTF_8));
+      httpPost.setEntity(entity);
+    }
+
+    try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpPost)) {
+      String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
+      Map respHeaders = new HashMap<>();
+      Header[] rHeaders = response.getHeaders();
+      if (rHeaders != null) {
+        for (Header h : rHeaders) {
+          respHeaders.putIfAbsent(h.getName(), h.getValue());
+        }
+      }
+      return this.handleResponse(wxType, responseContent, respHeaders);
+    } catch (HttpException httpException) {
+      throw new ClientProtocolException(httpException.getMessage(), httpException);
+    }
+  }
+}

From 216bf5aff215419507e286aae45b4abc0355c07b Mon Sep 17 00:00:00 2001
From: altusea 
Date: Fri, 6 Jun 2025 22:07:27 +0800
Subject: [PATCH 20/31] fix unit test

---
 .../weixin/common/util/http/HttpResponseProxyTest.java      | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/http/HttpResponseProxyTest.java b/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/http/HttpResponseProxyTest.java
index 69e723ea7c..1b20b98d74 100644
--- a/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/http/HttpResponseProxyTest.java
+++ b/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/http/HttpResponseProxyTest.java
@@ -8,12 +8,10 @@
 
 public class HttpResponseProxyTest {
 
-  public final ApacheHttpResponseProxy httpResponseProxy = new ApacheHttpResponseProxy(null);
-
   @Test
   public void testExtractFileNameFromContentString() throws WxErrorException {
     String content = "attachment; filename*=utf-8''%E6%B5%8B%E8%AF%95.xlsx; filename=\"��.xlsx\"";
-    String filename = httpResponseProxy.extractFileNameFromContentString(content);
+    String filename = HttpResponseProxy.extractFileNameFromContentString(content);
     assertNotNull(filename);
     assertEquals(filename, "测试.xlsx");
   }
@@ -22,7 +20,7 @@ public void testExtractFileNameFromContentString() throws WxErrorException {
   public void testExtractFileNameFromContentString_another() throws WxErrorException {
     String content = "attachment; filename*=utf-8''%E8%90%A5%E4%B8%9A%E6%89%A7%E7%85%A7.jpg; filename=\"����.jpg\"";
 //    String content = "attachment; filename=\"����.jpg\"";
-    String filename = httpResponseProxy.extractFileNameFromContentString(content);
+    String filename = HttpResponseProxy.extractFileNameFromContentString(content);
     assertNotNull(filename);
     assertEquals(filename, "营业执照.jpg");
   }

From 3b354cfddc96195dbdae2683746331beef19685b Mon Sep 17 00:00:00 2001
From: altusea 
Date: Fri, 6 Jun 2025 22:35:44 +0800
Subject: [PATCH 21/31] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20MaterialVideoInfoHtt?=
 =?UTF-8?q?pClient5RequestExecutor=20=E7=B1=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 ...alVideoInfoHttpClient5RequestExecutor.java | 44 +++++++++++++++++++
 .../MaterialVideoInfoRequestExecutor.java     | 13 +++---
 2 files changed, 51 insertions(+), 6 deletions(-)
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoHttpClient5RequestExecutor.java

diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoHttpClient5RequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoHttpClient5RequestExecutor.java
new file mode 100644
index 0000000000..7641e8fa3f
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoHttpClient5RequestExecutor.java
@@ -0,0 +1,44 @@
+package me.chanjar.weixin.mp.util.requestexecuter.material;
+
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxError;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import me.chanjar.weixin.common.util.json.WxGsonBuilder;
+import me.chanjar.weixin.mp.bean.material.WxMpMaterialVideoInfoResult;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.io.entity.StringEntity;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class MaterialVideoInfoHttpClient5RequestExecutor extends MaterialVideoInfoRequestExecutor {
+  public MaterialVideoInfoHttpClient5RequestExecutor(RequestHttp requestHttp) {
+    super(requestHttp);
+  }
+
+  @Override
+  public WxMpMaterialVideoInfoResult execute(String uri, String materialId, WxType wxType) throws WxErrorException, IOException {
+    HttpPost httpPost = new HttpPost(uri);
+    if (requestHttp.getRequestHttpProxy() != null) {
+      RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
+      httpPost.setConfig(config);
+    }
+
+    Map params = new HashMap<>();
+    params.put("media_id", materialId);
+    httpPost.setEntity(new StringEntity(WxGsonBuilder.create().toJson(params)));
+    String responseContent = requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
+    WxError error = WxError.fromJson(responseContent, WxType.MP);
+    if (error.getErrorCode() != 0) {
+      throw new WxErrorException(error);
+    } else {
+      return WxMpMaterialVideoInfoResult.fromJson(responseContent);
+    }
+  }
+}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoRequestExecutor.java
index d08baa4646..ac9d41f021 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoRequestExecutor.java
@@ -1,8 +1,5 @@
 package me.chanjar.weixin.mp.util.requestexecuter.material;
 
-
-import java.io.IOException;
-
 import jodd.http.HttpConnectionProvider;
 import jodd.http.ProxyInfo;
 import me.chanjar.weixin.common.enums.WxType;
@@ -13,8 +10,8 @@
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
 import me.chanjar.weixin.mp.bean.material.WxMpMaterialVideoInfoResult;
 import okhttp3.OkHttpClient;
-import org.apache.http.HttpHost;
-import org.apache.http.impl.client.CloseableHttpClient;
+
+import java.io.IOException;
 
 public abstract class MaterialVideoInfoRequestExecutor implements RequestExecutor {
   protected RequestHttp requestHttp;
@@ -32,11 +29,15 @@ public void execute(String uri, String data, ResponseHandler create(RequestHttp requestHttp) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new MaterialVideoInfoApacheHttpRequestExecutor((RequestHttp) requestHttp);
+        return new MaterialVideoInfoApacheHttpRequestExecutor(
+          (RequestHttp) requestHttp);
       case JODD_HTTP:
         return new MaterialVideoInfoJoddHttpRequestExecutor((RequestHttp) requestHttp);
       case OK_HTTP:
         return new MaterialVideoInfoOkhttpRequestExecutor((RequestHttp) requestHttp);
+      case HTTP_CLIENT_5:
+        return new MaterialVideoInfoHttpClient5RequestExecutor(
+          (RequestHttp) requestHttp);
       default:
         return null;
     }

From f9c45bb6181b85febe6d7dae5abfc7be6fbbca22 Mon Sep 17 00:00:00 2001
From: altusea 
Date: Fri, 6 Jun 2025 22:42:00 +0800
Subject: [PATCH 22/31] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20MaterialUploadHttpCl?=
 =?UTF-8?q?ient5RequestExecutor=20=E7=B1=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 ...erialUploadHttpClient5RequestExecutor.java | 67 +++++++++++++++++++
 .../MaterialUploadRequestExecutor.java        | 12 ++--
 2 files changed, 74 insertions(+), 5 deletions(-)
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadHttpClient5RequestExecutor.java

diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadHttpClient5RequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadHttpClient5RequestExecutor.java
new file mode 100644
index 0000000000..7fb73ab81f
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadHttpClient5RequestExecutor.java
@@ -0,0 +1,67 @@
+package me.chanjar.weixin.mp.util.requestexecuter.material;
+
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxError;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import me.chanjar.weixin.common.util.json.WxGsonBuilder;
+import me.chanjar.weixin.mp.bean.material.WxMpMaterial;
+import me.chanjar.weixin.mp.bean.material.WxMpMaterialUploadResult;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
+import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
+import org.apache.hc.client5.http.entity.mime.StringBody;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.HttpHost;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+
+public class MaterialUploadHttpClient5RequestExecutor extends MaterialUploadRequestExecutor {
+  public MaterialUploadHttpClient5RequestExecutor(RequestHttp requestHttp) {
+    super(requestHttp);
+  }
+
+  @Override
+  public WxMpMaterialUploadResult execute(String uri, WxMpMaterial material, WxType wxType) throws WxErrorException, IOException {
+    HttpPost httpPost = new HttpPost(uri);
+    if (requestHttp.getRequestHttpProxy() != null) {
+      RequestConfig response = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
+      httpPost.setConfig(response);
+    }
+
+    if (material == null) {
+      throw new WxErrorException("非法请求,material参数为空");
+    }
+
+    File file = material.getFile();
+    if (file == null || !file.exists()) {
+      throw new FileNotFoundException();
+    }
+
+    MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
+    multipartEntityBuilder
+      .addBinaryBody("media", file)
+      .setMode(HttpMultipartMode.EXTENDED);
+    Map form = material.getForm();
+    if (material.getForm() != null) {
+      multipartEntityBuilder.addPart("description",
+        new StringBody(WxGsonBuilder.create().toJson(form), ContentType.TEXT_PLAIN.withCharset(StandardCharsets.UTF_8)));
+    }
+    httpPost.setEntity(multipartEntityBuilder.build());
+
+    String responseContent = requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
+    WxError error = WxError.fromJson(responseContent, WxType.MP);
+    if (error.getErrorCode() != 0) {
+      throw new WxErrorException(error);
+    } else {
+      return WxMpMaterialUploadResult.fromJson(responseContent);
+    }
+  }
+}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadRequestExecutor.java
index e75677f8f4..1d7ef1947c 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadRequestExecutor.java
@@ -1,7 +1,5 @@
 package me.chanjar.weixin.mp.util.requestexecuter.material;
 
-import java.io.IOException;
-
 import jodd.http.HttpConnectionProvider;
 import jodd.http.ProxyInfo;
 import me.chanjar.weixin.common.enums.WxType;
@@ -13,8 +11,8 @@
 import me.chanjar.weixin.mp.bean.material.WxMpMaterial;
 import me.chanjar.weixin.mp.bean.material.WxMpMaterialUploadResult;
 import okhttp3.OkHttpClient;
-import org.apache.http.HttpHost;
-import org.apache.http.impl.client.CloseableHttpClient;
+
+import java.io.IOException;
 
 /**
  * @author codepiano
@@ -35,11 +33,15 @@ public void execute(String uri, WxMpMaterial data, ResponseHandler create(RequestHttp requestHttp) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new MaterialUploadApacheHttpRequestExecutor((RequestHttp) requestHttp);
+        return new MaterialUploadApacheHttpRequestExecutor(
+          (RequestHttp) requestHttp);
       case JODD_HTTP:
         return new MaterialUploadJoddHttpRequestExecutor((RequestHttp) requestHttp);
       case OK_HTTP:
         return new MaterialUploadOkhttpRequestExecutor((RequestHttp) requestHttp);
+      case HTTP_CLIENT_5:
+        return new MaterialUploadHttpClient5RequestExecutor(
+          (RequestHttp) requestHttp);
       default:
         return null;
     }

From 1e6d2a3ed0172d21bc5de2349f9c1c0cf1563dde Mon Sep 17 00:00:00 2001
From: altusea 
Date: Fri, 6 Jun 2025 22:45:08 +0800
Subject: [PATCH 23/31] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20MaterialDeleteHttpCl?=
 =?UTF-8?q?ient5RequestExecutor=20=E7=B1=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 ...erialDeleteHttpClient5RequestExecutor.java | 42 +++++++++++++++++++
 .../MaterialDeleteRequestExecutor.java        | 12 +++---
 2 files changed, 49 insertions(+), 5 deletions(-)
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialDeleteHttpClient5RequestExecutor.java

diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialDeleteHttpClient5RequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialDeleteHttpClient5RequestExecutor.java
new file mode 100644
index 0000000000..25245fb019
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialDeleteHttpClient5RequestExecutor.java
@@ -0,0 +1,42 @@
+package me.chanjar.weixin.mp.util.requestexecuter.material;
+
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxError;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import me.chanjar.weixin.common.util.json.WxGsonBuilder;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.io.entity.StringEntity;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class MaterialDeleteHttpClient5RequestExecutor extends MaterialDeleteRequestExecutor {
+  public MaterialDeleteHttpClient5RequestExecutor(RequestHttp requestHttp) {
+    super(requestHttp);
+  }
+
+  @Override
+  public Boolean execute(String uri, String materialId, WxType wxType) throws WxErrorException, IOException {
+    HttpPost httpPost = new HttpPost(uri);
+    if (requestHttp.getRequestHttpProxy() != null) {
+      RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
+      httpPost.setConfig(config);
+    }
+
+    Map params = new HashMap<>();
+    params.put("media_id", materialId);
+    httpPost.setEntity(new StringEntity(WxGsonBuilder.create().toJson(params)));
+    String responseContent = requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
+    WxError error = WxError.fromJson(responseContent, WxType.MP);
+    if (error.getErrorCode() != 0) {
+      throw new WxErrorException(error);
+    }
+    return true;
+  }
+}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialDeleteRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialDeleteRequestExecutor.java
index 5c2ab9ef5b..3f8eae8c83 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialDeleteRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialDeleteRequestExecutor.java
@@ -1,7 +1,5 @@
 package me.chanjar.weixin.mp.util.requestexecuter.material;
 
-import java.io.IOException;
-
 import jodd.http.HttpConnectionProvider;
 import jodd.http.ProxyInfo;
 import me.chanjar.weixin.common.enums.WxType;
@@ -11,8 +9,8 @@
 import me.chanjar.weixin.common.util.http.ResponseHandler;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
 import okhttp3.OkHttpClient;
-import org.apache.http.HttpHost;
-import org.apache.http.impl.client.CloseableHttpClient;
+
+import java.io.IOException;
 
 public abstract class MaterialDeleteRequestExecutor implements RequestExecutor {
   protected RequestHttp requestHttp;
@@ -30,11 +28,15 @@ public void execute(String uri, String data, ResponseHandler handler, W
   public static RequestExecutor create(RequestHttp requestHttp) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new MaterialDeleteApacheHttpRequestExecutor((RequestHttp) requestHttp);
+        return new MaterialDeleteApacheHttpRequestExecutor(
+          (RequestHttp) requestHttp);
       case JODD_HTTP:
         return new MaterialDeleteJoddHttpRequestExecutor((RequestHttp) requestHttp);
       case OK_HTTP:
         return new MaterialDeleteOkhttpRequestExecutor((RequestHttp) requestHttp);
+      case HTTP_CLIENT_5:
+        return new MaterialDeleteHttpClient5RequestExecutor(
+          (RequestHttp) requestHttp);
       default:
         return null;
     }

From 6460ceef88c5a03ee6e003225fa307270c257dff Mon Sep 17 00:00:00 2001
From: altusea 
Date: Fri, 6 Jun 2025 22:51:16 +0800
Subject: [PATCH 24/31] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20MaterialNewsInfoHttp?=
 =?UTF-8?q?Client5RequestExecutor=20=E7=B1=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 ...ialNewsInfoHttpClient5RequestExecutor.java | 46 +++++++++++++++++++
 .../MaterialNewsInfoRequestExecutor.java      |  6 ++-
 2 files changed, 51 insertions(+), 1 deletion(-)
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoHttpClient5RequestExecutor.java

diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoHttpClient5RequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoHttpClient5RequestExecutor.java
new file mode 100644
index 0000000000..1c16c55471
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoHttpClient5RequestExecutor.java
@@ -0,0 +1,46 @@
+package me.chanjar.weixin.mp.util.requestexecuter.material;
+
+import com.google.common.collect.ImmutableMap;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxError;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import me.chanjar.weixin.common.util.json.WxGsonBuilder;
+import me.chanjar.weixin.mp.bean.material.WxMpMaterialNews;
+import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.io.entity.StringEntity;
+
+import java.io.IOException;
+
+@Slf4j
+public class MaterialNewsInfoHttpClient5RequestExecutor extends MaterialNewsInfoRequestExecutor {
+
+  public MaterialNewsInfoHttpClient5RequestExecutor(RequestHttp requestHttp) {
+    super(requestHttp);
+  }
+
+  @Override
+  public WxMpMaterialNews execute(String uri, String materialId, WxType wxType) throws WxErrorException, IOException {
+    HttpPost httpPost = new HttpPost(uri);
+    if (requestHttp.getRequestHttpProxy() != null) {
+      RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
+      httpPost.setConfig(config);
+    }
+
+    httpPost.setEntity(new StringEntity(WxGsonBuilder.create().toJson(ImmutableMap.of("media_id", materialId))));
+    String responseContent = requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
+    log.debug("响应原始数据:{}", responseContent);
+    WxError error = WxError.fromJson(responseContent, WxType.MP);
+    if (error.getErrorCode() != 0) {
+      throw new WxErrorException(error);
+    } else {
+      return WxMpGsonBuilder.create().fromJson(responseContent, WxMpMaterialNews.class);
+    }
+  }
+}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoRequestExecutor.java
index d21cb9b50d..bc6e616f8f 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoRequestExecutor.java
@@ -31,11 +31,15 @@ public void execute(String uri, String data, ResponseHandler h
   public static RequestExecutor create(RequestHttp requestHttp) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new MaterialNewsInfoApacheHttpRequestExecutor((RequestHttp) requestHttp);
+        return new MaterialNewsInfoApacheHttpRequestExecutor(
+          (RequestHttp) requestHttp);
       case JODD_HTTP:
         return new MaterialNewsInfoJoddHttpRequestExecutor((RequestHttp) requestHttp);
       case OK_HTTP:
         return new MaterialNewsInfoOkhttpRequestExecutor((RequestHttp) requestHttp);
+        case HTTP_CLIENT_5:
+          return new MaterialNewsInfoHttpClient5RequestExecutor(
+            (RequestHttp) requestHttp);
       default:
         //TODO 需要优化抛出异常
         return null;

From ca16c39b30f37e46710ed2de454e61b8b2be5d37 Mon Sep 17 00:00:00 2001
From: altusea 
Date: Fri, 6 Jun 2025 22:56:10 +0800
Subject: [PATCH 25/31] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20MaterialVoiceAndImag?=
 =?UTF-8?q?eDownloadHttpClient5RequestExecutor=20=E7=B1=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 ...ageDownloadHttpClient5RequestExecutor.java | 63 +++++++++++++++++++
 ...lVoiceAndImageDownloadRequestExecutor.java |  6 +-
 2 files changed, 68 insertions(+), 1 deletion(-)
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadHttpClient5RequestExecutor.java

diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadHttpClient5RequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadHttpClient5RequestExecutor.java
new file mode 100644
index 0000000000..8caa089e09
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadHttpClient5RequestExecutor.java
@@ -0,0 +1,63 @@
+package me.chanjar.weixin.mp.util.requestexecuter.material;
+
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxError;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.hc5.InputStreamResponseHandler;
+import me.chanjar.weixin.common.util.json.WxGsonBuilder;
+import org.apache.commons.io.IOUtils;
+import org.apache.hc.client5.http.ClientProtocolException;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.io.entity.StringEntity;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
+public class MaterialVoiceAndImageDownloadHttpClient5RequestExecutor extends MaterialVoiceAndImageDownloadRequestExecutor {
+  public MaterialVoiceAndImageDownloadHttpClient5RequestExecutor(RequestHttp requestHttp, File tmpDirFile) {
+    super(requestHttp, tmpDirFile);
+  }
+
+  @Override
+  public InputStream execute(String uri, String materialId, WxType wxType) throws WxErrorException, IOException {
+    HttpPost httpPost = new HttpPost(uri);
+    if (requestHttp.getRequestHttpProxy() != null) {
+      RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
+      httpPost.setConfig(config);
+    }
+
+    Map params = new HashMap<>();
+    params.put("media_id", materialId);
+    httpPost.setEntity(new StringEntity(WxGsonBuilder.create().toJson(params)));
+    try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpPost);
+         InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response)) {
+      // 下载媒体文件出错
+      byte[] responseContent = IOUtils.toByteArray(inputStream);
+      String responseContentString = new String(responseContent, StandardCharsets.UTF_8);
+      if (responseContentString.length() <= 215) {
+        try {
+          WxError wxError = WxGsonBuilder.create().fromJson(responseContentString, WxError.class);
+          if (wxError.getErrorCode() != 0) {
+            throw new WxErrorException(wxError);
+          }
+        } catch (com.google.gson.JsonSyntaxException ex) {
+          return new ByteArrayInputStream(responseContent);
+        }
+      }
+      return new ByteArrayInputStream(responseContent);
+    } catch (HttpException httpException) {
+      throw new ClientProtocolException(httpException.getMessage(), httpException);
+    }
+  }
+}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadRequestExecutor.java
index 632acc6232..42e70afa3a 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadRequestExecutor.java
@@ -34,11 +34,15 @@ public void execute(String uri, String data, ResponseHandler handle
   public static RequestExecutor create(RequestHttp requestHttp, File tmpDirFile) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new MaterialVoiceAndImageDownloadApacheHttpRequestExecutor((RequestHttp) requestHttp, tmpDirFile);
+        return new MaterialVoiceAndImageDownloadApacheHttpRequestExecutor(
+          (RequestHttp) requestHttp, tmpDirFile);
       case JODD_HTTP:
         return new MaterialVoiceAndImageDownloadJoddHttpRequestExecutor((RequestHttp) requestHttp, tmpDirFile);
       case OK_HTTP:
         return new MaterialVoiceAndImageDownloadOkhttpRequestExecutor((RequestHttp) requestHttp, tmpDirFile);
+      case HTTP_CLIENT_5:
+        return new MaterialVoiceAndImageDownloadHttpClient5RequestExecutor(
+          (RequestHttp) requestHttp, tmpDirFile);
       default:
         return null;
     }

From 83200d797131a88024306c80087d8de1e054a4ea Mon Sep 17 00:00:00 2001
From: altusea 
Date: Fri, 6 Jun 2025 23:01:24 +0800
Subject: [PATCH 26/31] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20MediaImgUploadHttpCl?=
 =?UTF-8?q?ient5RequestExecutor=20=E7=B1=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 ...iaImgUploadHttpClient5RequestExecutor.java | 52 +++++++++++++++++++
 .../media/MediaImgUploadRequestExecutor.java  |  6 ++-
 2 files changed, 57 insertions(+), 1 deletion(-)
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadHttpClient5RequestExecutor.java

diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadHttpClient5RequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadHttpClient5RequestExecutor.java
new file mode 100644
index 0000000000..71ed71da8c
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadHttpClient5RequestExecutor.java
@@ -0,0 +1,52 @@
+package me.chanjar.weixin.mp.util.requestexecuter.media;
+
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxError;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
+import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.core5.http.HttpEntity;
+import org.apache.hc.core5.http.HttpHost;
+
+import java.io.File;
+import java.io.IOException;
+
+public class MediaImgUploadHttpClient5RequestExecutor extends MediaImgUploadRequestExecutor {
+  public MediaImgUploadHttpClient5RequestExecutor(RequestHttp requestHttp) {
+    super(requestHttp);
+  }
+
+  @Override
+  public WxMediaImgUploadResult execute(String uri, File data, WxType wxType) throws WxErrorException, IOException {
+    if (data == null) {
+      throw new WxErrorException("文件对象为空");
+    }
+
+    HttpPost httpPost = new HttpPost(uri);
+    if (requestHttp.getRequestHttpProxy() != null) {
+      RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
+      httpPost.setConfig(config);
+    }
+
+    HttpEntity entity = MultipartEntityBuilder
+      .create()
+      .addBinaryBody("media", data)
+      .setMode(HttpMultipartMode.EXTENDED)
+      .build();
+    httpPost.setEntity(entity);
+
+    String responseContent = requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
+    WxError error = WxError.fromJson(responseContent, WxType.MP);
+    if (error.getErrorCode() != 0) {
+      throw new WxErrorException(error);
+    }
+
+    return WxMediaImgUploadResult.fromJson(responseContent);
+  }
+}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadRequestExecutor.java
index 4d47a3ac6b..ec84906209 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadRequestExecutor.java
@@ -35,11 +35,15 @@ public void execute(String uri, File data, ResponseHandler create(RequestHttp requestHttp) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new MediaImgUploadApacheHttpRequestExecutor((RequestHttp) requestHttp);
+        return new MediaImgUploadApacheHttpRequestExecutor(
+          (RequestHttp) requestHttp);
       case JODD_HTTP:
         return new MediaImgUploadHttpRequestExecutor((RequestHttp) requestHttp);
       case OK_HTTP:
         return new MediaImgUploadOkhttpRequestExecutor((RequestHttp) requestHttp);
+      case HTTP_CLIENT_5:
+        return new MediaImgUploadHttpClient5RequestExecutor(
+          (RequestHttp) requestHttp);
       default:
         return null;
     }

From e505c48c296c702ce3c9ae681c56aeac3160372f Mon Sep 17 00:00:00 2001
From: altusea 
Date: Fri, 6 Jun 2025 23:07:19 +0800
Subject: [PATCH 27/31] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20VoiceUploadHttpClien?=
 =?UTF-8?q?t5RequestExecutor=20=E7=B1=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 ...VoiceUploadHttpClient5RequestExecutor.java | 50 +++++++++++++++++++
 .../voice/VoiceUploadRequestExecutor.java     |  7 ++-
 2 files changed, 55 insertions(+), 2 deletions(-)
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadHttpClient5RequestExecutor.java

diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadHttpClient5RequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadHttpClient5RequestExecutor.java
new file mode 100644
index 0000000000..6899ca4f0e
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadHttpClient5RequestExecutor.java
@@ -0,0 +1,50 @@
+package me.chanjar.weixin.mp.util.requestexecuter.voice;
+
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxError;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
+import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.core5.http.HttpEntity;
+import org.apache.hc.core5.http.HttpHost;
+
+import java.io.File;
+import java.io.IOException;
+
+public class VoiceUploadHttpClient5RequestExecutor extends VoiceUploadRequestExecutor {
+  public VoiceUploadHttpClient5RequestExecutor(RequestHttp requestHttp) {
+    super(requestHttp);
+  }
+
+  @Override
+  public Boolean execute(String uri, File data, WxType wxType) throws WxErrorException, IOException {
+    if (data == null) {
+      throw new WxErrorException("文件对象为空");
+    }
+
+    HttpPost httpPost = new HttpPost(uri);
+    if (requestHttp.getRequestHttpProxy() != null) {
+      RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
+      httpPost.setConfig(config);
+    }
+
+    HttpEntity entity = MultipartEntityBuilder
+      .create()
+      .addBinaryBody("media", data)
+      .setMode(HttpMultipartMode.EXTENDED)
+      .build();
+    httpPost.setEntity(entity);
+
+    String responseContent = requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
+    WxError error = WxError.fromJson(responseContent, WxType.MP);
+    if (error.getErrorCode() != 0) {
+      throw new WxErrorException(error);
+    }
+    return true;
+  }
+}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadRequestExecutor.java
index 747b89fe57..81794d31b4 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadRequestExecutor.java
@@ -34,8 +34,11 @@ public void execute(String uri, File data, ResponseHandler handler, WxT
   public static RequestExecutor create(RequestHttp requestHttp) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new VoiceUploadApacheHttpRequestExecutor((RequestHttp) requestHttp);
-      case JODD_HTTP:
+        return new VoiceUploadApacheHttpRequestExecutor(
+          (RequestHttp) requestHttp);
+      case HTTP_CLIENT_5:
+        return new VoiceUploadHttpClient5RequestExecutor(
+          (RequestHttp) requestHttp);
       case OK_HTTP:
       default:
         return null;

From fb2906f172342237e35f1a1992cd2de39fbabd66 Mon Sep 17 00:00:00 2001
From: altusea 
Date: Sat, 7 Jun 2025 10:19:05 +0800
Subject: [PATCH 28/31] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20CommonUploadRequestE?=
 =?UTF-8?q?xecutorHttpClient5Impl=20=E5=92=8C=20MaQrCodeHttpClient5Request?=
 =?UTF-8?q?Executor=20=E7=B1=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../executor/CommonUploadRequestExecutor.java | 18 +++--
 ...nUploadRequestExecutorHttpClient5Impl.java | 75 +++++++++++++++++++
 .../CommonUploadMultiRequestExecutor.java     | 18 +++--
 .../MaQrCodeHttpClient5RequestExecutor.java   | 65 ++++++++++++++++
 .../executor/MaQrCodeRequestExecutor.java     |  3 +
 .../WxPayOrderNotifyResultConverter.java      |  1 -
 6 files changed, 168 insertions(+), 12 deletions(-)
 create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorHttpClient5Impl.java
 create mode 100644 weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/MaQrCodeHttpClient5RequestExecutor.java

diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutor.java
index 2c9a4d7526..2f1138119f 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutor.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutor.java
@@ -1,11 +1,15 @@
 package me.chanjar.weixin.common.executor;
 
+import jodd.http.HttpConnectionProvider;
+import jodd.http.ProxyInfo;
 import me.chanjar.weixin.common.bean.CommonUploadParam;
 import me.chanjar.weixin.common.enums.WxType;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.RequestExecutor;
 import me.chanjar.weixin.common.util.http.RequestHttp;
 import me.chanjar.weixin.common.util.http.ResponseHandler;
+import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
+import okhttp3.OkHttpClient;
 
 import java.io.IOException;
 
@@ -34,15 +38,19 @@ public void execute(String uri, CommonUploadParam data, ResponseHandler
    * @param requestHttp 请求信息
    * @return 执行器
    */
-  @SuppressWarnings({"rawtypes", "unchecked"})
-  public static RequestExecutor create(RequestHttp requestHttp) {
+  @SuppressWarnings("unchecked")
+  public static RequestExecutor create(RequestHttp requestHttp) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new CommonUploadRequestExecutorApacheImpl(requestHttp);
+        return new CommonUploadRequestExecutorApacheImpl(
+          (RequestHttp) requestHttp);
       case JODD_HTTP:
-        return new CommonUploadRequestExecutorJoddHttpImpl(requestHttp);
+        return new CommonUploadRequestExecutorJoddHttpImpl((RequestHttp) requestHttp);
       case OK_HTTP:
-        return new CommonUploadRequestExecutorOkHttpImpl(requestHttp);
+        return new CommonUploadRequestExecutorOkHttpImpl((RequestHttp) requestHttp);
+      case HTTP_CLIENT_5:
+        return new CommonUploadRequestExecutorHttpClient5Impl(
+          (RequestHttp) requestHttp);
       default:
         throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorHttpClient5Impl.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorHttpClient5Impl.java
new file mode 100644
index 0000000000..4105a88c2d
--- /dev/null
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorHttpClient5Impl.java
@@ -0,0 +1,75 @@
+package me.chanjar.weixin.common.executor;
+
+import lombok.Getter;
+import me.chanjar.weixin.common.bean.CommonUploadData;
+import me.chanjar.weixin.common.bean.CommonUploadParam;
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxError;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
+import org.apache.hc.client5.http.entity.mime.InputStreamBody;
+import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.HttpEntity;
+import org.apache.hc.core5.http.HttpHost;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Apache HttpClient5 通用文件上传器
+ */
+public class CommonUploadRequestExecutorHttpClient5Impl extends CommonUploadRequestExecutor {
+
+  public CommonUploadRequestExecutorHttpClient5Impl(RequestHttp requestHttp) {
+    super(requestHttp);
+  }
+
+  @Override
+  public String execute(String uri, CommonUploadParam param, WxType wxType) throws WxErrorException, IOException {
+    HttpPost httpPost = new HttpPost(uri);
+    if (requestHttp.getRequestHttpProxy() != null) {
+      RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
+      httpPost.setConfig(config);
+    }
+    if (param != null) {
+      CommonUploadData data = param.getData();
+      InnerStreamBody part = new InnerStreamBody(data.getInputStream(), ContentType.DEFAULT_BINARY, data.getFileName(), data.getLength());
+      HttpEntity entity = MultipartEntityBuilder
+        .create()
+        .addPart(param.getName(), part)
+        .setMode(HttpMultipartMode.EXTENDED)
+        .build();
+      httpPost.setEntity(entity);
+    }
+    String responseContent = requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
+    if (StringUtils.isEmpty(responseContent)) {
+      throw new WxErrorException(String.format("上传失败,服务器响应空 url:%s param:%s", uri, param));
+    }
+    WxError error = WxError.fromJson(responseContent, wxType);
+    if (error.getErrorCode() != 0) {
+      throw new WxErrorException(error);
+    }
+    return responseContent;
+  }
+
+  /**
+   * 内部流 请求体
+   */
+  @Getter
+  public static class InnerStreamBody extends InputStreamBody {
+
+    private final long contentLength;
+
+    public InnerStreamBody(final InputStream in, final ContentType contentType, final String filename, long contentLength) {
+      super(in, contentType, filename);
+      this.contentLength = contentLength;
+    }
+  }
+}
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutor.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutor.java
index 4b623860e1..ba413b13f8 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutor.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutor.java
@@ -1,11 +1,15 @@
 package me.chanjar.weixin.open.executor;
 
+import jodd.http.HttpConnectionProvider;
+import jodd.http.ProxyInfo;
+import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
 import me.chanjar.weixin.open.bean.CommonUploadMultiParam;
 import me.chanjar.weixin.common.enums.WxType;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.RequestExecutor;
 import me.chanjar.weixin.common.util.http.RequestHttp;
 import me.chanjar.weixin.common.util.http.ResponseHandler;
+import okhttp3.OkHttpClient;
 
 import java.io.IOException;
 
@@ -33,17 +37,19 @@ public void execute(String uri, CommonUploadMultiParam data, ResponseHandler create(RequestHttp requestHttp) {
+  @SuppressWarnings("unchecked")
+  public static RequestExecutor create(RequestHttp requestHttp) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new CommonUploadMultiRequestExecutorApacheImpl(requestHttp);
+        return new CommonUploadMultiRequestExecutorApacheImpl(
+          (RequestHttp) requestHttp);
       case JODD_HTTP:
-        return new CommonUploadMultiRequestExecutorJoddHttpImpl(requestHttp);
+        return new CommonUploadMultiRequestExecutorJoddHttpImpl((RequestHttp) requestHttp);
       case OK_HTTP:
-        return new CommonUploadMultiRequestExecutorOkHttpImpl(requestHttp);
+        return new CommonUploadMultiRequestExecutorOkHttpImpl((RequestHttp) requestHttp);
       case HTTP_CLIENT_5:
-        return new CommonUploadMultiRequestExecutorHttpClient5Impl(requestHttp);
+        return new CommonUploadMultiRequestExecutorHttpClient5Impl(
+          (RequestHttp) requestHttp);
       default:
         throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/MaQrCodeHttpClient5RequestExecutor.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/MaQrCodeHttpClient5RequestExecutor.java
new file mode 100644
index 0000000000..d1fa0078c1
--- /dev/null
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/MaQrCodeHttpClient5RequestExecutor.java
@@ -0,0 +1,65 @@
+package me.chanjar.weixin.open.executor;
+
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxError;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.fs.FileUtils;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.hc5.InputStreamResponseHandler;
+import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import me.chanjar.weixin.open.bean.ma.WxMaQrcodeParam;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.hc.client5.http.ClientProtocolException;
+import org.apache.hc.client5.http.classic.methods.HttpGet;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpHost;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLEncoder;
+import java.util.UUID;
+
+public class MaQrCodeHttpClient5RequestExecutor extends MaQrCodeRequestExecutor {
+  public MaQrCodeHttpClient5RequestExecutor(RequestHttp requestHttp) {
+    super(requestHttp);
+  }
+
+  @Override
+  public File execute(String uri, WxMaQrcodeParam qrcodeParam, WxType wxType) throws WxErrorException, IOException {
+    if (qrcodeParam != null && StringUtils.isNotBlank(qrcodeParam.getPagePath())) {
+      if (uri.indexOf('?') == -1) {
+        uri += '?';
+      }
+      uri += uri.endsWith("?")
+        ? "path=" + URLEncoder.encode(qrcodeParam.getRequestPath(), "UTF-8")
+        : "&path=" + URLEncoder.encode(qrcodeParam.getRequestPath(), "UTF-8");
+    }
+
+    HttpGet httpGet = new HttpGet(uri);
+    if (requestHttp.getRequestHttpProxy() != null) {
+      RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
+      httpGet.setConfig(config);
+    }
+
+    try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpGet);
+         InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response);) {
+      Header[] contentTypeHeader = response.getHeaders("Content-Type");
+      if (contentTypeHeader != null && contentTypeHeader.length > 0) {
+        // 出错
+        if (ContentType.TEXT_PLAIN.getMimeType().equals(ContentType.parse(contentTypeHeader[0].getValue()).getMimeType())) {
+          String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
+          throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp));
+        }
+      }
+      return FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), "jpg");
+    } catch (HttpException httpException) {
+      throw new ClientProtocolException(httpException.getMessage(), httpException);
+    }
+  }
+}
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/MaQrCodeRequestExecutor.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/MaQrCodeRequestExecutor.java
index 89801a3684..103a73d2e1 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/MaQrCodeRequestExecutor.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/MaQrCodeRequestExecutor.java
@@ -43,6 +43,9 @@ public static RequestExecutor create(RequestHttp re
         return new MaQrCodeJoddHttpRequestExecutor((RequestHttp) requestHttp);
       case OK_HTTP:
         return new MaQrCodeOkhttpRequestExecutor((RequestHttp) requestHttp);
+      case HTTP_CLIENT_5:
+        return new MaQrCodeHttpClient5RequestExecutor(
+          (RequestHttp) requestHttp);
       default:
         throw new WxErrorException("不支持的http框架");
     }
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/converter/WxPayOrderNotifyResultConverter.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/converter/WxPayOrderNotifyResultConverter.java
index 0f01358633..e3e28e9183 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/converter/WxPayOrderNotifyResultConverter.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/converter/WxPayOrderNotifyResultConverter.java
@@ -39,7 +39,6 @@ public WxPayOrderNotifyResultConverter(Mapper mapper, ReflectionProvider reflect
   }
 
   @Override
-  @SuppressWarnings("rawtypes")
   public boolean canConvert(Class type) {
     return type.equals(WxPayOrderNotifyResult.class);
   }

From 7eda22e65e1c2db3a2ac774da4d527693bff8785 Mon Sep 17 00:00:00 2001
From: altusea 
Date: Sat, 7 Jun 2025 10:45:21 +0800
Subject: [PATCH 29/31] =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../AbstractWxChannelConfiguration.java       |  6 +--
 .../wxjava/channel/enums/HttpClientType.java  |  4 +-
 .../services/AbstractWxCpConfiguration.java   |  4 +-
 .../properties/WxCpMultiProperties.java       |  4 +-
 .../services/AbstractWxMpConfiguration.java   |  4 +-
 .../mp/properties/WxMpMultiProperties.java    |  4 +-
 ...> WxChannelServiceHttpComponentsImpl.java} | 17 +++---
 ...eHttpChannelFileUploadRequestExecutor.java | 47 +++++++++++++++++
 .../ChannelFileUploadRequestExecutor.java     | 52 ++++---------------
 ...nentsChannelFileUploadRequestExecutor.java | 47 +++++++++++++++++
 .../executor/CommonUploadRequestExecutor.java |  4 +-
 ...CommonUploadRequestExecutorApacheImpl.java |  3 +-
 ...oadRequestExecutorHttpComponentsImpl.java} |  8 +--
 .../common/util/http/HttpClientType.java      |  4 +-
 .../common/util/http/HttpResponseProxy.java   |  6 +--
 .../util/http/MediaUploadRequestExecutor.java | 12 +++--
 .../http/MinishopUploadRequestExecutor.java   | 11 ++--
 .../util/http/hc/BasicResponseHandler.java    | 14 +++++
 .../{hc5 => hc}/ByteArrayResponseHandler.java |  2 +-
 .../DefaultHttpComponentsClientBuilder.java}  | 24 +++++----
 .../http/hc/HttpComponentsClientBuilder.java  | 51 ++++++++++++++++++
 ...mponentsMediaDownloadRequestExecutor.java} |  6 +--
 ...ediaInputStreamUploadRequestExecutor.java} |  6 +--
 ...ComponentsMediaUploadRequestExecutor.java} |  6 +--
 ...pMediaUploadRequestCustomizeExecutor.java} |  6 +--
 ...tsMinishopMediaUploadRequestExecutor.java} |  6 +--
 .../HttpComponentsResponseProxy.java}         |  6 +--
 ...tpComponentsSimpleGetRequestExecutor.java} |  6 +--
 ...pComponentsSimplePostRequestExecutor.java} |  6 +--
 .../InputStreamResponseHandler.java           |  2 +-
 .../http/{hc5 => hc}/NoopRetryStrategy.java   |  2 +-
 .../http/{hc5 => hc}/Utf8ResponseHandler.java |  2 +-
 .../http/hc5/ApacheBasicResponseHandler.java  | 14 -----
 .../http/hc5/ApacheHttpClientBuilder.java     | 50 ------------------
 ...ava => WxCpServiceHttpComponentsImpl.java} | 14 ++---
 ...a => WxCpCgServiceHttpComponentsImpl.java} | 10 ++--
 ...a => WxCpTpServiceHttpComponentsImpl.java} | 14 ++---
 .../ApiSignaturePostRequestExecutor.java      |  6 +--
 ...nentsApiSignaturePostRequestExecutor.java} |  6 +--
 ...ComponentsQrcodeBytesRequestExecutor.java} |  9 ++--
 ...pComponentsQrcodeFileRequestExecutor.java} |  8 +--
 ...ntsUploadAuthMaterialRequestExecutor.java} |  6 +--
 .../executor/QrcodeBytesRequestExecutor.java  |  4 +-
 .../executor/QrcodeRequestExecutor.java       |  8 +--
 .../UploadAuthMaterialRequestExecutor.java    |  4 +-
 ...ava => WxMpServiceHttpComponentsImpl.java} | 16 +++---
 ...lDeleteHttpComponentsRequestExecutor.java} |  6 +--
 .../MaterialDeleteRequestExecutor.java        |  4 +-
 ...ewsInfoHttpComponentsRequestExecutor.java} |  6 +--
 .../MaterialNewsInfoRequestExecutor.java      |  6 +--
 ...lUploadHttpComponentsRequestExecutor.java} |  6 +--
 .../MaterialUploadRequestExecutor.java        |  4 +-
 ...deoInfoHttpComponentsRequestExecutor.java} |  6 +--
 .../MaterialVideoInfoRequestExecutor.java     |  4 +-
 ...ownloadHttpComponentsRequestExecutor.java} |  7 +--
 ...lVoiceAndImageDownloadRequestExecutor.java |  6 +--
 ...gUploadHttpComponentsRequestExecutor.java} |  6 +--
 .../media/MediaImgUploadRequestExecutor.java  |  6 +--
 ... QrCodeHttpComponentsRequestExecutor.java} |  8 +--
 .../qrcode/QrCodeRequestExecutor.java         | 10 ++--
 ...eUploadHttpComponentsRequestExecutor.java} |  6 +--
 .../voice/VoiceUploadRequestExecutor.java     |  6 +--
 .../CommonUploadMultiRequestExecutor.java     |  4 +-
 ...ltiRequestExecutorHttpComponentsImpl.java} |  6 +--
 ...aQrCodeHttpComponentsRequestExecutor.java} |  8 +--
 .../executor/MaQrCodeRequestExecutor.java     | 13 +++--
 ...va => WxPayServiceHttpComponentsImpl.java} |  4 +-
 ...=> WxQidianServiceHttpComponentsImpl.java} | 14 ++---
 68 files changed, 378 insertions(+), 319 deletions(-)
 rename weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/{WxChannelServiceHttpClient5Impl.java => WxChannelServiceHttpComponentsImpl.java} (83%)
 create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/ApacheHttpChannelFileUploadRequestExecutor.java
 create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/HttpComponentsChannelFileUploadRequestExecutor.java
 rename weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/{CommonUploadRequestExecutorHttpClient5Impl.java => CommonUploadRequestExecutorHttpComponentsImpl.java} (88%)
 create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/BasicResponseHandler.java
 rename weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/{hc5 => hc}/ByteArrayResponseHandler.java (92%)
 rename weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/{hc5/DefaultApacheHttpClientBuilder.java => hc/DefaultHttpComponentsClientBuilder.java} (87%)
 create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsClientBuilder.java
 rename weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/{hc5/ApacheMediaDownloadRequestExecutor.java => hc/HttpComponentsMediaDownloadRequestExecutor.java} (90%)
 rename weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/{hc5/ApacheMediaInputStreamUploadRequestExecutor.java => hc/HttpComponentsMediaInputStreamUploadRequestExecutor.java} (86%)
 rename weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/{hc5/ApacheMediaUploadRequestExecutor.java => hc/HttpComponentsMediaUploadRequestExecutor.java} (86%)
 rename weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/{hc5/ApacheMinishopMediaUploadRequestCustomizeExecutor.java => hc/HttpComponentsMinishopMediaUploadRequestCustomizeExecutor.java} (88%)
 rename weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/{hc5/ApacheMinishopMediaUploadRequestExecutor.java => hc/HttpComponentsMinishopMediaUploadRequestExecutor.java} (86%)
 rename weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/{hc5/ApacheHttpClient5ResponseProxy.java => hc/HttpComponentsResponseProxy.java} (78%)
 rename weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/{hc5/ApacheSimpleGetRequestExecutor.java => hc/HttpComponentsSimpleGetRequestExecutor.java} (82%)
 rename weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/{hc5/ApacheSimplePostRequestExecutor.java => hc/HttpComponentsSimplePostRequestExecutor.java} (84%)
 rename weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/{hc5 => hc}/InputStreamResponseHandler.java (92%)
 rename weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/{hc5 => hc}/NoopRetryStrategy.java (95%)
 rename weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/{hc5 => hc}/Utf8ResponseHandler.java (95%)
 delete mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheBasicResponseHandler.java
 delete mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheHttpClientBuilder.java
 rename weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/{WxCpServiceHttpClient5Impl.java => WxCpServiceHttpComponentsImpl.java} (85%)
 rename weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/impl/{WxCpCgServiceHttpClient5Impl.java => WxCpCgServiceHttpComponentsImpl.java} (74%)
 rename weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/{WxCpTpServiceHttpClient5Impl.java => WxCpTpServiceHttpComponentsImpl.java} (87%)
 rename weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/{HttpClient5ApiSignaturePostRequestExecutor.java => HttpComponentsApiSignaturePostRequestExecutor.java} (87%)
 rename weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/{HttpClient5QrcodeBytesRequestExecutor.java => HttpComponentsQrcodeBytesRequestExecutor.java} (87%)
 rename weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/{HttpClient5QrcodeFileRequestExecutor.java => HttpComponentsQrcodeFileRequestExecutor.java} (88%)
 rename weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/{HttpClient5UploadAuthMaterialRequestExecutor.java => HttpComponentsUploadAuthMaterialRequestExecutor.java} (84%)
 rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/{WxMpServiceHttpClient5Impl.java => WxMpServiceHttpComponentsImpl.java} (83%)
 rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/{MaterialDeleteHttpClient5RequestExecutor.java => MaterialDeleteHttpComponentsRequestExecutor.java} (83%)
 rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/{MaterialNewsInfoHttpClient5RequestExecutor.java => MaterialNewsInfoHttpComponentsRequestExecutor.java} (85%)
 rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/{MaterialUploadHttpClient5RequestExecutor.java => MaterialUploadHttpComponentsRequestExecutor.java} (89%)
 rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/{MaterialVideoInfoHttpClient5RequestExecutor.java => MaterialVideoInfoHttpComponentsRequestExecutor.java} (84%)
 rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/{MaterialVoiceAndImageDownloadHttpClient5RequestExecutor.java => MaterialVoiceAndImageDownloadHttpComponentsRequestExecutor.java} (87%)
 rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/{MediaImgUploadHttpClient5RequestExecutor.java => MediaImgUploadHttpComponentsRequestExecutor.java} (85%)
 rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/{QrCodeHttpClient5RequestExecutor.java => QrCodeHttpComponentsRequestExecutor.java} (87%)
 rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/{VoiceUploadHttpClient5RequestExecutor.java => VoiceUploadHttpComponentsRequestExecutor.java} (84%)
 rename weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/{CommonUploadMultiRequestExecutorHttpClient5Impl.java => CommonUploadMultiRequestExecutorHttpComponentsImpl.java} (91%)
 rename weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/{MaQrCodeHttpClient5RequestExecutor.java => MaQrCodeHttpComponentsRequestExecutor.java} (88%)
 rename weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/{WxPayServiceHttpClient5Impl.java => WxPayServiceHttpComponentsImpl.java} (99%)
 rename weixin-java-qidian/src/main/java/me/chanjar/weixin/qidian/api/impl/{WxQidianServiceHttpClient5Impl.java => WxQidianServiceHttpComponentsImpl.java} (85%)

diff --git a/solon-plugins/wx-java-channel-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/channel/configuration/services/AbstractWxChannelConfiguration.java b/solon-plugins/wx-java-channel-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/channel/configuration/services/AbstractWxChannelConfiguration.java
index 0032ecd41e..eb80b5f7f3 100644
--- a/solon-plugins/wx-java-channel-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/channel/configuration/services/AbstractWxChannelConfiguration.java
+++ b/solon-plugins/wx-java-channel-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/channel/configuration/services/AbstractWxChannelConfiguration.java
@@ -8,7 +8,7 @@
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.channel.api.WxChannelService;
-import me.chanjar.weixin.channel.api.impl.WxChannelServiceHttpClient5Impl;
+import me.chanjar.weixin.channel.api.impl.WxChannelServiceHttpComponentsImpl;
 import me.chanjar.weixin.channel.api.impl.WxChannelServiceHttpClientImpl;
 import me.chanjar.weixin.channel.api.impl.WxChannelServiceImpl;
 import me.chanjar.weixin.channel.config.WxChannelConfig;
@@ -85,8 +85,8 @@ public WxChannelService wxChannelService(WxChannelConfig wxChannelConfig, WxChan
       case HTTP_CLIENT:
         wxChannelService = new WxChannelServiceHttpClientImpl();
         break;
-      case HTTP_CLIENT_5:
-        wxChannelService = new WxChannelServiceHttpClient5Impl();
+      case HTTP_COMPONENTS:
+        wxChannelService = new WxChannelServiceHttpComponentsImpl();
         break;
       default:
         wxChannelService = new WxChannelServiceImpl();
diff --git a/solon-plugins/wx-java-channel-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/channel/enums/HttpClientType.java b/solon-plugins/wx-java-channel-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/channel/enums/HttpClientType.java
index 2bf6da63ef..c34533c6d1 100644
--- a/solon-plugins/wx-java-channel-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/channel/enums/HttpClientType.java
+++ b/solon-plugins/wx-java-channel-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/channel/enums/HttpClientType.java
@@ -12,9 +12,9 @@ public enum HttpClientType {
    */
   HTTP_CLIENT,
   /**
-   * HttpClient5
+   * HttpComponents
    */
-  HTTP_CLIENT_5
+  HTTP_COMPONENTS
   // WxChannelServiceOkHttpImpl 实现经测试无法正常完成业务固暂不支持OK_HTTP方式
 //  /**
 //   * OkHttp.
diff --git a/solon-plugins/wx-java-cp-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/cp_multi/configuration/services/AbstractWxCpConfiguration.java b/solon-plugins/wx-java-cp-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/cp_multi/configuration/services/AbstractWxCpConfiguration.java
index d88a8f42b0..ada4ac504c 100644
--- a/solon-plugins/wx-java-cp-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/cp_multi/configuration/services/AbstractWxCpConfiguration.java
+++ b/solon-plugins/wx-java-cp-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/cp_multi/configuration/services/AbstractWxCpConfiguration.java
@@ -93,8 +93,8 @@ private WxCpService wxCpService(WxCpConfigStorage wxCpConfigStorage, WxCpMultiPr
       case HTTP_CLIENT:
         wxCpService = new WxCpServiceApacheHttpClientImpl();
         break;
-      case HTTP_CLIENT_5:
-        wxCpService = new WxCpServiceHttpClient5Impl();
+      case HTTP_COMPONENTS:
+        wxCpService = new WxCpServiceHttpComponentsImpl();
         break;
       default:
         wxCpService = new WxCpServiceImpl();
diff --git a/solon-plugins/wx-java-cp-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/cp_multi/properties/WxCpMultiProperties.java b/solon-plugins/wx-java-cp-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/cp_multi/properties/WxCpMultiProperties.java
index c89ef8486f..821f885f98 100644
--- a/solon-plugins/wx-java-cp-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/cp_multi/properties/WxCpMultiProperties.java
+++ b/solon-plugins/wx-java-cp-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/cp_multi/properties/WxCpMultiProperties.java
@@ -118,9 +118,9 @@ public enum HttpClientType {
      */
     HTTP_CLIENT,
     /**
-     * HttpClient5
+     * HttpComponents
      */
-    HTTP_CLIENT_5,
+    HTTP_COMPONENTS,
     /**
      * OkHttp
      */
diff --git a/spring-boot-starters/wx-java-mp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/configuration/services/AbstractWxMpConfiguration.java b/spring-boot-starters/wx-java-mp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/configuration/services/AbstractWxMpConfiguration.java
index ece0956171..1f431b645d 100644
--- a/spring-boot-starters/wx-java-mp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/configuration/services/AbstractWxMpConfiguration.java
+++ b/spring-boot-starters/wx-java-mp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/configuration/services/AbstractWxMpConfiguration.java
@@ -88,8 +88,8 @@ public WxMpService wxMpService(WxMpConfigStorage configStorage, WxMpMultiPropert
       case HTTP_CLIENT:
         wxMpService = new WxMpServiceHttpClientImpl();
         break;
-      case HTTP_CLIENT_5:
-        wxMpService = new WxMpServiceHttpClient5Impl();
+      case HTTP_COMPONENTS:
+        wxMpService = new WxMpServiceHttpComponentsImpl();
         break;
       default:
         wxMpService = new WxMpServiceImpl();
diff --git a/spring-boot-starters/wx-java-mp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/properties/WxMpMultiProperties.java b/spring-boot-starters/wx-java-mp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/properties/WxMpMultiProperties.java
index 668af31a13..8b2fa58aa3 100644
--- a/spring-boot-starters/wx-java-mp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/properties/WxMpMultiProperties.java
+++ b/spring-boot-starters/wx-java-mp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/properties/WxMpMultiProperties.java
@@ -143,9 +143,9 @@ public enum HttpClientType {
      */
     HTTP_CLIENT,
     /**
-     * HttpClient5
+     * HttpComponents
      */
-    HTTP_CLIENT_5,
+    HTTP_COMPONENTS,
     /**
      * OkHttp
      */
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelServiceHttpClient5Impl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelServiceHttpComponentsImpl.java
similarity index 83%
rename from weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelServiceHttpClient5Impl.java
rename to weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelServiceHttpComponentsImpl.java
index 1764d772e9..6cf2d38503 100644
--- a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelServiceHttpClient5Impl.java
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelServiceHttpComponentsImpl.java
@@ -5,9 +5,10 @@
 import me.chanjar.weixin.channel.config.WxChannelConfig;
 import me.chanjar.weixin.channel.util.JsonUtils;
 import me.chanjar.weixin.common.util.http.HttpClientType;
-import me.chanjar.weixin.common.util.http.hc5.ApacheBasicResponseHandler;
-import me.chanjar.weixin.common.util.http.hc5.ApacheHttpClientBuilder;
-import me.chanjar.weixin.common.util.http.hc5.DefaultApacheHttpClientBuilder;
+import me.chanjar.weixin.common.util.http.apache.ApacheBasicResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.BasicResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.DefaultHttpComponentsClientBuilder;
+import me.chanjar.weixin.common.util.http.hc.HttpComponentsClientBuilder;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.hc.client5.http.classic.HttpClient;
 import org.apache.hc.client5.http.classic.methods.HttpGet;
@@ -27,7 +28,7 @@
  * @author altusea
  */
 @Slf4j
-public class WxChannelServiceHttpClient5Impl extends BaseWxChannelServiceImpl {
+public class WxChannelServiceHttpComponentsImpl extends BaseWxChannelServiceImpl {
 
   private CloseableHttpClient httpClient;
   private HttpHost httpProxy;
@@ -35,7 +36,7 @@ public class WxChannelServiceHttpClient5Impl extends BaseWxChannelServiceImpl {
+  public ApacheHttpChannelFileUploadRequestExecutor(RequestHttp requestHttp) {
+    super(requestHttp);
+  }
+
+  @Override
+  public String execute(String uri, File file, WxType wxType) throws WxErrorException, IOException {
+    HttpPost httpPost = new HttpPost(uri);
+    if (requestHttp.getRequestHttpProxy() != null) {
+      RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
+      httpPost.setConfig(config);
+    }
+    if (file != null) {
+      HttpEntity entity = MultipartEntityBuilder
+        .create()
+        .addBinaryBody("media", file)
+        .setMode(HttpMultipartMode.RFC6532)
+        .build();
+      httpPost.setEntity(entity);
+    }
+    return requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
+  }
+
+  @Override
+  public void execute(String uri, File data, ResponseHandler handler, WxType wxType)
+    throws WxErrorException, IOException {
+    handler.handle(this.execute(uri, data, wxType));
+  }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/ChannelFileUploadRequestExecutor.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/ChannelFileUploadRequestExecutor.java
index d171be2361..78a6735192 100644
--- a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/ChannelFileUploadRequestExecutor.java
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/ChannelFileUploadRequestExecutor.java
@@ -1,66 +1,34 @@
 package me.chanjar.weixin.channel.executor;
 
-import me.chanjar.weixin.common.enums.WxType;
-import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.RequestExecutor;
 import me.chanjar.weixin.common.util.http.RequestHttp;
-import me.chanjar.weixin.common.util.http.ResponseHandler;
-import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpHost;
-import org.apache.http.client.config.RequestConfig;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.entity.mime.HttpMultipartMode;
-import org.apache.http.entity.mime.MultipartEntityBuilder;
-import org.apache.http.impl.client.CloseableHttpClient;
 
 import java.io.File;
-import java.io.IOException;
 
 /**
  * 视频号小店 图片上传接口 请求的参数是File, 返回的结果是String
  *
  * @author Zeyes
  */
-public class ChannelFileUploadRequestExecutor implements RequestExecutor {
+public abstract class ChannelFileUploadRequestExecutor implements RequestExecutor {
 
-  protected RequestHttp requestHttp;
+  protected RequestHttp requestHttp;
 
-  public ChannelFileUploadRequestExecutor(RequestHttp requestHttp) {
+  public ChannelFileUploadRequestExecutor(RequestHttp requestHttp) {
     this.requestHttp = requestHttp;
   }
 
-  @Override
-  public String execute(String uri, File file, WxType wxType) throws WxErrorException, IOException {
-    HttpPost httpPost = new HttpPost(uri);
-    if (requestHttp.getRequestHttpProxy() != null) {
-      RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
-      httpPost.setConfig(config);
-    }
-    if (file != null) {
-      HttpEntity entity = MultipartEntityBuilder
-        .create()
-        .addBinaryBody("media", file)
-        .setMode(HttpMultipartMode.RFC6532)
-        .build();
-      httpPost.setEntity(entity);
-    }
-    return requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
-  }
-
-  @Override
-  public void execute(String uri, File data, ResponseHandler handler, WxType wxType)
-    throws WxErrorException, IOException {
-    handler.handle(this.execute(uri, data, wxType));
-  }
-
   @SuppressWarnings("unchecked")
-  public static RequestExecutor create(RequestHttp requestHttp) throws WxErrorException {
+  public static RequestExecutor create(RequestHttp requestHttp) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new ChannelFileUploadRequestExecutor((RequestHttp) requestHttp);
+        return new ApacheHttpChannelFileUploadRequestExecutor(
+          (RequestHttp) requestHttp);
+      case HTTP_COMPONENTS:
+        return new HttpComponentsChannelFileUploadRequestExecutor(
+          (RequestHttp) requestHttp);
       default:
-        throw new WxErrorException("不支持的http框架");
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/HttpComponentsChannelFileUploadRequestExecutor.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/HttpComponentsChannelFileUploadRequestExecutor.java
new file mode 100644
index 0000000000..3b1e7076a9
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/HttpComponentsChannelFileUploadRequestExecutor.java
@@ -0,0 +1,47 @@
+package me.chanjar.weixin.channel.executor;
+
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.ResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.Utf8ResponseHandler;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
+import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.core5.http.HttpEntity;
+import org.apache.hc.core5.http.HttpHost;
+
+import java.io.File;
+import java.io.IOException;
+
+public class HttpComponentsChannelFileUploadRequestExecutor extends ChannelFileUploadRequestExecutor {
+  public HttpComponentsChannelFileUploadRequestExecutor(RequestHttp requestHttp) {
+    super(requestHttp);
+  }
+
+  @Override
+  public String execute(String uri, File file, WxType wxType) throws WxErrorException, IOException {
+    HttpPost httpPost = new HttpPost(uri);
+    if (requestHttp.getRequestHttpProxy() != null) {
+      RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
+      httpPost.setConfig(config);
+    }
+    if (file != null) {
+      HttpEntity entity = MultipartEntityBuilder
+        .create()
+        .addBinaryBody("media", file)
+        .setMode(HttpMultipartMode.EXTENDED)
+        .build();
+      httpPost.setEntity(entity);
+    }
+    return requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
+  }
+
+  @Override
+  public void execute(String uri, File data, ResponseHandler handler, WxType wxType)
+    throws WxErrorException, IOException {
+    handler.handle(this.execute(uri, data, wxType));
+  }
+}
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutor.java
index 2f1138119f..a93cbe1e99 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutor.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutor.java
@@ -48,8 +48,8 @@ public static RequestExecutor create(RequestHttp) requestHttp);
       case OK_HTTP:
         return new CommonUploadRequestExecutorOkHttpImpl((RequestHttp) requestHttp);
-      case HTTP_CLIENT_5:
-        return new CommonUploadRequestExecutorHttpClient5Impl(
+      case HTTP_COMPONENTS:
+        return new CommonUploadRequestExecutorHttpComponentsImpl(
           (RequestHttp) requestHttp);
       default:
         throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorApacheImpl.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorApacheImpl.java
index f37cb805da..7f19241cdb 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorApacheImpl.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorApacheImpl.java
@@ -28,8 +28,7 @@
  * @author 广州跨界
  * created on  2024/01/11
  */
-public class CommonUploadRequestExecutorApacheImpl
-  extends CommonUploadRequestExecutor {
+public class CommonUploadRequestExecutorApacheImpl extends CommonUploadRequestExecutor {
 
   public CommonUploadRequestExecutorApacheImpl(RequestHttp requestHttp) {
     super(requestHttp);
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorHttpClient5Impl.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorHttpComponentsImpl.java
similarity index 88%
rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorHttpClient5Impl.java
rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorHttpComponentsImpl.java
index 4105a88c2d..f79eaa49b8 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorHttpClient5Impl.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorHttpComponentsImpl.java
@@ -7,7 +7,7 @@
 import me.chanjar.weixin.common.error.WxError;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.RequestHttp;
-import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.Utf8ResponseHandler;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.hc.client5.http.classic.methods.HttpPost;
 import org.apache.hc.client5.http.config.RequestConfig;
@@ -23,11 +23,11 @@
 import java.io.InputStream;
 
 /**
- * Apache HttpClient5 通用文件上传器
+ * Apache HttpComponents 通用文件上传器
  */
-public class CommonUploadRequestExecutorHttpClient5Impl extends CommonUploadRequestExecutor {
+public class CommonUploadRequestExecutorHttpComponentsImpl extends CommonUploadRequestExecutor {
 
-  public CommonUploadRequestExecutorHttpClient5Impl(RequestHttp requestHttp) {
+  public CommonUploadRequestExecutorHttpComponentsImpl(RequestHttp requestHttp) {
     super(requestHttp);
   }
 
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpClientType.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpClientType.java
index 3c21add2e8..f309d0d852 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpClientType.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpClientType.java
@@ -17,7 +17,7 @@ public enum HttpClientType {
    */
   OK_HTTP,
   /**
-   * apache httpclient5.
+   * apache httpclient 5.x.
    */
-  HTTP_CLIENT_5
+  HTTP_COMPONENTS
 }
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpResponseProxy.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpResponseProxy.java
index 4cdca78960..e45294b503 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpResponseProxy.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpResponseProxy.java
@@ -2,7 +2,7 @@
 
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.apache.ApacheHttpResponseProxy;
-import me.chanjar.weixin.common.util.http.hc5.ApacheHttpClient5ResponseProxy;
+import me.chanjar.weixin.common.util.http.hc.HttpComponentsResponseProxy;
 import me.chanjar.weixin.common.util.http.jodd.JoddHttpResponseProxy;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpResponseProxy;
 
@@ -26,8 +26,8 @@ static ApacheHttpResponseProxy from(org.apache.http.client.methods.CloseableHttp
     return new ApacheHttpResponseProxy(response);
   }
 
-  static ApacheHttpClient5ResponseProxy from(org.apache.hc.client5.http.impl.classic.CloseableHttpResponse response) {
-    return new ApacheHttpClient5ResponseProxy(response);
+  static HttpComponentsResponseProxy from(org.apache.hc.client5.http.impl.classic.CloseableHttpResponse response) {
+    return new HttpComponentsResponseProxy(response);
   }
 
   static JoddHttpResponseProxy from(jodd.http.HttpResponse response) {
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaUploadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaUploadRequestExecutor.java
index 9b4f2d5571..2d16e714e9 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaUploadRequestExecutor.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaUploadRequestExecutor.java
@@ -8,12 +8,11 @@
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.service.WxService;
 import me.chanjar.weixin.common.util.http.apache.ApacheMediaUploadRequestExecutor;
+import me.chanjar.weixin.common.util.http.hc.HttpComponentsMediaUploadRequestExecutor;
 import me.chanjar.weixin.common.util.http.jodd.JoddHttpMediaUploadRequestExecutor;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpMediaUploadRequestExecutor;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
 import okhttp3.OkHttpClient;
-import org.apache.http.HttpHost;
-import org.apache.http.impl.client.CloseableHttpClient;
 
 import java.io.File;
 import java.io.IOException;
@@ -40,16 +39,21 @@ public void execute(String uri, File data, ResponseHandler
     handler.handle(this.execute(uri, data, wxType));
   }
 
+  @SuppressWarnings("unchecked")
   public static RequestExecutor create(RequestHttp requestHttp) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new ApacheMediaUploadRequestExecutor((RequestHttp) requestHttp);
+        return new ApacheMediaUploadRequestExecutor(
+          (RequestHttp) requestHttp);
       case JODD_HTTP:
         return new JoddHttpMediaUploadRequestExecutor((RequestHttp) requestHttp);
       case OK_HTTP:
         return new OkHttpMediaUploadRequestExecutor((RequestHttp) requestHttp);
+      case HTTP_COMPONENTS:
+        return new HttpComponentsMediaUploadRequestExecutor(
+          (RequestHttp) requestHttp);
       default:
-        return null;
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MinishopUploadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MinishopUploadRequestExecutor.java
index 7b7f9ca460..e6018a7791 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MinishopUploadRequestExecutor.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MinishopUploadRequestExecutor.java
@@ -6,12 +6,11 @@
 import me.chanjar.weixin.common.enums.WxType;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.apache.ApacheMinishopMediaUploadRequestExecutor;
+import me.chanjar.weixin.common.util.http.hc.HttpComponentsMinishopMediaUploadRequestExecutor;
 import me.chanjar.weixin.common.util.http.jodd.JoddHttpMinishopMediaUploadRequestExecutor;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpMinishopMediaUploadRequestExecutor;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
 import okhttp3.OkHttpClient;
-import org.apache.http.HttpHost;
-import org.apache.http.impl.client.CloseableHttpClient;
 
 import java.io.File;
 import java.io.IOException;
@@ -32,13 +31,17 @@ public void execute(String uri, File data, ResponseHandler create(RequestHttp requestHttp) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new ApacheMinishopMediaUploadRequestExecutor((RequestHttp) requestHttp);
+        return new ApacheMinishopMediaUploadRequestExecutor(
+          (RequestHttp) requestHttp);
       case JODD_HTTP:
         return new JoddHttpMinishopMediaUploadRequestExecutor((RequestHttp) requestHttp);
       case OK_HTTP:
         return new OkHttpMinishopMediaUploadRequestExecutor((RequestHttp) requestHttp);
+      case HTTP_COMPONENTS:
+        return new HttpComponentsMinishopMediaUploadRequestExecutor(
+          (RequestHttp) requestHttp);
       default:
-        return null;
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 }
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/BasicResponseHandler.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/BasicResponseHandler.java
new file mode 100644
index 0000000000..f69e14a240
--- /dev/null
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/BasicResponseHandler.java
@@ -0,0 +1,14 @@
+package me.chanjar.weixin.common.util.http.hc;
+
+import org.apache.hc.client5.http.impl.classic.BasicHttpClientResponseHandler;
+
+/**
+ * ApacheBasicResponseHandler
+ *
+ * @author altusea
+ */
+public class BasicResponseHandler extends BasicHttpClientResponseHandler {
+
+  public static final BasicHttpClientResponseHandler INSTANCE = new BasicHttpClientResponseHandler();
+
+}
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ByteArrayResponseHandler.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/ByteArrayResponseHandler.java
similarity index 92%
rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ByteArrayResponseHandler.java
rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/ByteArrayResponseHandler.java
index 12be55c2cb..e4a314f866 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ByteArrayResponseHandler.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/ByteArrayResponseHandler.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.common.util.http.hc5;
+package me.chanjar.weixin.common.util.http.hc;
 
 import org.apache.hc.client5.http.impl.classic.AbstractHttpClientResponseHandler;
 import org.apache.hc.core5.http.HttpEntity;
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/DefaultApacheHttpClientBuilder.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/DefaultHttpComponentsClientBuilder.java
similarity index 87%
rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/DefaultApacheHttpClientBuilder.java
rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/DefaultHttpComponentsClientBuilder.java
index 9e95f4429b..4915e31a16 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/DefaultApacheHttpClientBuilder.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/DefaultHttpComponentsClientBuilder.java
@@ -1,7 +1,9 @@
-package me.chanjar.weixin.common.util.http.hc5;
+package me.chanjar.weixin.common.util.http.hc;
 
 import lombok.Data;
 import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
+import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder;
 import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.hc.client5.http.ConnectionKeepAliveStrategy;
@@ -43,7 +45,7 @@
 @Slf4j
 @Data
 @NotThreadSafe
-public class DefaultApacheHttpClientBuilder implements ApacheHttpClientBuilder {
+public class DefaultHttpComponentsClientBuilder implements HttpComponentsClientBuilder {
 
   private final AtomicBoolean prepared = new AtomicBoolean(false);
 
@@ -121,45 +123,45 @@ public class DefaultApacheHttpClientBuilder implements ApacheHttpClientBuilder {
    */
   private CloseableHttpClient closeableHttpClient;
 
-  private DefaultApacheHttpClientBuilder() {
+  private DefaultHttpComponentsClientBuilder() {
   }
 
-  public static DefaultApacheHttpClientBuilder get() {
+  public static DefaultHttpComponentsClientBuilder get() {
     return SingletonHolder.INSTANCE;
   }
 
   @Override
-  public ApacheHttpClientBuilder httpProxyHost(String httpProxyHost) {
+  public HttpComponentsClientBuilder httpProxyHost(String httpProxyHost) {
     this.httpProxyHost = httpProxyHost;
     return this;
   }
 
   @Override
-  public ApacheHttpClientBuilder httpProxyPort(int httpProxyPort) {
+  public HttpComponentsClientBuilder httpProxyPort(int httpProxyPort) {
     this.httpProxyPort = httpProxyPort;
     return this;
   }
 
   @Override
-  public ApacheHttpClientBuilder httpProxyUsername(String httpProxyUsername) {
+  public HttpComponentsClientBuilder httpProxyUsername(String httpProxyUsername) {
     this.httpProxyUsername = httpProxyUsername;
     return this;
   }
 
   @Override
-  public ApacheHttpClientBuilder httpProxyPassword(char[] httpProxyPassword) {
+  public HttpComponentsClientBuilder httpProxyPassword(char[] httpProxyPassword) {
     this.httpProxyPassword = httpProxyPassword;
     return this;
   }
 
   @Override
-  public ApacheHttpClientBuilder httpRequestRetryStrategy(HttpRequestRetryStrategy httpRequestRetryStrategy) {
+  public HttpComponentsClientBuilder httpRequestRetryStrategy(HttpRequestRetryStrategy httpRequestRetryStrategy) {
     this.httpRequestRetryStrategy = httpRequestRetryStrategy;
     return this;
   }
 
   @Override
-  public ApacheHttpClientBuilder keepAliveStrategy(ConnectionKeepAliveStrategy keepAliveStrategy) {
+  public HttpComponentsClientBuilder keepAliveStrategy(ConnectionKeepAliveStrategy keepAliveStrategy) {
     this.connectionKeepAliveStrategy = keepAliveStrategy;
     return this;
   }
@@ -242,6 +244,6 @@ public CloseableHttpClient build() {
    * DefaultApacheHttpClientBuilder 改为单例模式,并持有唯一的CloseableHttpClient(仅首次调用创建)
    */
   private static class SingletonHolder {
-    private static final DefaultApacheHttpClientBuilder INSTANCE = new DefaultApacheHttpClientBuilder();
+    private static final DefaultHttpComponentsClientBuilder INSTANCE = new DefaultHttpComponentsClientBuilder();
   }
 }
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsClientBuilder.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsClientBuilder.java
new file mode 100644
index 0000000000..66cd58e15f
--- /dev/null
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsClientBuilder.java
@@ -0,0 +1,51 @@
+package me.chanjar.weixin.common.util.http.hc;
+
+import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
+import org.apache.hc.client5.http.ConnectionKeepAliveStrategy;
+import org.apache.hc.client5.http.HttpRequestRetryStrategy;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+
+/**
+ * httpclient build interface.
+ *
+ * @author altusea
+ */
+public interface HttpComponentsClientBuilder {
+
+  /**
+   * 构建httpclient实例.
+   *
+   * @return new instance of CloseableHttpClient
+   */
+  CloseableHttpClient build();
+
+  /**
+   * 代理服务器地址.
+   */
+  HttpComponentsClientBuilder httpProxyHost(String httpProxyHost);
+
+  /**
+   * 代理服务器端口.
+   */
+  HttpComponentsClientBuilder httpProxyPort(int httpProxyPort);
+
+  /**
+   * 代理服务器用户名.
+   */
+  HttpComponentsClientBuilder httpProxyUsername(String httpProxyUsername);
+
+  /**
+   * 代理服务器密码.
+   */
+  HttpComponentsClientBuilder httpProxyPassword(char[] httpProxyPassword);
+
+  /**
+   * 重试策略.
+   */
+  HttpComponentsClientBuilder httpRequestRetryStrategy(HttpRequestRetryStrategy httpRequestRetryStrategy);
+
+  /**
+   * 超时时间.
+   */
+  HttpComponentsClientBuilder keepAliveStrategy(ConnectionKeepAliveStrategy keepAliveStrategy);
+}
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheMediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsMediaDownloadRequestExecutor.java
similarity index 90%
rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheMediaDownloadRequestExecutor.java
rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsMediaDownloadRequestExecutor.java
index 95e55469cc..26fbed93f3 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheMediaDownloadRequestExecutor.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsMediaDownloadRequestExecutor.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.common.util.http.hc5;
+package me.chanjar.weixin.common.util.http.hc;
 
 import me.chanjar.weixin.common.enums.WxType;
 import me.chanjar.weixin.common.error.WxError;
@@ -28,9 +28,9 @@
  *
  * @author altusea
  */
-public class ApacheMediaDownloadRequestExecutor extends BaseMediaDownloadRequestExecutor {
+public class HttpComponentsMediaDownloadRequestExecutor extends BaseMediaDownloadRequestExecutor {
 
-  public ApacheMediaDownloadRequestExecutor(RequestHttp requestHttp, File tmpDirFile) {
+  public HttpComponentsMediaDownloadRequestExecutor(RequestHttp requestHttp, File tmpDirFile) {
     super(requestHttp, tmpDirFile);
   }
 
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheMediaInputStreamUploadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsMediaInputStreamUploadRequestExecutor.java
similarity index 86%
rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheMediaInputStreamUploadRequestExecutor.java
rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsMediaInputStreamUploadRequestExecutor.java
index 56ad71fe1f..4853b1572b 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheMediaInputStreamUploadRequestExecutor.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsMediaInputStreamUploadRequestExecutor.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.common.util.http.hc5;
+package me.chanjar.weixin.common.util.http.hc;
 
 import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
 import me.chanjar.weixin.common.enums.WxType;
@@ -23,9 +23,9 @@
  *
  * @author altusea
  */
-public class ApacheMediaInputStreamUploadRequestExecutor extends MediaInputStreamUploadRequestExecutor {
+public class HttpComponentsMediaInputStreamUploadRequestExecutor extends MediaInputStreamUploadRequestExecutor {
 
-  public ApacheMediaInputStreamUploadRequestExecutor(RequestHttp requestHttp) {
+  public HttpComponentsMediaInputStreamUploadRequestExecutor(RequestHttp requestHttp) {
     super(requestHttp);
   }
 
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheMediaUploadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsMediaUploadRequestExecutor.java
similarity index 86%
rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheMediaUploadRequestExecutor.java
rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsMediaUploadRequestExecutor.java
index 3aaf06349f..e65d855d52 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheMediaUploadRequestExecutor.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsMediaUploadRequestExecutor.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.common.util.http.hc5;
+package me.chanjar.weixin.common.util.http.hc;
 
 import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
 import me.chanjar.weixin.common.enums.WxType;
@@ -22,9 +22,9 @@
  *
  * @author altusea
  */
-public class ApacheMediaUploadRequestExecutor extends MediaUploadRequestExecutor {
+public class HttpComponentsMediaUploadRequestExecutor extends MediaUploadRequestExecutor {
 
-  public ApacheMediaUploadRequestExecutor(RequestHttp requestHttp) {
+  public HttpComponentsMediaUploadRequestExecutor(RequestHttp requestHttp) {
     super(requestHttp);
   }
 
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheMinishopMediaUploadRequestCustomizeExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsMinishopMediaUploadRequestCustomizeExecutor.java
similarity index 88%
rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheMinishopMediaUploadRequestCustomizeExecutor.java
rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsMinishopMediaUploadRequestCustomizeExecutor.java
index 80f5920b0d..711f538309 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheMinishopMediaUploadRequestCustomizeExecutor.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsMinishopMediaUploadRequestCustomizeExecutor.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.common.util.http.hc5;
+package me.chanjar.weixin.common.util.http.hc;
 
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.bean.result.WxMinishopImageUploadCustomizeResult;
@@ -24,9 +24,9 @@
  * @author altusea
  */
 @Slf4j
-public class ApacheMinishopMediaUploadRequestCustomizeExecutor extends MinishopUploadRequestCustomizeExecutor {
+public class HttpComponentsMinishopMediaUploadRequestCustomizeExecutor extends MinishopUploadRequestCustomizeExecutor {
 
-  public ApacheMinishopMediaUploadRequestCustomizeExecutor(RequestHttp requestHttp, String respType, String imgUrl) {
+  public HttpComponentsMinishopMediaUploadRequestCustomizeExecutor(RequestHttp requestHttp, String respType, String imgUrl) {
     super(requestHttp, respType, imgUrl);
   }
 
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheMinishopMediaUploadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsMinishopMediaUploadRequestExecutor.java
similarity index 86%
rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheMinishopMediaUploadRequestExecutor.java
rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsMinishopMediaUploadRequestExecutor.java
index 1140e36715..72c1f2765f 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheMinishopMediaUploadRequestExecutor.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsMinishopMediaUploadRequestExecutor.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.common.util.http.hc5;
+package me.chanjar.weixin.common.util.http.hc;
 
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.bean.result.WxMinishopImageUploadResult;
@@ -24,9 +24,9 @@
  * @author altusea
  */
 @Slf4j
-public class ApacheMinishopMediaUploadRequestExecutor extends MinishopUploadRequestExecutor {
+public class HttpComponentsMinishopMediaUploadRequestExecutor extends MinishopUploadRequestExecutor {
 
-  public ApacheMinishopMediaUploadRequestExecutor(RequestHttp requestHttp) {
+  public HttpComponentsMinishopMediaUploadRequestExecutor(RequestHttp requestHttp) {
     super(requestHttp);
   }
 
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheHttpClient5ResponseProxy.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsResponseProxy.java
similarity index 78%
rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheHttpClient5ResponseProxy.java
rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsResponseProxy.java
index f5c057f1ea..d55ff0735f 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheHttpClient5ResponseProxy.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsResponseProxy.java
@@ -1,15 +1,15 @@
-package me.chanjar.weixin.common.util.http.hc5;
+package me.chanjar.weixin.common.util.http.hc;
 
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.HttpResponseProxy;
 import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
 import org.apache.hc.core5.http.Header;
 
-public class ApacheHttpClient5ResponseProxy implements HttpResponseProxy {
+public class HttpComponentsResponseProxy implements HttpResponseProxy {
 
   private final CloseableHttpResponse response;
 
-  public ApacheHttpClient5ResponseProxy(CloseableHttpResponse closeableHttpResponse) {
+  public HttpComponentsResponseProxy(CloseableHttpResponse closeableHttpResponse) {
     this.response = closeableHttpResponse;
   }
 
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheSimpleGetRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsSimpleGetRequestExecutor.java
similarity index 82%
rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheSimpleGetRequestExecutor.java
rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsSimpleGetRequestExecutor.java
index b376e4a6d3..0d212fe7e2 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheSimpleGetRequestExecutor.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsSimpleGetRequestExecutor.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.common.util.http.hc5;
+package me.chanjar.weixin.common.util.http.hc;
 
 import me.chanjar.weixin.common.enums.WxType;
 import me.chanjar.weixin.common.error.WxErrorException;
@@ -16,9 +16,9 @@
  *
  * @author altusea
  */
-public class ApacheSimpleGetRequestExecutor extends SimpleGetRequestExecutor {
+public class HttpComponentsSimpleGetRequestExecutor extends SimpleGetRequestExecutor {
 
-  public ApacheSimpleGetRequestExecutor(RequestHttp requestHttp) {
+  public HttpComponentsSimpleGetRequestExecutor(RequestHttp requestHttp) {
     super(requestHttp);
   }
 
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheSimplePostRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsSimplePostRequestExecutor.java
similarity index 84%
rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheSimplePostRequestExecutor.java
rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsSimplePostRequestExecutor.java
index d46d6cbfd5..45d2ca9f6e 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheSimplePostRequestExecutor.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/HttpComponentsSimplePostRequestExecutor.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.common.util.http.hc5;
+package me.chanjar.weixin.common.util.http.hc;
 
 import me.chanjar.weixin.common.enums.WxType;
 import me.chanjar.weixin.common.error.WxErrorException;
@@ -19,9 +19,9 @@
  *
  * @author altusea
  */
-public class ApacheSimplePostRequestExecutor extends SimplePostRequestExecutor {
+public class HttpComponentsSimplePostRequestExecutor extends SimplePostRequestExecutor {
 
-  public ApacheSimplePostRequestExecutor(RequestHttp requestHttp) {
+  public HttpComponentsSimplePostRequestExecutor(RequestHttp requestHttp) {
     super(requestHttp);
   }
 
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/InputStreamResponseHandler.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/InputStreamResponseHandler.java
similarity index 92%
rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/InputStreamResponseHandler.java
rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/InputStreamResponseHandler.java
index dc86318490..27308151f7 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/InputStreamResponseHandler.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/InputStreamResponseHandler.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.common.util.http.hc5;
+package me.chanjar.weixin.common.util.http.hc;
 
 import org.apache.hc.client5.http.impl.classic.AbstractHttpClientResponseHandler;
 import org.apache.hc.core5.http.HttpEntity;
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/NoopRetryStrategy.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/NoopRetryStrategy.java
similarity index 95%
rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/NoopRetryStrategy.java
rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/NoopRetryStrategy.java
index 742ab25691..9b4e3bc384 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/NoopRetryStrategy.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/NoopRetryStrategy.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.common.util.http.hc5;
+package me.chanjar.weixin.common.util.http.hc;
 
 import org.apache.hc.client5.http.HttpRequestRetryStrategy;
 import org.apache.hc.core5.http.HttpRequest;
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/Utf8ResponseHandler.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/Utf8ResponseHandler.java
similarity index 95%
rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/Utf8ResponseHandler.java
rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/Utf8ResponseHandler.java
index 33a9d22c5f..81699ef57b 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/Utf8ResponseHandler.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc/Utf8ResponseHandler.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.common.util.http.hc5;
+package me.chanjar.weixin.common.util.http.hc;
 
 import org.apache.hc.client5.http.ClientProtocolException;
 import org.apache.hc.client5.http.impl.classic.AbstractHttpClientResponseHandler;
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheBasicResponseHandler.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheBasicResponseHandler.java
deleted file mode 100644
index a207e88bd2..0000000000
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheBasicResponseHandler.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package me.chanjar.weixin.common.util.http.hc5;
-
-import org.apache.hc.client5.http.impl.classic.BasicHttpClientResponseHandler;
-
-/**
- * ApacheBasicResponseHandler
- *
- * @author altusea
- */
-public class ApacheBasicResponseHandler extends BasicHttpClientResponseHandler {
-
-  public static final ApacheBasicResponseHandler INSTANCE = new ApacheBasicResponseHandler();
-
-}
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheHttpClientBuilder.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheHttpClientBuilder.java
deleted file mode 100644
index 27c2883cc2..0000000000
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/hc5/ApacheHttpClientBuilder.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package me.chanjar.weixin.common.util.http.hc5;
-
-import org.apache.hc.client5.http.ConnectionKeepAliveStrategy;
-import org.apache.hc.client5.http.HttpRequestRetryStrategy;
-import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
-
-/**
- * httpclient build interface.
- *
- * @author altusea
- */
-public interface ApacheHttpClientBuilder {
-
-  /**
-   * 构建httpclient实例.
-   *
-   * @return new instance of CloseableHttpClient
-   */
-  CloseableHttpClient build();
-
-  /**
-   * 代理服务器地址.
-   */
-  ApacheHttpClientBuilder httpProxyHost(String httpProxyHost);
-
-  /**
-   * 代理服务器端口.
-   */
-  ApacheHttpClientBuilder httpProxyPort(int httpProxyPort);
-
-  /**
-   * 代理服务器用户名.
-   */
-  ApacheHttpClientBuilder httpProxyUsername(String httpProxyUsername);
-
-  /**
-   * 代理服务器密码.
-   */
-  ApacheHttpClientBuilder httpProxyPassword(char[] httpProxyPassword);
-
-  /**
-   * 重试策略.
-   */
-  ApacheHttpClientBuilder httpRequestRetryStrategy(HttpRequestRetryStrategy httpRequestRetryStrategy);
-
-  /**
-   * 超时时间.
-   */
-  ApacheHttpClientBuilder keepAliveStrategy(ConnectionKeepAliveStrategy keepAliveStrategy);
-}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceHttpClient5Impl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceHttpComponentsImpl.java
similarity index 85%
rename from weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceHttpClient5Impl.java
rename to weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceHttpComponentsImpl.java
index 17b2b6b3c8..92fd2dbd9b 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceHttpClient5Impl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceHttpComponentsImpl.java
@@ -6,9 +6,9 @@
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.error.WxRuntimeException;
 import me.chanjar.weixin.common.util.http.HttpClientType;
-import me.chanjar.weixin.common.util.http.hc5.ApacheBasicResponseHandler;
-import me.chanjar.weixin.common.util.http.hc5.ApacheHttpClientBuilder;
-import me.chanjar.weixin.common.util.http.hc5.DefaultApacheHttpClientBuilder;
+import me.chanjar.weixin.common.util.http.hc.BasicResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.DefaultHttpComponentsClientBuilder;
+import me.chanjar.weixin.common.util.http.hc.HttpComponentsClientBuilder;
 import me.chanjar.weixin.cp.config.WxCpConfigStorage;
 import me.chanjar.weixin.cp.constant.WxCpApiPathConsts;
 import org.apache.hc.client5.http.classic.methods.HttpGet;
@@ -23,7 +23,7 @@
  *
  * @author altusea
  */
-public class WxCpServiceHttpClient5Impl extends BaseWxCpServiceImpl {
+public class WxCpServiceHttpComponentsImpl extends BaseWxCpServiceImpl {
 
   private CloseableHttpClient httpClient;
   private HttpHost httpProxy;
@@ -40,7 +40,7 @@ public HttpHost getRequestHttpProxy() {
 
   @Override
   public HttpClientType getRequestType() {
-    return HttpClientType.HTTP_CLIENT_5;
+    return HttpClientType.HTTP_COMPONENTS;
   }
 
   @Override
@@ -60,7 +60,7 @@ public String getAccessToken(boolean forceRefresh) throws WxErrorException {
             .setProxy(this.httpProxy).build();
           httpGet.setConfig(config);
         }
-        String resultContent = getRequestHttpClient().execute(httpGet, ApacheBasicResponseHandler.INSTANCE);
+        String resultContent = getRequestHttpClient().execute(httpGet, BasicResponseHandler.INSTANCE);
         WxError error = WxError.fromJson(resultContent, WxType.CP);
         if (error.getErrorCode() != 0) {
           throw new WxErrorException(error);
@@ -77,7 +77,7 @@ public String getAccessToken(boolean forceRefresh) throws WxErrorException {
 
   @Override
   public void initHttp() {
-    ApacheHttpClientBuilder apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get();
+    HttpComponentsClientBuilder apacheHttpClientBuilder = DefaultHttpComponentsClientBuilder.get();
 
     apacheHttpClientBuilder.httpProxyHost(this.configStorage.getHttpProxyHost())
       .httpProxyPort(this.configStorage.getHttpProxyPort())
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpCgServiceHttpClient5Impl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpCgServiceHttpComponentsImpl.java
similarity index 74%
rename from weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpCgServiceHttpClient5Impl.java
rename to weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpCgServiceHttpComponentsImpl.java
index 2b30614b3b..d5c60ad037 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpCgServiceHttpClient5Impl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/corpgroup/service/impl/WxCpCgServiceHttpComponentsImpl.java
@@ -1,15 +1,15 @@
 package me.chanjar.weixin.cp.corpgroup.service.impl;
 
 import me.chanjar.weixin.common.util.http.HttpClientType;
-import me.chanjar.weixin.common.util.http.hc5.ApacheHttpClientBuilder;
-import me.chanjar.weixin.common.util.http.hc5.DefaultApacheHttpClientBuilder;
+import me.chanjar.weixin.common.util.http.hc.DefaultHttpComponentsClientBuilder;
+import me.chanjar.weixin.common.util.http.hc.HttpComponentsClientBuilder;
 import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
 import org.apache.hc.core5.http.HttpHost;
 
 /**
  * @author altusea
  */
-public class WxCpCgServiceHttpClient5Impl extends BaseWxCpCgServiceImpl {
+public class WxCpCgServiceHttpComponentsImpl extends BaseWxCpCgServiceImpl {
   private CloseableHttpClient httpClient;
   private HttpHost httpProxy;
 
@@ -25,12 +25,12 @@ public HttpHost getRequestHttpProxy() {
 
   @Override
   public HttpClientType getRequestType() {
-    return HttpClientType.HTTP_CLIENT_5;
+    return HttpClientType.HTTP_COMPONENTS;
   }
 
   @Override
   public void initHttp() {
-    ApacheHttpClientBuilder apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get();
+    HttpComponentsClientBuilder apacheHttpClientBuilder = DefaultHttpComponentsClientBuilder.get();
 
     apacheHttpClientBuilder.httpProxyHost(this.configStorage.getHttpProxyHost())
       .httpProxyPort(this.configStorage.getHttpProxyPort())
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpServiceHttpClient5Impl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpServiceHttpComponentsImpl.java
similarity index 87%
rename from weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpServiceHttpClient5Impl.java
rename to weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpServiceHttpComponentsImpl.java
index 9499d070fc..419394a070 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpServiceHttpClient5Impl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpServiceHttpComponentsImpl.java
@@ -6,9 +6,9 @@
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.error.WxRuntimeException;
 import me.chanjar.weixin.common.util.http.HttpClientType;
-import me.chanjar.weixin.common.util.http.hc5.ApacheBasicResponseHandler;
-import me.chanjar.weixin.common.util.http.hc5.ApacheHttpClientBuilder;
-import me.chanjar.weixin.common.util.http.hc5.DefaultApacheHttpClientBuilder;
+import me.chanjar.weixin.common.util.http.hc.BasicResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.DefaultHttpComponentsClientBuilder;
+import me.chanjar.weixin.common.util.http.hc.HttpComponentsClientBuilder;
 import me.chanjar.weixin.common.util.json.GsonParser;
 import me.chanjar.weixin.cp.config.WxCpTpConfigStorage;
 import me.chanjar.weixin.cp.constant.WxCpApiPathConsts;
@@ -26,7 +26,7 @@
  *
  * @author altusea
  */
-public class WxCpTpServiceHttpClient5Impl extends BaseWxCpTpServiceImpl {
+public class WxCpTpServiceHttpComponentsImpl extends BaseWxCpTpServiceImpl {
   private CloseableHttpClient httpClient;
   private HttpHost httpProxy;
 
@@ -42,7 +42,7 @@ public HttpHost getRequestHttpProxy() {
 
   @Override
   public HttpClientType getRequestType() {
-    return HttpClientType.HTTP_CLIENT_5;
+    return HttpClientType.HTTP_COMPONENTS;
   }
 
   @Override
@@ -66,7 +66,7 @@ public String getSuiteAccessToken(boolean forceRefresh) throws WxErrorException
         StringEntity entity = new StringEntity(jsonObject.toString(), StandardCharsets.UTF_8);
         httpPost.setEntity(entity);
 
-        String resultContent = getRequestHttpClient().execute(httpPost, ApacheBasicResponseHandler.INSTANCE);
+        String resultContent = getRequestHttpClient().execute(httpPost, BasicResponseHandler.INSTANCE);
         WxError error = WxError.fromJson(resultContent, WxType.CP);
         if (error.getErrorCode() != 0) {
           throw new WxErrorException(error);
@@ -84,7 +84,7 @@ public String getSuiteAccessToken(boolean forceRefresh) throws WxErrorException
 
   @Override
   public void initHttp() {
-    ApacheHttpClientBuilder apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get();
+    HttpComponentsClientBuilder apacheHttpClientBuilder = DefaultHttpComponentsClientBuilder.get();
 
     apacheHttpClientBuilder.httpProxyHost(this.configStorage.getHttpProxyHost())
       .httpProxyPort(this.configStorage.getHttpProxyPort())
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApiSignaturePostRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApiSignaturePostRequestExecutor.java
index 5a5d21d928..e97e4b98f3 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApiSignaturePostRequestExecutor.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApiSignaturePostRequestExecutor.java
@@ -15,8 +15,6 @@
 import me.chanjar.weixin.common.util.http.ResponseHandler;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
 import okhttp3.OkHttpClient;
-import org.apache.http.HttpHost;
-import org.apache.http.impl.client.CloseableHttpClient;
 import org.jetbrains.annotations.NotNull;
 
 public abstract class ApiSignaturePostRequestExecutor
@@ -71,8 +69,8 @@ public WxMaApiResponse handleResponse(
         return new JoddApiSignaturePostRequestExecutor((RequestHttp) requestHttp);
       case OK_HTTP:
         return new OkHttpApiSignaturePostRequestExecutor((RequestHttp) requestHttp);
-      case HTTP_CLIENT_5:
-        return new HttpClient5ApiSignaturePostRequestExecutor(
+      case HTTP_COMPONENTS:
+        return new HttpComponentsApiSignaturePostRequestExecutor(
           (RequestHttp) requestHttp);
       default:
         throw new IllegalArgumentException("非法请求参数");
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5ApiSignaturePostRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpComponentsApiSignaturePostRequestExecutor.java
similarity index 87%
rename from weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5ApiSignaturePostRequestExecutor.java
rename to weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpComponentsApiSignaturePostRequestExecutor.java
index b86930f27c..23d2231855 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5ApiSignaturePostRequestExecutor.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpComponentsApiSignaturePostRequestExecutor.java
@@ -4,7 +4,7 @@
 import me.chanjar.weixin.common.enums.WxType;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.RequestHttp;
-import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.Utf8ResponseHandler;
 import org.apache.hc.client5.http.ClientProtocolException;
 import org.apache.hc.client5.http.classic.methods.HttpPost;
 import org.apache.hc.client5.http.config.RequestConfig;
@@ -21,9 +21,9 @@
 import java.util.HashMap;
 import java.util.Map;
 
-public class HttpClient5ApiSignaturePostRequestExecutor extends ApiSignaturePostRequestExecutor {
+public class HttpComponentsApiSignaturePostRequestExecutor extends ApiSignaturePostRequestExecutor {
 
-  public HttpClient5ApiSignaturePostRequestExecutor(RequestHttp requestHttp) {
+  public HttpComponentsApiSignaturePostRequestExecutor(RequestHttp requestHttp) {
     super(requestHttp);
   }
 
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5QrcodeBytesRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpComponentsQrcodeBytesRequestExecutor.java
similarity index 87%
rename from weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5QrcodeBytesRequestExecutor.java
rename to weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpComponentsQrcodeBytesRequestExecutor.java
index 5a536560b2..655296fdaf 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5QrcodeBytesRequestExecutor.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpComponentsQrcodeBytesRequestExecutor.java
@@ -5,8 +5,8 @@
 import me.chanjar.weixin.common.error.WxError;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.RequestHttp;
-import me.chanjar.weixin.common.util.http.hc5.InputStreamResponseHandler;
-import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.InputStreamResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.Utf8ResponseHandler;
 import org.apache.commons.io.IOUtils;
 import org.apache.hc.client5.http.ClientProtocolException;
 import org.apache.hc.client5.http.classic.methods.HttpPost;
@@ -25,10 +25,9 @@
 /**
  * @author altusea
  */
-public class HttpClient5QrcodeBytesRequestExecutor extends QrcodeBytesRequestExecutor {
+public class HttpComponentsQrcodeBytesRequestExecutor extends QrcodeBytesRequestExecutor {
 
-
-  public HttpClient5QrcodeBytesRequestExecutor(RequestHttp requestHttp) {
+  public HttpComponentsQrcodeBytesRequestExecutor(RequestHttp requestHttp) {
     super(requestHttp);
   }
 
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5QrcodeFileRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpComponentsQrcodeFileRequestExecutor.java
similarity index 88%
rename from weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5QrcodeFileRequestExecutor.java
rename to weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpComponentsQrcodeFileRequestExecutor.java
index d11f41b361..10d01b1cfd 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5QrcodeFileRequestExecutor.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpComponentsQrcodeFileRequestExecutor.java
@@ -6,8 +6,8 @@
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.fs.FileUtils;
 import me.chanjar.weixin.common.util.http.RequestHttp;
-import me.chanjar.weixin.common.util.http.hc5.InputStreamResponseHandler;
-import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.InputStreamResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.Utf8ResponseHandler;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.hc.client5.http.ClientProtocolException;
 import org.apache.hc.client5.http.classic.methods.HttpPost;
@@ -29,11 +29,11 @@
 /**
  * @author altusea
  */
-public class HttpClient5QrcodeFileRequestExecutor extends QrcodeRequestExecutor {
+public class HttpComponentsQrcodeFileRequestExecutor extends QrcodeRequestExecutor {
 
   private final String filePath;
 
-  public HttpClient5QrcodeFileRequestExecutor(RequestHttp requestHttp, String filePath) {
+  public HttpComponentsQrcodeFileRequestExecutor(RequestHttp requestHttp, String filePath) {
     super(requestHttp);
     this.filePath = filePath;
   }
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5UploadAuthMaterialRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpComponentsUploadAuthMaterialRequestExecutor.java
similarity index 84%
rename from weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5UploadAuthMaterialRequestExecutor.java
rename to weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpComponentsUploadAuthMaterialRequestExecutor.java
index 09528f5c63..8bfed3b5fa 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpClient5UploadAuthMaterialRequestExecutor.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpComponentsUploadAuthMaterialRequestExecutor.java
@@ -5,7 +5,7 @@
 import me.chanjar.weixin.common.error.WxError;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.RequestHttp;
-import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.Utf8ResponseHandler;
 import org.apache.hc.client5.http.classic.methods.HttpPost;
 import org.apache.hc.client5.http.config.RequestConfig;
 import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
@@ -20,9 +20,9 @@
 /**
  * @author altusea
  */
-public class HttpClient5UploadAuthMaterialRequestExecutor extends UploadAuthMaterialRequestExecutor {
+public class HttpComponentsUploadAuthMaterialRequestExecutor extends UploadAuthMaterialRequestExecutor {
 
-  public HttpClient5UploadAuthMaterialRequestExecutor(RequestHttp requestHttp) {
+  public HttpComponentsUploadAuthMaterialRequestExecutor(RequestHttp requestHttp) {
     super(requestHttp);
   }
 
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeBytesRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeBytesRequestExecutor.java
index 24e97d7b21..41f3dfbc10 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeBytesRequestExecutor.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeBytesRequestExecutor.java
@@ -35,8 +35,8 @@ public static RequestExecutor create(RequestH
           (RequestHttp) requestHttp);
       case OK_HTTP:
         return new OkHttpQrcodeBytesRequestExecutor((RequestHttp) requestHttp);
-      case HTTP_CLIENT_5:
-        return new HttpClient5QrcodeBytesRequestExecutor(
+      case HTTP_COMPONENTS:
+        return new HttpComponentsQrcodeBytesRequestExecutor(
           (RequestHttp) requestHttp);
       default:
         return null;
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeRequestExecutor.java
index 9527b5ce50..be52c0cccf 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeRequestExecutor.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeRequestExecutor.java
@@ -37,8 +37,8 @@ public static RequestExecutor create(RequestHtt
           (RequestHttp) requestHttp, path);
       case OK_HTTP:
         return new OkHttpQrcodeFileRequestExecutor((RequestHttp) requestHttp, path);
-      case HTTP_CLIENT_5:
-        return new HttpClient5QrcodeFileRequestExecutor(
+      case HTTP_COMPONENTS:
+        return new HttpComponentsQrcodeFileRequestExecutor(
           (RequestHttp) requestHttp, path);
       default:
         return null;
@@ -52,8 +52,8 @@ public static RequestExecutor create(RequestHtt
         return new ApacheQrcodeFileRequestExecutor((RequestHttp) requestHttp, null);
       case OK_HTTP:
         return new OkHttpQrcodeFileRequestExecutor((RequestHttp) requestHttp, null);
-      case HTTP_CLIENT_5:
-        return new HttpClient5QrcodeFileRequestExecutor(
+      case HTTP_COMPONENTS:
+        return new HttpComponentsQrcodeFileRequestExecutor(
           (RequestHttp) requestHttp, null);
       default:
         return null;
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/UploadAuthMaterialRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/UploadAuthMaterialRequestExecutor.java
index a3dcad1d78..cc53afb2d0 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/UploadAuthMaterialRequestExecutor.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/UploadAuthMaterialRequestExecutor.java
@@ -44,8 +44,8 @@ public static RequestExecutor create(Request
         return new JoddHttpUploadAuthMaterialRequestExecutor((RequestHttp) requestHttp);
       case OK_HTTP:
         return new OkHttpUploadAuthMaterialRequestExecutor((RequestHttp) requestHttp);
-      case HTTP_CLIENT_5:
-        return new HttpClient5UploadAuthMaterialRequestExecutor(
+      case HTTP_COMPONENTS:
+        return new HttpComponentsUploadAuthMaterialRequestExecutor(
           (RequestHttp) requestHttp);
       default:
         return null;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceHttpClient5Impl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceHttpComponentsImpl.java
similarity index 83%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceHttpClient5Impl.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceHttpComponentsImpl.java
index e1f9d35e67..bbf065acfc 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceHttpClient5Impl.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceHttpComponentsImpl.java
@@ -1,9 +1,9 @@
 package me.chanjar.weixin.mp.api.impl;
 
 import me.chanjar.weixin.common.util.http.HttpClientType;
-import me.chanjar.weixin.common.util.http.hc5.ApacheBasicResponseHandler;
-import me.chanjar.weixin.common.util.http.hc5.ApacheHttpClientBuilder;
-import me.chanjar.weixin.common.util.http.hc5.DefaultApacheHttpClientBuilder;
+import me.chanjar.weixin.common.util.http.hc.BasicResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.DefaultHttpComponentsClientBuilder;
+import me.chanjar.weixin.common.util.http.hc.HttpComponentsClientBuilder;
 import me.chanjar.weixin.mp.bean.WxMpStableAccessTokenRequest;
 import me.chanjar.weixin.mp.config.WxMpConfigStorage;
 import org.apache.hc.client5.http.classic.methods.HttpGet;
@@ -24,7 +24,7 @@
  *
  * @author altusea
  */
-public class WxMpServiceHttpClient5Impl extends BaseWxMpServiceImpl {
+public class WxMpServiceHttpComponentsImpl extends BaseWxMpServiceImpl {
   private CloseableHttpClient httpClient;
   private HttpHost httpProxy;
 
@@ -40,13 +40,13 @@ public HttpHost getRequestHttpProxy() {
 
   @Override
   public HttpClientType getRequestType() {
-    return HttpClientType.HTTP_CLIENT_5;
+    return HttpClientType.HTTP_COMPONENTS;
   }
 
   @Override
   public void initHttp() {
     WxMpConfigStorage configStorage = this.getWxMpConfigStorage();
-    ApacheHttpClientBuilder apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get();
+    HttpComponentsClientBuilder apacheHttpClientBuilder = DefaultHttpComponentsClientBuilder.get();
 
     apacheHttpClientBuilder.httpProxyHost(configStorage.getHttpProxyHost())
       .httpProxyPort(configStorage.getHttpProxyPort())
@@ -69,7 +69,7 @@ protected String doGetAccessTokenRequest() throws IOException {
       RequestConfig config = RequestConfig.custom().setProxy(this.getRequestHttpProxy()).build();
       httpGet.setConfig(config);
     }
-    return getRequestHttpClient().execute(httpGet, ApacheBasicResponseHandler.INSTANCE);
+    return getRequestHttpClient().execute(httpGet, BasicResponseHandler.INSTANCE);
   }
 
   @Override
@@ -88,7 +88,7 @@ protected String doGetStableAccessTokenRequest(boolean forceRefresh) throws IOEx
     wxMaAccessTokenRequest.setForceRefresh(forceRefresh);
 
     httpPost.setEntity(new StringEntity(wxMaAccessTokenRequest.toJson(), ContentType.APPLICATION_JSON));
-    return getRequestHttpClient().execute(httpPost, ApacheBasicResponseHandler.INSTANCE);
+    return getRequestHttpClient().execute(httpPost, BasicResponseHandler.INSTANCE);
   }
 
 }
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialDeleteHttpClient5RequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialDeleteHttpComponentsRequestExecutor.java
similarity index 83%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialDeleteHttpClient5RequestExecutor.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialDeleteHttpComponentsRequestExecutor.java
index 25245fb019..46f8f16988 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialDeleteHttpClient5RequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialDeleteHttpComponentsRequestExecutor.java
@@ -4,7 +4,7 @@
 import me.chanjar.weixin.common.error.WxError;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.RequestHttp;
-import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.Utf8ResponseHandler;
 import me.chanjar.weixin.common.util.json.WxGsonBuilder;
 import org.apache.hc.client5.http.classic.methods.HttpPost;
 import org.apache.hc.client5.http.config.RequestConfig;
@@ -16,8 +16,8 @@
 import java.util.HashMap;
 import java.util.Map;
 
-public class MaterialDeleteHttpClient5RequestExecutor extends MaterialDeleteRequestExecutor {
-  public MaterialDeleteHttpClient5RequestExecutor(RequestHttp requestHttp) {
+public class MaterialDeleteHttpComponentsRequestExecutor extends MaterialDeleteRequestExecutor {
+  public MaterialDeleteHttpComponentsRequestExecutor(RequestHttp requestHttp) {
     super(requestHttp);
   }
 
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialDeleteRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialDeleteRequestExecutor.java
index 3f8eae8c83..f75afd9646 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialDeleteRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialDeleteRequestExecutor.java
@@ -34,8 +34,8 @@ public static RequestExecutor create(RequestHttp requestH
         return new MaterialDeleteJoddHttpRequestExecutor((RequestHttp) requestHttp);
       case OK_HTTP:
         return new MaterialDeleteOkhttpRequestExecutor((RequestHttp) requestHttp);
-      case HTTP_CLIENT_5:
-        return new MaterialDeleteHttpClient5RequestExecutor(
+      case HTTP_COMPONENTS:
+        return new MaterialDeleteHttpComponentsRequestExecutor(
           (RequestHttp) requestHttp);
       default:
         return null;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoHttpClient5RequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoHttpComponentsRequestExecutor.java
similarity index 85%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoHttpClient5RequestExecutor.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoHttpComponentsRequestExecutor.java
index 1c16c55471..ddf3ad6762 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoHttpClient5RequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoHttpComponentsRequestExecutor.java
@@ -6,7 +6,7 @@
 import me.chanjar.weixin.common.error.WxError;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.RequestHttp;
-import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.Utf8ResponseHandler;
 import me.chanjar.weixin.common.util.json.WxGsonBuilder;
 import me.chanjar.weixin.mp.bean.material.WxMpMaterialNews;
 import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
@@ -19,9 +19,9 @@
 import java.io.IOException;
 
 @Slf4j
-public class MaterialNewsInfoHttpClient5RequestExecutor extends MaterialNewsInfoRequestExecutor {
+public class MaterialNewsInfoHttpComponentsRequestExecutor extends MaterialNewsInfoRequestExecutor {
 
-  public MaterialNewsInfoHttpClient5RequestExecutor(RequestHttp requestHttp) {
+  public MaterialNewsInfoHttpComponentsRequestExecutor(RequestHttp requestHttp) {
     super(requestHttp);
   }
 
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoRequestExecutor.java
index bc6e616f8f..87ac96a397 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoRequestExecutor.java
@@ -12,8 +12,6 @@
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
 import me.chanjar.weixin.mp.bean.material.WxMpMaterialNews;
 import okhttp3.OkHttpClient;
-import org.apache.http.HttpHost;
-import org.apache.http.impl.client.CloseableHttpClient;
 
 public abstract class MaterialNewsInfoRequestExecutor implements RequestExecutor {
   protected RequestHttp requestHttp;
@@ -37,8 +35,8 @@ public static RequestExecutor create(RequestHttp
         return new MaterialNewsInfoJoddHttpRequestExecutor((RequestHttp) requestHttp);
       case OK_HTTP:
         return new MaterialNewsInfoOkhttpRequestExecutor((RequestHttp) requestHttp);
-        case HTTP_CLIENT_5:
-          return new MaterialNewsInfoHttpClient5RequestExecutor(
+        case HTTP_COMPONENTS:
+          return new MaterialNewsInfoHttpComponentsRequestExecutor(
             (RequestHttp) requestHttp);
       default:
         //TODO 需要优化抛出异常
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadHttpClient5RequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadHttpComponentsRequestExecutor.java
similarity index 89%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadHttpClient5RequestExecutor.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadHttpComponentsRequestExecutor.java
index 7fb73ab81f..05ae0fe506 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadHttpClient5RequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadHttpComponentsRequestExecutor.java
@@ -4,7 +4,7 @@
 import me.chanjar.weixin.common.error.WxError;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.RequestHttp;
-import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.Utf8ResponseHandler;
 import me.chanjar.weixin.common.util.json.WxGsonBuilder;
 import me.chanjar.weixin.mp.bean.material.WxMpMaterial;
 import me.chanjar.weixin.mp.bean.material.WxMpMaterialUploadResult;
@@ -23,8 +23,8 @@
 import java.nio.charset.StandardCharsets;
 import java.util.Map;
 
-public class MaterialUploadHttpClient5RequestExecutor extends MaterialUploadRequestExecutor {
-  public MaterialUploadHttpClient5RequestExecutor(RequestHttp requestHttp) {
+public class MaterialUploadHttpComponentsRequestExecutor extends MaterialUploadRequestExecutor {
+  public MaterialUploadHttpComponentsRequestExecutor(RequestHttp requestHttp) {
     super(requestHttp);
   }
 
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadRequestExecutor.java
index 1d7ef1947c..0317f0588c 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadRequestExecutor.java
@@ -39,8 +39,8 @@ public static RequestExecutor create(Req
         return new MaterialUploadJoddHttpRequestExecutor((RequestHttp) requestHttp);
       case OK_HTTP:
         return new MaterialUploadOkhttpRequestExecutor((RequestHttp) requestHttp);
-      case HTTP_CLIENT_5:
-        return new MaterialUploadHttpClient5RequestExecutor(
+      case HTTP_COMPONENTS:
+        return new MaterialUploadHttpComponentsRequestExecutor(
           (RequestHttp) requestHttp);
       default:
         return null;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoHttpClient5RequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoHttpComponentsRequestExecutor.java
similarity index 84%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoHttpClient5RequestExecutor.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoHttpComponentsRequestExecutor.java
index 7641e8fa3f..2a147609d5 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoHttpClient5RequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoHttpComponentsRequestExecutor.java
@@ -4,7 +4,7 @@
 import me.chanjar.weixin.common.error.WxError;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.RequestHttp;
-import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.Utf8ResponseHandler;
 import me.chanjar.weixin.common.util.json.WxGsonBuilder;
 import me.chanjar.weixin.mp.bean.material.WxMpMaterialVideoInfoResult;
 import org.apache.hc.client5.http.classic.methods.HttpPost;
@@ -17,8 +17,8 @@
 import java.util.HashMap;
 import java.util.Map;
 
-public class MaterialVideoInfoHttpClient5RequestExecutor extends MaterialVideoInfoRequestExecutor {
-  public MaterialVideoInfoHttpClient5RequestExecutor(RequestHttp requestHttp) {
+public class MaterialVideoInfoHttpComponentsRequestExecutor extends MaterialVideoInfoRequestExecutor {
+  public MaterialVideoInfoHttpComponentsRequestExecutor(RequestHttp requestHttp) {
     super(requestHttp);
   }
 
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoRequestExecutor.java
index ac9d41f021..3c265dc26f 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoRequestExecutor.java
@@ -35,8 +35,8 @@ public static RequestExecutor create(Reques
         return new MaterialVideoInfoJoddHttpRequestExecutor((RequestHttp) requestHttp);
       case OK_HTTP:
         return new MaterialVideoInfoOkhttpRequestExecutor((RequestHttp) requestHttp);
-      case HTTP_CLIENT_5:
-        return new MaterialVideoInfoHttpClient5RequestExecutor(
+      case HTTP_COMPONENTS:
+        return new MaterialVideoInfoHttpComponentsRequestExecutor(
           (RequestHttp) requestHttp);
       default:
         return null;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadHttpClient5RequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadHttpComponentsRequestExecutor.java
similarity index 87%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadHttpClient5RequestExecutor.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadHttpComponentsRequestExecutor.java
index 8caa089e09..ac7df1a0ce 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadHttpClient5RequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadHttpComponentsRequestExecutor.java
@@ -4,7 +4,7 @@
 import me.chanjar.weixin.common.error.WxError;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.RequestHttp;
-import me.chanjar.weixin.common.util.http.hc5.InputStreamResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.InputStreamResponseHandler;
 import me.chanjar.weixin.common.util.json.WxGsonBuilder;
 import org.apache.commons.io.IOUtils;
 import org.apache.hc.client5.http.ClientProtocolException;
@@ -24,8 +24,9 @@
 import java.util.HashMap;
 import java.util.Map;
 
-public class MaterialVoiceAndImageDownloadHttpClient5RequestExecutor extends MaterialVoiceAndImageDownloadRequestExecutor {
-  public MaterialVoiceAndImageDownloadHttpClient5RequestExecutor(RequestHttp requestHttp, File tmpDirFile) {
+public class MaterialVoiceAndImageDownloadHttpComponentsRequestExecutor
+  extends MaterialVoiceAndImageDownloadRequestExecutor {
+  public MaterialVoiceAndImageDownloadHttpComponentsRequestExecutor(RequestHttp requestHttp, File tmpDirFile) {
     super(requestHttp, tmpDirFile);
   }
 
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadRequestExecutor.java
index 42e70afa3a..5ad8ebd1f6 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadRequestExecutor.java
@@ -13,8 +13,6 @@
 import me.chanjar.weixin.common.util.http.ResponseHandler;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
 import okhttp3.OkHttpClient;
-import org.apache.http.HttpHost;
-import org.apache.http.impl.client.CloseableHttpClient;
 
 public abstract class MaterialVoiceAndImageDownloadRequestExecutor implements RequestExecutor {
   protected RequestHttp requestHttp;
@@ -40,8 +38,8 @@ public static RequestExecutor create(RequestHttp requ
         return new MaterialVoiceAndImageDownloadJoddHttpRequestExecutor((RequestHttp) requestHttp, tmpDirFile);
       case OK_HTTP:
         return new MaterialVoiceAndImageDownloadOkhttpRequestExecutor((RequestHttp) requestHttp, tmpDirFile);
-      case HTTP_CLIENT_5:
-        return new MaterialVoiceAndImageDownloadHttpClient5RequestExecutor(
+      case HTTP_COMPONENTS:
+        return new MaterialVoiceAndImageDownloadHttpComponentsRequestExecutor(
           (RequestHttp) requestHttp, tmpDirFile);
       default:
         return null;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadHttpClient5RequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadHttpComponentsRequestExecutor.java
similarity index 85%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadHttpClient5RequestExecutor.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadHttpComponentsRequestExecutor.java
index 71ed71da8c..be1d12631d 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadHttpClient5RequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadHttpComponentsRequestExecutor.java
@@ -4,7 +4,7 @@
 import me.chanjar.weixin.common.error.WxError;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.RequestHttp;
-import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.Utf8ResponseHandler;
 import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult;
 import org.apache.hc.client5.http.classic.methods.HttpPost;
 import org.apache.hc.client5.http.config.RequestConfig;
@@ -17,8 +17,8 @@
 import java.io.File;
 import java.io.IOException;
 
-public class MediaImgUploadHttpClient5RequestExecutor extends MediaImgUploadRequestExecutor {
-  public MediaImgUploadHttpClient5RequestExecutor(RequestHttp requestHttp) {
+public class MediaImgUploadHttpComponentsRequestExecutor extends MediaImgUploadRequestExecutor {
+  public MediaImgUploadHttpComponentsRequestExecutor(RequestHttp requestHttp) {
     super(requestHttp);
   }
 
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadRequestExecutor.java
index ec84906209..039093f97b 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadRequestExecutor.java
@@ -13,8 +13,6 @@
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
 import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult;
 import okhttp3.OkHttpClient;
-import org.apache.http.HttpHost;
-import org.apache.http.impl.client.CloseableHttpClient;
 
 /**
  * @author miller
@@ -41,8 +39,8 @@ public static RequestExecutor create(RequestHttp) requestHttp);
       case OK_HTTP:
         return new MediaImgUploadOkhttpRequestExecutor((RequestHttp) requestHttp);
-      case HTTP_CLIENT_5:
-        return new MediaImgUploadHttpClient5RequestExecutor(
+      case HTTP_COMPONENTS:
+        return new MediaImgUploadHttpComponentsRequestExecutor(
           (RequestHttp) requestHttp);
       default:
         return null;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeHttpClient5RequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeHttpComponentsRequestExecutor.java
similarity index 87%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeHttpClient5RequestExecutor.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeHttpComponentsRequestExecutor.java
index aecf7de7f7..fbf8af0783 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeHttpClient5RequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeHttpComponentsRequestExecutor.java
@@ -5,8 +5,8 @@
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.fs.FileUtils;
 import me.chanjar.weixin.common.util.http.RequestHttp;
-import me.chanjar.weixin.common.util.http.hc5.InputStreamResponseHandler;
-import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.InputStreamResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.Utf8ResponseHandler;
 import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
 import org.apache.hc.client5.http.ClientProtocolException;
 import org.apache.hc.client5.http.classic.methods.HttpGet;
@@ -27,8 +27,8 @@
 /**
  * @author altusea
  */
-public class QrCodeHttpClient5RequestExecutor extends QrCodeRequestExecutor {
-  public QrCodeHttpClient5RequestExecutor(RequestHttp requestHttp) {
+public class QrCodeHttpComponentsRequestExecutor extends QrCodeRequestExecutor {
+  public QrCodeHttpComponentsRequestExecutor(RequestHttp requestHttp) {
     super(requestHttp);
   }
 
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeRequestExecutor.java
index ac2e5ffced..6407ac11ad 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/qrcode/QrCodeRequestExecutor.java
@@ -13,8 +13,6 @@
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
 import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
 import okhttp3.OkHttpClient;
-import org.apache.http.HttpHost;
-import org.apache.http.impl.client.CloseableHttpClient;
 
 /**
  * 获得QrCode图片 请求执行器.
@@ -34,7 +32,7 @@ public void execute(String uri, WxMpQrCodeTicket data, ResponseHandler han
   }
 
   @SuppressWarnings("unchecked")
-  public static RequestExecutor create(RequestHttp requestHttp) throws WxErrorException {
+  public static RequestExecutor create(RequestHttp requestHttp) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
         return new QrCodeApacheHttpRequestExecutor(
@@ -43,11 +41,11 @@ public static RequestExecutor create(RequestHttp r
         return new QrCodeJoddHttpRequestExecutor((RequestHttp) requestHttp);
       case OK_HTTP:
         return new QrCodeOkhttpRequestExecutor((RequestHttp) requestHttp);
-      case HTTP_CLIENT_5:
-        return new QrCodeHttpClient5RequestExecutor(
+      case HTTP_COMPONENTS:
+        return new QrCodeHttpComponentsRequestExecutor(
           (RequestHttp) requestHttp);
       default:
-        throw new WxErrorException("不支持的http框架");
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadHttpClient5RequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadHttpComponentsRequestExecutor.java
similarity index 84%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadHttpClient5RequestExecutor.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadHttpComponentsRequestExecutor.java
index 6899ca4f0e..1775f04aef 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadHttpClient5RequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadHttpComponentsRequestExecutor.java
@@ -4,7 +4,7 @@
 import me.chanjar.weixin.common.error.WxError;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.RequestHttp;
-import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.Utf8ResponseHandler;
 import org.apache.hc.client5.http.classic.methods.HttpPost;
 import org.apache.hc.client5.http.config.RequestConfig;
 import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
@@ -16,8 +16,8 @@
 import java.io.File;
 import java.io.IOException;
 
-public class VoiceUploadHttpClient5RequestExecutor extends VoiceUploadRequestExecutor {
-  public VoiceUploadHttpClient5RequestExecutor(RequestHttp requestHttp) {
+public class VoiceUploadHttpComponentsRequestExecutor extends VoiceUploadRequestExecutor {
+  public VoiceUploadHttpComponentsRequestExecutor(RequestHttp requestHttp) {
     super(requestHttp);
   }
 
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadRequestExecutor.java
index 81794d31b4..bdbd029303 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadRequestExecutor.java
@@ -8,8 +8,6 @@
 import me.chanjar.weixin.common.util.http.RequestExecutor;
 import me.chanjar.weixin.common.util.http.RequestHttp;
 import me.chanjar.weixin.common.util.http.ResponseHandler;
-import org.apache.http.HttpHost;
-import org.apache.http.impl.client.CloseableHttpClient;
 
 /**
  * 
@@ -36,8 +34,8 @@ public static RequestExecutor create(RequestHttp requestHtt
       case APACHE_HTTP:
         return new VoiceUploadApacheHttpRequestExecutor(
           (RequestHttp) requestHttp);
-      case HTTP_CLIENT_5:
-        return new VoiceUploadHttpClient5RequestExecutor(
+      case HTTP_COMPONENTS:
+        return new VoiceUploadHttpComponentsRequestExecutor(
           (RequestHttp) requestHttp);
       case OK_HTTP:
       default:
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutor.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutor.java
index ba413b13f8..17c7906c5a 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutor.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutor.java
@@ -47,8 +47,8 @@ public static RequestExecutor create(RequestHttp
         return new CommonUploadMultiRequestExecutorJoddHttpImpl((RequestHttp) requestHttp);
       case OK_HTTP:
         return new CommonUploadMultiRequestExecutorOkHttpImpl((RequestHttp) requestHttp);
-      case HTTP_CLIENT_5:
-        return new CommonUploadMultiRequestExecutorHttpClient5Impl(
+      case HTTP_COMPONENTS:
+        return new CommonUploadMultiRequestExecutorHttpComponentsImpl(
           (RequestHttp) requestHttp);
       default:
         throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutorHttpClient5Impl.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutorHttpComponentsImpl.java
similarity index 91%
rename from weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutorHttpClient5Impl.java
rename to weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutorHttpComponentsImpl.java
index bba2d0ae3f..98bf2e7541 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutorHttpClient5Impl.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutorHttpComponentsImpl.java
@@ -7,7 +7,7 @@
 import me.chanjar.weixin.common.error.WxError;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.RequestHttp;
-import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.Utf8ResponseHandler;
 import me.chanjar.weixin.open.bean.CommonUploadMultiParam;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.hc.client5.http.classic.methods.HttpPost;
@@ -29,9 +29,9 @@
 /**
  * @author altusea
  */
-public class CommonUploadMultiRequestExecutorHttpClient5Impl extends CommonUploadMultiRequestExecutor {
+public class CommonUploadMultiRequestExecutorHttpComponentsImpl extends CommonUploadMultiRequestExecutor {
 
-  public CommonUploadMultiRequestExecutorHttpClient5Impl(RequestHttp requestHttp) {
+  public CommonUploadMultiRequestExecutorHttpComponentsImpl(RequestHttp requestHttp) {
     super(requestHttp);
   }
 
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/MaQrCodeHttpClient5RequestExecutor.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/MaQrCodeHttpComponentsRequestExecutor.java
similarity index 88%
rename from weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/MaQrCodeHttpClient5RequestExecutor.java
rename to weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/MaQrCodeHttpComponentsRequestExecutor.java
index d1fa0078c1..e4682a7143 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/MaQrCodeHttpClient5RequestExecutor.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/MaQrCodeHttpComponentsRequestExecutor.java
@@ -5,8 +5,8 @@
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.fs.FileUtils;
 import me.chanjar.weixin.common.util.http.RequestHttp;
-import me.chanjar.weixin.common.util.http.hc5.InputStreamResponseHandler;
-import me.chanjar.weixin.common.util.http.hc5.Utf8ResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.InputStreamResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.Utf8ResponseHandler;
 import me.chanjar.weixin.open.bean.ma.WxMaQrcodeParam;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.hc.client5.http.ClientProtocolException;
@@ -25,8 +25,8 @@
 import java.net.URLEncoder;
 import java.util.UUID;
 
-public class MaQrCodeHttpClient5RequestExecutor extends MaQrCodeRequestExecutor {
-  public MaQrCodeHttpClient5RequestExecutor(RequestHttp requestHttp) {
+public class MaQrCodeHttpComponentsRequestExecutor extends MaQrCodeRequestExecutor {
+  public MaQrCodeHttpComponentsRequestExecutor(RequestHttp requestHttp) {
     super(requestHttp);
   }
 
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/MaQrCodeRequestExecutor.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/MaQrCodeRequestExecutor.java
index 103a73d2e1..000845b716 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/MaQrCodeRequestExecutor.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/MaQrCodeRequestExecutor.java
@@ -13,8 +13,6 @@
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
 import me.chanjar.weixin.open.bean.ma.WxMaQrcodeParam;
 import okhttp3.OkHttpClient;
-import org.apache.http.HttpHost;
-import org.apache.http.impl.client.CloseableHttpClient;
 
 /**
  * 获得小程序体验QrCode图片 请求执行器.
@@ -35,19 +33,20 @@ public void execute(String uri, WxMaQrcodeParam data, ResponseHandler hand
   }
 
   @SuppressWarnings("unchecked")
-  public static RequestExecutor create(RequestHttp requestHttp) throws WxErrorException {
+  public static RequestExecutor create(RequestHttp requestHttp) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new MaQrCodeApacheHttpRequestExecutor((RequestHttp) requestHttp);
+        return new MaQrCodeApacheHttpRequestExecutor(
+          (RequestHttp) requestHttp);
       case JODD_HTTP:
         return new MaQrCodeJoddHttpRequestExecutor((RequestHttp) requestHttp);
       case OK_HTTP:
         return new MaQrCodeOkhttpRequestExecutor((RequestHttp) requestHttp);
-      case HTTP_CLIENT_5:
-        return new MaQrCodeHttpClient5RequestExecutor(
+      case HTTP_COMPONENTS:
+        return new MaQrCodeHttpComponentsRequestExecutor(
           (RequestHttp) requestHttp);
       default:
-        throw new WxErrorException("不支持的http框架");
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceHttpClient5Impl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceHttpComponentsImpl.java
similarity index 99%
rename from weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceHttpClient5Impl.java
rename to weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceHttpComponentsImpl.java
index 5845a8338a..1c558f711b 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceHttpClient5Impl.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceHttpComponentsImpl.java
@@ -34,12 +34,12 @@
 import java.util.Optional;
 
 /**
- * 微信支付请求实现类,apache httpclient5 实现.
+ * 微信支付请求实现类,apache httpconponents 实现.
  *
  * @author altusea
  */
 @Slf4j
-public class WxPayServiceHttpClient5Impl extends BaseWxPayServiceImpl {
+public class WxPayServiceHttpComponentsImpl extends BaseWxPayServiceImpl {
 
   private static final String ACCEPT = "Accept";
   private static final String CONTENT_TYPE = "Content-Type";
diff --git a/weixin-java-qidian/src/main/java/me/chanjar/weixin/qidian/api/impl/WxQidianServiceHttpClient5Impl.java b/weixin-java-qidian/src/main/java/me/chanjar/weixin/qidian/api/impl/WxQidianServiceHttpComponentsImpl.java
similarity index 85%
rename from weixin-java-qidian/src/main/java/me/chanjar/weixin/qidian/api/impl/WxQidianServiceHttpClient5Impl.java
rename to weixin-java-qidian/src/main/java/me/chanjar/weixin/qidian/api/impl/WxQidianServiceHttpComponentsImpl.java
index cad20239a6..a5cc23f0a2 100644
--- a/weixin-java-qidian/src/main/java/me/chanjar/weixin/qidian/api/impl/WxQidianServiceHttpClient5Impl.java
+++ b/weixin-java-qidian/src/main/java/me/chanjar/weixin/qidian/api/impl/WxQidianServiceHttpComponentsImpl.java
@@ -3,9 +3,9 @@
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.error.WxRuntimeException;
 import me.chanjar.weixin.common.util.http.HttpClientType;
-import me.chanjar.weixin.common.util.http.hc5.ApacheBasicResponseHandler;
-import me.chanjar.weixin.common.util.http.hc5.ApacheHttpClientBuilder;
-import me.chanjar.weixin.common.util.http.hc5.DefaultApacheHttpClientBuilder;
+import me.chanjar.weixin.common.util.http.hc.BasicResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.DefaultHttpComponentsClientBuilder;
+import me.chanjar.weixin.common.util.http.hc.HttpComponentsClientBuilder;
 import me.chanjar.weixin.qidian.config.WxQidianConfigStorage;
 import org.apache.hc.client5.http.classic.methods.HttpGet;
 import org.apache.hc.client5.http.config.RequestConfig;
@@ -23,7 +23,7 @@
  *
  * @author altusea
  */
-public class WxQidianServiceHttpClient5Impl extends BaseWxQidianServiceImpl {
+public class WxQidianServiceHttpComponentsImpl extends BaseWxQidianServiceImpl {
   private CloseableHttpClient httpClient;
   private HttpHost httpProxy;
 
@@ -39,13 +39,13 @@ public HttpHost getRequestHttpProxy() {
 
   @Override
   public HttpClientType getRequestType() {
-    return HttpClientType.HTTP_CLIENT_5;
+    return HttpClientType.HTTP_COMPONENTS;
   }
 
   @Override
   public void initHttp() {
     WxQidianConfigStorage configStorage = this.getWxMpConfigStorage();
-    ApacheHttpClientBuilder apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get();
+    HttpComponentsClientBuilder apacheHttpClientBuilder = DefaultHttpComponentsClientBuilder.get();
 
     apacheHttpClientBuilder.httpProxyHost(configStorage.getHttpProxyHost())
         .httpProxyPort(configStorage.getHttpProxyPort()).httpProxyUsername(configStorage.getHttpProxyUsername())
@@ -82,7 +82,7 @@ public String getAccessToken(boolean forceRefresh) throws WxErrorException {
           RequestConfig requestConfig = RequestConfig.custom().setProxy(this.getRequestHttpProxy()).build();
           httpGet.setConfig(requestConfig);
         }
-        String responseContent = getRequestHttpClient().execute(httpGet, ApacheBasicResponseHandler.INSTANCE);
+        String responseContent = getRequestHttpClient().execute(httpGet, BasicResponseHandler.INSTANCE);
         return this.extractAccessToken(responseContent);
       } catch (IOException e) {
         throw new WxRuntimeException(e);

From 1753f1f500c2603fe7120ce9f802a56b44f0084e Mon Sep 17 00:00:00 2001
From: altusea 
Date: Sat, 7 Jun 2025 17:28:42 +0800
Subject: [PATCH 30/31] add

---
 ...tpChannelMediaDownloadRequestExecutor.java | 90 +++++++++++++++++
 .../ChannelMediaDownloadRequestExecutor.java  | 98 +++----------------
 ...tsChannelMediaDownloadRequestExecutor.java | 94 ++++++++++++++++++
 ...rDiscernHttpComponentsRequestExecutor.java | 46 +++++++++
 .../ocr/OcrDiscernRequestExecutor.java        |  8 +-
 .../BaseMediaDownloadRequestExecutor.java     | 17 ++--
 .../common/util/http/HttpClientType.java      |  2 +-
 ...MediaInputStreamUploadRequestExecutor.java | 12 ++-
 ...inishopUploadRequestCustomizeExecutor.java | 14 +--
 .../util/http/SimpleGetRequestExecutor.java   | 11 ++-
 .../util/http/SimplePostRequestExecutor.java  | 12 ++-
 .../ApiSignaturePostRequestExecutor.java      | 10 +-
 ...ponentsVodSingleUploadRequestExecutor.java | 59 +++++++++++
 ...omponentsVodUploadPartRequestExecutor.java | 52 ++++++++++
 .../executor/QrcodeBytesRequestExecutor.java  |  2 +-
 .../executor/QrcodeRequestExecutor.java       |  4 +-
 .../UploadAuthMaterialRequestExecutor.java    |  2 +-
 .../VodSingleUploadRequestExecutor.java       | 17 ++--
 .../VodUploadPartRequestExecutor.java         | 14 ++-
 .../MaterialDeleteRequestExecutor.java        |  2 +-
 .../MaterialNewsInfoRequestExecutor.java      | 13 ++-
 .../MaterialUploadRequestExecutor.java        |  2 +-
 .../MaterialVideoInfoRequestExecutor.java     |  2 +-
 ...lVoiceAndImageDownloadRequestExecutor.java |  2 +-
 .../media/MediaImgUploadRequestExecutor.java  |  2 +-
 .../voice/VoiceUploadRequestExecutor.java     |  9 +-
 26 files changed, 446 insertions(+), 150 deletions(-)
 create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/ApacheHttpChannelMediaDownloadRequestExecutor.java
 create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/HttpComponentsChannelMediaDownloadRequestExecutor.java
 create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/requestexecuter/ocr/OcrDiscernHttpComponentsRequestExecutor.java
 create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpComponentsVodSingleUploadRequestExecutor.java
 create mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpComponentsVodUploadPartRequestExecutor.java

diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/ApacheHttpChannelMediaDownloadRequestExecutor.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/ApacheHttpChannelMediaDownloadRequestExecutor.java
new file mode 100644
index 0000000000..b9b44b60e2
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/ApacheHttpChannelMediaDownloadRequestExecutor.java
@@ -0,0 +1,90 @@
+package me.chanjar.weixin.channel.executor;
+
+import me.chanjar.weixin.channel.bean.image.ChannelImageResponse;
+import me.chanjar.weixin.channel.util.JsonUtils;
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.ResponseHandler;
+import me.chanjar.weixin.common.util.http.apache.InputStreamResponseHandler;
+import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.Header;
+import org.apache.http.HttpHost;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.entity.ContentType;
+import org.apache.http.impl.client.CloseableHttpClient;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class ApacheHttpChannelMediaDownloadRequestExecutor extends ChannelMediaDownloadRequestExecutor {
+
+  public ApacheHttpChannelMediaDownloadRequestExecutor(RequestHttp requestHttp, File tmpDirFile) {
+    super(requestHttp, tmpDirFile);
+  }
+
+  @Override
+  public ChannelImageResponse execute(String uri, String data, WxType wxType) throws WxErrorException, IOException {
+    if (data != null) {
+      if (uri.indexOf('?') == -1) {
+        uri += '?';
+      }
+      uri += uri.endsWith("?") ? data : '&' + data;
+    }
+
+    HttpGet httpGet = new HttpGet(uri);
+    if (requestHttp.getRequestHttpProxy() != null) {
+      RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
+      httpGet.setConfig(config);
+    }
+
+    try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpGet);
+         InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response)) {
+      Header[] contentTypeHeader = response.getHeaders("Content-Type");
+      String contentType = null;
+      if (contentTypeHeader != null && contentTypeHeader.length > 0) {
+        contentType = contentTypeHeader[0].getValue();
+        if (contentType.startsWith(ContentType.APPLICATION_JSON.getMimeType())) {
+          // application/json; encoding=utf-8 下载媒体文件出错
+          String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
+          return JsonUtils.decode(responseContent, ChannelImageResponse.class);
+        }
+      }
+
+      String fileName = this.getFileName(response);
+      if (StringUtils.isBlank(fileName)) {
+        fileName = String.valueOf(System.currentTimeMillis());
+      }
+
+      String baseName = FilenameUtils.getBaseName(fileName);
+      if (StringUtils.isBlank(fileName) || baseName.length() < 3) {
+        baseName = String.valueOf(System.currentTimeMillis());
+      }
+      String extension = FilenameUtils.getExtension(fileName);
+      if (StringUtils.isBlank(extension)) {
+        extension = "unknown";
+      }
+      File file = createTmpFile(inputStream, baseName, extension, tmpDirFile);
+      return new ChannelImageResponse(file, contentType);
+    }
+  }
+
+  private String getFileName(CloseableHttpResponse response) throws WxErrorException {
+    Header[] contentDispositionHeader = response.getHeaders("Content-disposition");
+    if (contentDispositionHeader == null || contentDispositionHeader.length == 0) {
+      return createDefaultFileName();
+    }
+    return this.extractFileNameFromContentString(contentDispositionHeader[0].getValue());
+  }
+
+  @Override
+  public void execute(String uri, String data, ResponseHandler handler, WxType wxType)
+    throws WxErrorException, IOException {
+    handler.handle(this.execute(uri, data, wxType));
+  }
+}
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/ChannelMediaDownloadRequestExecutor.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/ChannelMediaDownloadRequestExecutor.java
index bb771a2560..dd4bf0ba89 100644
--- a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/ChannelMediaDownloadRequestExecutor.java
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/ChannelMediaDownloadRequestExecutor.java
@@ -1,25 +1,9 @@
 package me.chanjar.weixin.channel.executor;
 
-import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.channel.bean.image.ChannelImageResponse;
-import me.chanjar.weixin.channel.util.JsonUtils;
-import me.chanjar.weixin.common.enums.WxType;
-import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.RequestExecutor;
 import me.chanjar.weixin.common.util.http.RequestHttp;
-import me.chanjar.weixin.common.util.http.ResponseHandler;
-import me.chanjar.weixin.common.util.http.apache.InputStreamResponseHandler;
-import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler;
-import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.http.Header;
-import org.apache.http.HttpHost;
-import org.apache.http.client.config.RequestConfig;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.entity.ContentType;
-import org.apache.http.impl.client.CloseableHttpClient;
 
 import java.io.File;
 import java.io.IOException;
@@ -36,77 +20,29 @@
  *
  * @author Zeyes
  */
-@Slf4j
-public class ChannelMediaDownloadRequestExecutor implements RequestExecutor {
+public abstract class ChannelMediaDownloadRequestExecutor implements RequestExecutor {
 
-  protected RequestHttp requestHttp;
+  protected RequestHttp requestHttp;
   protected File tmpDirFile;
 
   private static final Pattern PATTERN = Pattern.compile(".*filename=\"(.*)\"");
 
-  public ChannelMediaDownloadRequestExecutor(RequestHttp requestHttp, File tmpDirFile) {
+  public ChannelMediaDownloadRequestExecutor(RequestHttp requestHttp, File tmpDirFile) {
     this.requestHttp = requestHttp;
     this.tmpDirFile = tmpDirFile;
   }
 
-  @Override
-  public ChannelImageResponse execute(String uri, String data, WxType wxType) throws WxErrorException, IOException {
-    if (data != null) {
-      if (uri.indexOf('?') == -1) {
-        uri += '?';
-      }
-      uri += uri.endsWith("?") ? data : '&' + data;
-    }
-
-    HttpGet httpGet = new HttpGet(uri);
-    if (requestHttp.getRequestHttpProxy() != null) {
-      RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
-      httpGet.setConfig(config);
-    }
-
-    try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpGet);
-      InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response)) {
-      Header[] contentTypeHeader = response.getHeaders("Content-Type");
-      String contentType = null;
-      if (contentTypeHeader != null && contentTypeHeader.length > 0) {
-        contentType = contentTypeHeader[0].getValue();
-        if (contentType.startsWith(ContentType.APPLICATION_JSON.getMimeType())) {
-          // application/json; encoding=utf-8 下载媒体文件出错
-          String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
-          return JsonUtils.decode(responseContent, ChannelImageResponse.class);
-        }
-      }
-
-      String fileName = this.getFileName(response);
-      if (StringUtils.isBlank(fileName)) {
-        fileName = String.valueOf(System.currentTimeMillis());
-      }
-
-      String baseName = FilenameUtils.getBaseName(fileName);
-      if (StringUtils.isBlank(fileName) || baseName.length() < 3) {
-        baseName = String.valueOf(System.currentTimeMillis());
-      }
-      String extension = FilenameUtils.getExtension(fileName);
-      if (StringUtils.isBlank(extension)) {
-        extension = "unknown";
-      }
-      File file = createTmpFile(inputStream, baseName, extension, tmpDirFile);
-      return new ChannelImageResponse(file, contentType);
-    }
-  }
-
-  @Override
-  public void execute(String uri, String data, ResponseHandler handler, WxType wxType)
-    throws WxErrorException, IOException {
-    handler.handle(this.execute(uri, data, wxType));
-  }
-
-  public static RequestExecutor create(RequestHttp requestHttp, File tmpDirFile) throws WxErrorException {
+  @SuppressWarnings("unchecked")
+  public static RequestExecutor create(RequestHttp requestHttp, File tmpDirFile) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new ChannelMediaDownloadRequestExecutor((RequestHttp) requestHttp, tmpDirFile);
+        return new ApacheHttpChannelMediaDownloadRequestExecutor(
+          (RequestHttp) requestHttp, tmpDirFile);
+      case HTTP_COMPONENTS:
+        return new HttpComponentsChannelMediaDownloadRequestExecutor(
+          (RequestHttp) requestHttp, tmpDirFile);
       default:
-        throw new WxErrorException("不支持的http框架");
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 
@@ -128,19 +64,11 @@ public static File createTmpFile(InputStream inputStream, String name, String ex
     return resultFile;
   }
 
-  private String getFileName(CloseableHttpResponse response) throws WxErrorException {
-    Header[] contentDispositionHeader = response.getHeaders("Content-disposition");
-    if (contentDispositionHeader == null || contentDispositionHeader.length == 0) {
-      return createDefaultFileName();
-    }
-    return this.extractFileNameFromContentString(contentDispositionHeader[0].getValue());
-  }
-
-  private String createDefaultFileName() {
+  protected String createDefaultFileName() {
     return UUID.randomUUID().toString();
   }
 
-  private String extractFileNameFromContentString(String content) throws WxErrorException {
+  protected String extractFileNameFromContentString(String content) {
     if (content == null || content.isEmpty()) {
       return createDefaultFileName();
     }
diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/HttpComponentsChannelMediaDownloadRequestExecutor.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/HttpComponentsChannelMediaDownloadRequestExecutor.java
new file mode 100644
index 0000000000..95a13f6c86
--- /dev/null
+++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/executor/HttpComponentsChannelMediaDownloadRequestExecutor.java
@@ -0,0 +1,94 @@
+package me.chanjar.weixin.channel.executor;
+
+import me.chanjar.weixin.channel.bean.image.ChannelImageResponse;
+import me.chanjar.weixin.channel.util.JsonUtils;
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.ResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.InputStreamResponseHandler;
+import me.chanjar.weixin.common.util.http.hc.Utf8ResponseHandler;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.hc.client5.http.ClientProtocolException;
+import org.apache.hc.client5.http.classic.methods.HttpGet;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpHost;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class HttpComponentsChannelMediaDownloadRequestExecutor extends ChannelMediaDownloadRequestExecutor {
+
+  public HttpComponentsChannelMediaDownloadRequestExecutor(RequestHttp requestHttp, File tmpDirFile) {
+    super(requestHttp, tmpDirFile);
+  }
+
+  @Override
+  public ChannelImageResponse execute(String uri, String data, WxType wxType) throws WxErrorException, IOException {
+    if (data != null) {
+      if (uri.indexOf('?') == -1) {
+        uri += '?';
+      }
+      uri += uri.endsWith("?") ? data : '&' + data;
+    }
+
+    HttpGet httpGet = new HttpGet(uri);
+    if (requestHttp.getRequestHttpProxy() != null) {
+      RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
+      httpGet.setConfig(config);
+    }
+
+    try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpGet);
+         InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response)) {
+      Header[] contentTypeHeader = response.getHeaders("Content-Type");
+      String contentType = null;
+      if (contentTypeHeader != null && contentTypeHeader.length > 0) {
+        contentType = contentTypeHeader[0].getValue();
+        if (contentType.startsWith(ContentType.APPLICATION_JSON.getMimeType())) {
+          // application/json; encoding=utf-8 下载媒体文件出错
+          String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
+          return JsonUtils.decode(responseContent, ChannelImageResponse.class);
+        }
+      }
+
+      String fileName = this.getFileName(response);
+      if (StringUtils.isBlank(fileName)) {
+        fileName = String.valueOf(System.currentTimeMillis());
+      }
+
+      String baseName = FilenameUtils.getBaseName(fileName);
+      if (StringUtils.isBlank(fileName) || baseName.length() < 3) {
+        baseName = String.valueOf(System.currentTimeMillis());
+      }
+      String extension = FilenameUtils.getExtension(fileName);
+      if (StringUtils.isBlank(extension)) {
+        extension = "unknown";
+      }
+      File file = createTmpFile(inputStream, baseName, extension, tmpDirFile);
+      return new ChannelImageResponse(file, contentType);
+    } catch (HttpException httpException) {
+      throw new ClientProtocolException(httpException.getMessage(), httpException);
+    }
+  }
+
+  private String getFileName(CloseableHttpResponse response) throws WxErrorException {
+    Header[] contentDispositionHeader = response.getHeaders("Content-disposition");
+    if (contentDispositionHeader == null || contentDispositionHeader.length == 0) {
+      return createDefaultFileName();
+    }
+    return this.extractFileNameFromContentString(contentDispositionHeader[0].getValue());
+  }
+
+  @Override
+  public void execute(String uri, String data, ResponseHandler handler, WxType wxType)
+    throws WxErrorException, IOException {
+    handler.handle(this.execute(uri, data, wxType));
+  }
+}
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/requestexecuter/ocr/OcrDiscernHttpComponentsRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/requestexecuter/ocr/OcrDiscernHttpComponentsRequestExecutor.java
new file mode 100644
index 0000000000..2d02c965a8
--- /dev/null
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/requestexecuter/ocr/OcrDiscernHttpComponentsRequestExecutor.java
@@ -0,0 +1,46 @@
+package me.chanjar.weixin.common.requestexecuter.ocr;
+
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxError;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.hc.Utf8ResponseHandler;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
+import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.core5.http.HttpEntity;
+import org.apache.hc.core5.http.HttpHost;
+
+import java.io.File;
+import java.io.IOException;
+
+public class OcrDiscernHttpComponentsRequestExecutor extends OcrDiscernRequestExecutor {
+  public OcrDiscernHttpComponentsRequestExecutor(RequestHttp requestHttp) {
+    super(requestHttp);
+  }
+
+  @Override
+  public String execute(String uri, File file, WxType wxType) throws WxErrorException, IOException {
+    HttpPost httpPost = new HttpPost(uri);
+    if (requestHttp.getRequestHttpProxy() != null) {
+      RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
+      httpPost.setConfig(config);
+    }
+    if (file != null) {
+      HttpEntity entity = MultipartEntityBuilder
+        .create()
+        .addBinaryBody("file", file)
+        .setMode(HttpMultipartMode.EXTENDED)
+        .build();
+      httpPost.setEntity(entity);
+    }
+    String responseContent = requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
+    WxError error = WxError.fromJson(responseContent, wxType);
+    if (error.getErrorCode() != 0) {
+      throw new WxErrorException(error);
+    }
+    return responseContent;
+  }
+}
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/requestexecuter/ocr/OcrDiscernRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/requestexecuter/ocr/OcrDiscernRequestExecutor.java
index 58e525bc0e..542ab4a378 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/requestexecuter/ocr/OcrDiscernRequestExecutor.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/requestexecuter/ocr/OcrDiscernRequestExecutor.java
@@ -33,9 +33,13 @@ public void execute(String uri, File data, ResponseHandler handler, WxTy
   public static RequestExecutor create(RequestHttp requestHttp) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new OcrDiscernApacheHttpRequestExecutor((RequestHttp) requestHttp);
+        return new OcrDiscernApacheHttpRequestExecutor(
+          (RequestHttp) requestHttp);
+      case HTTP_COMPONENTS:
+        return new OcrDiscernHttpComponentsRequestExecutor(
+          (RequestHttp) requestHttp);
       default:
-        return null;
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 }
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/BaseMediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/BaseMediaDownloadRequestExecutor.java
index fa60d364b0..8304742524 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/BaseMediaDownloadRequestExecutor.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/BaseMediaDownloadRequestExecutor.java
@@ -1,19 +1,18 @@
 package me.chanjar.weixin.common.util.http;
 
-import java.io.File;
-import java.io.IOException;
-
 import jodd.http.HttpConnectionProvider;
 import jodd.http.ProxyInfo;
 import me.chanjar.weixin.common.enums.WxType;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.apache.ApacheMediaDownloadRequestExecutor;
+import me.chanjar.weixin.common.util.http.hc.HttpComponentsMediaDownloadRequestExecutor;
 import me.chanjar.weixin.common.util.http.jodd.JoddHttpMediaDownloadRequestExecutor;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpMediaDownloadRequestExecutor;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
 import okhttp3.OkHttpClient;
-import org.apache.http.HttpHost;
-import org.apache.http.impl.client.CloseableHttpClient;
+
+import java.io.File;
+import java.io.IOException;
 
 /**
  * 下载媒体文件请求执行器.
@@ -40,13 +39,17 @@ public void execute(String uri, String data, ResponseHandler handler, WxTy
   public static RequestExecutor create(RequestHttp requestHttp, File tmpDirFile) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new ApacheMediaDownloadRequestExecutor((RequestHttp) requestHttp, tmpDirFile);
+        return new ApacheMediaDownloadRequestExecutor(
+          (RequestHttp) requestHttp, tmpDirFile);
       case JODD_HTTP:
         return new JoddHttpMediaDownloadRequestExecutor((RequestHttp) requestHttp, tmpDirFile);
       case OK_HTTP:
         return new OkHttpMediaDownloadRequestExecutor((RequestHttp) requestHttp, tmpDirFile);
+      case HTTP_COMPONENTS:
+        return new HttpComponentsMediaDownloadRequestExecutor(
+          (RequestHttp) requestHttp, tmpDirFile);
       default:
-        return null;
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpClientType.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpClientType.java
index f309d0d852..a4e22be9b4 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpClientType.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpClientType.java
@@ -9,7 +9,7 @@ public enum HttpClientType {
    */
   JODD_HTTP,
   /**
-   * apache httpclient.
+   * apache httpclient 4.x.
    */
   APACHE_HTTP,
   /**
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaInputStreamUploadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaInputStreamUploadRequestExecutor.java
index cd92ba3b63..22c426ca54 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaInputStreamUploadRequestExecutor.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaInputStreamUploadRequestExecutor.java
@@ -6,12 +6,11 @@
 import me.chanjar.weixin.common.enums.WxType;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.apache.ApacheMediaInputStreamUploadRequestExecutor;
+import me.chanjar.weixin.common.util.http.hc.HttpComponentsMediaInputStreamUploadRequestExecutor;
 import me.chanjar.weixin.common.util.http.jodd.JoddHttpMediaInputStreamUploadRequestExecutor;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpMediaInputStreamUploadRequestExecutor;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
 import okhttp3.OkHttpClient;
-import org.apache.http.HttpHost;
-import org.apache.http.impl.client.CloseableHttpClient;
 
 import java.io.IOException;
 
@@ -33,16 +32,21 @@ public void execute(String uri, InputStreamData data, ResponseHandler create(RequestHttp requestHttp) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new ApacheMediaInputStreamUploadRequestExecutor((RequestHttp) requestHttp);
+        return new ApacheMediaInputStreamUploadRequestExecutor(
+          (RequestHttp) requestHttp);
       case JODD_HTTP:
         return new JoddHttpMediaInputStreamUploadRequestExecutor((RequestHttp) requestHttp);
       case OK_HTTP:
         return new OkHttpMediaInputStreamUploadRequestExecutor((RequestHttp) requestHttp);
+      case HTTP_COMPONENTS:
+        return new HttpComponentsMediaInputStreamUploadRequestExecutor(
+          (RequestHttp) requestHttp);
       default:
-        return null;
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MinishopUploadRequestCustomizeExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MinishopUploadRequestCustomizeExecutor.java
index 97d4e1b3b8..0e8684a1db 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MinishopUploadRequestCustomizeExecutor.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MinishopUploadRequestCustomizeExecutor.java
@@ -6,12 +6,11 @@
 import me.chanjar.weixin.common.enums.WxType;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.apache.ApacheMinishopMediaUploadRequestCustomizeExecutor;
+import me.chanjar.weixin.common.util.http.hc.HttpComponentsMinishopMediaUploadRequestCustomizeExecutor;
 import me.chanjar.weixin.common.util.http.jodd.JoddHttpMinishopMediaUploadRequestCustomizeExecutor;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpMinishopMediaUploadRequestCustomizeExecutor;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
 import okhttp3.OkHttpClient;
-import org.apache.http.HttpHost;
-import org.apache.http.impl.client.CloseableHttpClient;
 
 import java.io.File;
 import java.io.IOException;
@@ -27,8 +26,7 @@ public MinishopUploadRequestCustomizeExecutor(RequestHttp requestHttp, Str
     this.respType = respType;
     if (imgUrl == null || imgUrl.isEmpty()) {
       this.uploadType = "0";
-    }
-    else {
+    } else {
       this.uploadType = "1";
       this.imgUrl = imgUrl;
     }
@@ -43,13 +41,17 @@ public void execute(String uri, File data, ResponseHandler create(RequestHttp requestHttp, String respType, String imgUrl) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new ApacheMinishopMediaUploadRequestCustomizeExecutor((RequestHttp) requestHttp, respType, imgUrl);
+        return new ApacheMinishopMediaUploadRequestCustomizeExecutor(
+          (RequestHttp) requestHttp, respType, imgUrl);
       case JODD_HTTP:
         return new JoddHttpMinishopMediaUploadRequestCustomizeExecutor((RequestHttp) requestHttp, respType, imgUrl);
       case OK_HTTP:
         return new OkHttpMinishopMediaUploadRequestCustomizeExecutor((RequestHttp) requestHttp, respType, imgUrl);
+      case HTTP_COMPONENTS:
+        return new HttpComponentsMinishopMediaUploadRequestCustomizeExecutor(
+          (RequestHttp) requestHttp, respType, imgUrl);
       default:
-        return null;
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 }
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/SimpleGetRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/SimpleGetRequestExecutor.java
index 4f2ad64afc..a880a9323c 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/SimpleGetRequestExecutor.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/SimpleGetRequestExecutor.java
@@ -6,12 +6,11 @@
 import me.chanjar.weixin.common.error.WxError;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.apache.ApacheSimpleGetRequestExecutor;
+import me.chanjar.weixin.common.util.http.hc.HttpComponentsSimpleGetRequestExecutor;
 import me.chanjar.weixin.common.util.http.jodd.JoddHttpSimpleGetRequestExecutor;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpSimpleGetRequestExecutor;
 import okhttp3.OkHttpClient;
-import org.apache.http.HttpHost;
-import org.apache.http.impl.client.CloseableHttpClient;
 
 import java.io.IOException;
 
@@ -37,13 +36,17 @@ public void execute(String uri, String data, ResponseHandler handler, Wx
   public static RequestExecutor create(RequestHttp requestHttp) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new ApacheSimpleGetRequestExecutor((RequestHttp< CloseableHttpClient, HttpHost>) requestHttp);
+        return new ApacheSimpleGetRequestExecutor(
+          (RequestHttp) requestHttp);
       case JODD_HTTP:
         return new JoddHttpSimpleGetRequestExecutor((RequestHttp) requestHttp);
       case OK_HTTP:
         return new OkHttpSimpleGetRequestExecutor((RequestHttp) requestHttp);
+      case HTTP_COMPONENTS:
+        return new HttpComponentsSimpleGetRequestExecutor(
+          (RequestHttp) requestHttp);
       default:
-        throw new IllegalArgumentException("非法请求参数");
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/SimplePostRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/SimplePostRequestExecutor.java
index 68265ace52..2cc086cd0f 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/SimplePostRequestExecutor.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/SimplePostRequestExecutor.java
@@ -6,12 +6,11 @@
 import me.chanjar.weixin.common.error.WxError;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.apache.ApacheSimplePostRequestExecutor;
+import me.chanjar.weixin.common.util.http.hc.HttpComponentsSimplePostRequestExecutor;
 import me.chanjar.weixin.common.util.http.jodd.JoddHttpSimplePostRequestExecutor;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpSimplePostRequestExecutor;
 import okhttp3.OkHttpClient;
-import org.apache.http.HttpHost;
-import org.apache.http.impl.client.CloseableHttpClient;
 import org.jetbrains.annotations.NotNull;
 
 import java.io.IOException;
@@ -34,16 +33,21 @@ public void execute(String uri, String data, ResponseHandler handler, Wx
     handler.handle(this.execute(uri, data, wxType));
   }
 
+  @SuppressWarnings("unchecked")
   public static RequestExecutor create(RequestHttp requestHttp) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new ApacheSimplePostRequestExecutor((RequestHttp) requestHttp);
+        return new ApacheSimplePostRequestExecutor(
+          (RequestHttp) requestHttp);
       case JODD_HTTP:
         return new JoddHttpSimplePostRequestExecutor((RequestHttp) requestHttp);
       case OK_HTTP:
         return new OkHttpSimplePostRequestExecutor((RequestHttp) requestHttp);
+      case HTTP_COMPONENTS:
+        return new HttpComponentsSimplePostRequestExecutor(
+          (RequestHttp) requestHttp);
       default:
-        throw new IllegalArgumentException("非法请求参数");
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApiSignaturePostRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApiSignaturePostRequestExecutor.java
index e97e4b98f3..c01a7ab5de 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApiSignaturePostRequestExecutor.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApiSignaturePostRequestExecutor.java
@@ -1,10 +1,6 @@
 package cn.binarywang.wx.miniapp.executor;
 
 import cn.binarywang.wx.miniapp.bean.WxMaApiResponse;
-import java.io.IOException;
-import java.rmi.RemoteException;
-import java.util.Map;
-
 import jodd.http.HttpConnectionProvider;
 import jodd.http.ProxyInfo;
 import me.chanjar.weixin.common.enums.WxType;
@@ -17,6 +13,10 @@
 import okhttp3.OkHttpClient;
 import org.jetbrains.annotations.NotNull;
 
+import java.io.IOException;
+import java.rmi.RemoteException;
+import java.util.Map;
+
 public abstract class ApiSignaturePostRequestExecutor
     implements RequestExecutor {
 
@@ -73,7 +73,7 @@ public WxMaApiResponse handleResponse(
         return new HttpComponentsApiSignaturePostRequestExecutor(
           (RequestHttp) requestHttp);
       default:
-        throw new IllegalArgumentException("非法请求参数");
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 }
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpComponentsVodSingleUploadRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpComponentsVodSingleUploadRequestExecutor.java
new file mode 100644
index 0000000000..3f9139d459
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpComponentsVodSingleUploadRequestExecutor.java
@@ -0,0 +1,59 @@
+package cn.binarywang.wx.miniapp.executor;
+
+import cn.binarywang.wx.miniapp.bean.vod.WxMaVodSingleFileUploadResult;
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxError;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.hc.Utf8ResponseHandler;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
+import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.core5.http.HttpHost;
+
+import java.io.File;
+import java.io.IOException;
+
+public class HttpComponentsVodSingleUploadRequestExecutor extends VodSingleUploadRequestExecutor {
+
+  public HttpComponentsVodSingleUploadRequestExecutor(RequestHttp requestHttp, String mediaName, String mediaType, String coverType, File coverData, String sourceContext) {
+    super(requestHttp, mediaName, mediaType, coverType, coverData, sourceContext);
+  }
+
+  @Override
+  public WxMaVodSingleFileUploadResult execute(String uri, File file, WxType wxType) throws WxErrorException, IOException {
+    HttpPost httpPost = new HttpPost(uri);
+    if (requestHttp.getRequestHttpProxy() != null) {
+      RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
+      httpPost.setConfig(config);
+    }
+    if (file != null) {
+      MultipartEntityBuilder entityBuilder = MultipartEntityBuilder
+        .create()
+        .setMode(HttpMultipartMode.EXTENDED)
+        .addTextBody("media_name", mediaName)
+        .addTextBody("media_type", mediaType)
+        .addBinaryBody("media_data", file);
+
+      if (coverType != null) {
+        entityBuilder.addTextBody("cover_type", coverType);
+      }
+      if (coverData != null) {
+        entityBuilder.addBinaryBody("cover_data", coverData);
+      }
+      if (sourceContext != null) {
+        entityBuilder.addTextBody("source_context", sourceContext);
+      }
+
+      httpPost.setEntity(entityBuilder.build());
+    }
+    String responseContent = requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
+    WxError error = WxError.fromJson(responseContent, wxType);
+    if (error.getErrorCode() != 0) {
+      throw new WxErrorException(error);
+    }
+    return WxMaVodSingleFileUploadResult.fromJson(responseContent);
+  }
+}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpComponentsVodUploadPartRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpComponentsVodUploadPartRequestExecutor.java
new file mode 100644
index 0000000000..eb2cf8e9db
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/HttpComponentsVodUploadPartRequestExecutor.java
@@ -0,0 +1,52 @@
+package cn.binarywang.wx.miniapp.executor;
+
+import cn.binarywang.wx.miniapp.bean.vod.WxMaVodUploadPartResult;
+import me.chanjar.weixin.common.enums.WxType;
+import me.chanjar.weixin.common.error.WxError;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.http.RequestHttp;
+import me.chanjar.weixin.common.util.http.hc.Utf8ResponseHandler;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
+import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.core5.http.HttpHost;
+
+import java.io.File;
+import java.io.IOException;
+
+public class HttpComponentsVodUploadPartRequestExecutor extends VodUploadPartRequestExecutor {
+
+  public HttpComponentsVodUploadPartRequestExecutor(RequestHttp requestHttp, String uploadId, Integer partNumber, Integer resourceType) {
+    super(requestHttp, uploadId, partNumber, resourceType);
+
+  }
+
+  @Override
+  public WxMaVodUploadPartResult execute(String uri, File file, WxType wxType) throws WxErrorException, IOException {
+    HttpPost httpPost = new HttpPost(uri);
+    if (requestHttp.getRequestHttpProxy() != null) {
+      RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
+      httpPost.setConfig(config);
+    }
+    if (file != null) {
+      MultipartEntityBuilder entityBuilder = MultipartEntityBuilder
+        .create()
+        .setMode(HttpMultipartMode.EXTENDED)
+        .addTextBody("upload_id", uploadId)
+        .addTextBody("part_number", String.valueOf(partNumber))
+        .addTextBody("resource_type", String.valueOf(resourceType))
+        .addBinaryBody("data", file);
+
+      httpPost.setEntity(entityBuilder.build());
+    }
+
+    String responseContent = requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
+    WxError error = WxError.fromJson(responseContent, wxType);
+    if (error.getErrorCode() != 0) {
+      throw new WxErrorException(error);
+    }
+    return WxMaVodUploadPartResult.fromJson(responseContent);
+  }
+}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeBytesRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeBytesRequestExecutor.java
index 41f3dfbc10..4d95a6daae 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeBytesRequestExecutor.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeBytesRequestExecutor.java
@@ -39,7 +39,7 @@ public static RequestExecutor create(RequestH
         return new HttpComponentsQrcodeBytesRequestExecutor(
           (RequestHttp) requestHttp);
       default:
-        return null;
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 }
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeRequestExecutor.java
index be52c0cccf..ec1d0fd158 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeRequestExecutor.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/QrcodeRequestExecutor.java
@@ -41,7 +41,7 @@ public static RequestExecutor create(RequestHtt
         return new HttpComponentsQrcodeFileRequestExecutor(
           (RequestHttp) requestHttp, path);
       default:
-        return null;
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 
@@ -56,7 +56,7 @@ public static RequestExecutor create(RequestHtt
         return new HttpComponentsQrcodeFileRequestExecutor(
           (RequestHttp) requestHttp, null);
       default:
-        return null;
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 }
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/UploadAuthMaterialRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/UploadAuthMaterialRequestExecutor.java
index cc53afb2d0..4d232ced21 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/UploadAuthMaterialRequestExecutor.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/UploadAuthMaterialRequestExecutor.java
@@ -48,7 +48,7 @@ public static RequestExecutor create(Request
         return new HttpComponentsUploadAuthMaterialRequestExecutor(
           (RequestHttp) requestHttp);
       default:
-        return null;
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 }
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/VodSingleUploadRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/VodSingleUploadRequestExecutor.java
index 225a1658cf..578fc8949c 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/VodSingleUploadRequestExecutor.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/VodSingleUploadRequestExecutor.java
@@ -10,8 +10,6 @@
 import me.chanjar.weixin.common.util.http.ResponseHandler;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
 import okhttp3.OkHttpClient;
-import org.apache.http.HttpHost;
-import org.apache.http.impl.client.CloseableHttpClient;
 
 import java.io.File;
 import java.io.IOException;
@@ -43,16 +41,24 @@ public VodSingleUploadRequestExecutor(RequestHttp requestHttp, String medi
 
   }
 
+  @SuppressWarnings("unchecked")
   public static RequestExecutor create(RequestHttp requestHttp, String mediaName, String mediaType, String coverType, File coverData, String sourceContext) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new ApacheVodSingleUploadRequestExecutor((RequestHttp) requestHttp, mediaName, mediaType, coverType, coverData, sourceContext);
+        return new ApacheVodSingleUploadRequestExecutor(
+          (RequestHttp) requestHttp,
+          mediaName, mediaType, coverType, coverData, sourceContext);
       case JODD_HTTP:
         return new JoddHttpVodSingleUploadRequestExecutor((RequestHttp) requestHttp, mediaName, mediaType, coverType, coverData, sourceContext);
       case OK_HTTP:
-        return new OkHttpVodSingleUploadRequestExecutor((RequestHttp) requestHttp, mediaName, mediaType, coverType, coverData, sourceContext);
+        return new OkHttpVodSingleUploadRequestExecutor(
+          (RequestHttp) requestHttp, mediaName, mediaType, coverType, coverData, sourceContext);
+        case HTTP_COMPONENTS:
+          return new HttpComponentsVodSingleUploadRequestExecutor(
+            (RequestHttp) requestHttp,
+            mediaName, mediaType, coverType, coverData, sourceContext);
       default:
-        return null;
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 
@@ -61,5 +67,4 @@ public void execute(String uri, File data, ResponseHandler requestHttp, String upload
 
   }
 
+  @SuppressWarnings("unchecked")
   public static RequestExecutor create(RequestHttp requestHttp, String uploadId, Integer partNumber, Integer resourceType) {
     switch (requestHttp.getRequestType()) {
       case APACHE_HTTP:
-        return new ApacheVodUploadPartRequestExecutor((RequestHttp) requestHttp, uploadId, partNumber, resourceType);
+        return new ApacheVodUploadPartRequestExecutor(
+          (RequestHttp) requestHttp,
+          uploadId, partNumber, resourceType);
       case JODD_HTTP:
         return new JoddHttpVodUploadPartRequestExecutor((RequestHttp) requestHttp, uploadId, partNumber, resourceType);
       case OK_HTTP:
         return new OkHttpVodUploadPartRequestExecutor((RequestHttp) requestHttp, uploadId, partNumber, resourceType);
+      case HTTP_COMPONENTS:
+        return new HttpComponentsVodUploadPartRequestExecutor(
+          (RequestHttp) requestHttp,
+          uploadId, partNumber, resourceType);
       default:
-        return null;
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 
@@ -51,5 +56,4 @@ public void execute(String uri, File data, ResponseHandler create(RequestHttp requestH
         return new MaterialDeleteHttpComponentsRequestExecutor(
           (RequestHttp) requestHttp);
       default:
-        return null;
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoRequestExecutor.java
index 87ac96a397..ca06327abd 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialNewsInfoRequestExecutor.java
@@ -1,7 +1,5 @@
 package me.chanjar.weixin.mp.util.requestexecuter.material;
 
-import java.io.IOException;
-
 import jodd.http.HttpConnectionProvider;
 import jodd.http.ProxyInfo;
 import me.chanjar.weixin.common.enums.WxType;
@@ -13,6 +11,8 @@
 import me.chanjar.weixin.mp.bean.material.WxMpMaterialNews;
 import okhttp3.OkHttpClient;
 
+import java.io.IOException;
+
 public abstract class MaterialNewsInfoRequestExecutor implements RequestExecutor {
   protected RequestHttp requestHttp;
 
@@ -35,12 +35,11 @@ public static RequestExecutor create(RequestHttp
         return new MaterialNewsInfoJoddHttpRequestExecutor((RequestHttp) requestHttp);
       case OK_HTTP:
         return new MaterialNewsInfoOkhttpRequestExecutor((RequestHttp) requestHttp);
-        case HTTP_COMPONENTS:
-          return new MaterialNewsInfoHttpComponentsRequestExecutor(
-            (RequestHttp) requestHttp);
+      case HTTP_COMPONENTS:
+        return new MaterialNewsInfoHttpComponentsRequestExecutor(
+          (RequestHttp) requestHttp);
       default:
-        //TODO 需要优化抛出异常
-        return null;
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadRequestExecutor.java
index 0317f0588c..76ad3f88fa 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadRequestExecutor.java
@@ -43,7 +43,7 @@ public static RequestExecutor create(Req
         return new MaterialUploadHttpComponentsRequestExecutor(
           (RequestHttp) requestHttp);
       default:
-        return null;
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoRequestExecutor.java
index 3c265dc26f..b4073c7fec 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVideoInfoRequestExecutor.java
@@ -39,7 +39,7 @@ public static RequestExecutor create(Reques
         return new MaterialVideoInfoHttpComponentsRequestExecutor(
           (RequestHttp) requestHttp);
       default:
-        return null;
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadRequestExecutor.java
index 5ad8ebd1f6..42994a7423 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialVoiceAndImageDownloadRequestExecutor.java
@@ -42,7 +42,7 @@ public static RequestExecutor create(RequestHttp requ
         return new MaterialVoiceAndImageDownloadHttpComponentsRequestExecutor(
           (RequestHttp) requestHttp, tmpDirFile);
       default:
-        return null;
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadRequestExecutor.java
index 039093f97b..40a9d47155 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/media/MediaImgUploadRequestExecutor.java
@@ -43,7 +43,7 @@ public static RequestExecutor create(RequestHttp) requestHttp);
       default:
-        return null;
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadRequestExecutor.java
index bdbd029303..e8eb7cb9e9 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/voice/VoiceUploadRequestExecutor.java
@@ -1,14 +1,14 @@
 package me.chanjar.weixin.mp.util.requestexecuter.voice;
 
-import java.io.File;
-import java.io.IOException;
-
 import me.chanjar.weixin.common.enums.WxType;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.RequestExecutor;
 import me.chanjar.weixin.common.util.http.RequestHttp;
 import me.chanjar.weixin.common.util.http.ResponseHandler;
 
+import java.io.File;
+import java.io.IOException;
+
 /**
  * 
  *  Created by BinaryWang on 2018/6/9.
@@ -37,9 +37,8 @@ public static RequestExecutor create(RequestHttp requestHtt
       case HTTP_COMPONENTS:
         return new VoiceUploadHttpComponentsRequestExecutor(
           (RequestHttp) requestHttp);
-      case OK_HTTP:
       default:
-        return null;
+        throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
     }
   }
 

From c74ce6078204c6a95fb17d22f5600ba4e823464d Mon Sep 17 00:00:00 2001
From: altusea 
Date: Sat, 7 Jun 2025 18:42:36 +0800
Subject: [PATCH 31/31] polish

---
 .../util/http/apache/ApacheSimplePostRequestExecutor.java | 6 +++---
 .../service/impl/WxCpTpServiceApacheHttpClientImpl.java   | 4 ++--
 .../executor/ApacheApiSignaturePostRequestExecutor.java   | 8 +++-----
 .../material/MaterialUploadApacheHttpRequestExecutor.java | 4 ++--
 .../CommonUploadMultiRequestExecutorApacheImpl.java       | 4 ++--
 .../CommonUploadMultiRequestExecutorJoddHttpImpl.java     | 5 ++---
 6 files changed, 14 insertions(+), 17 deletions(-)

diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheSimplePostRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheSimplePostRequestExecutor.java
index 410e30d5d7..65af81690d 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheSimplePostRequestExecutor.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheSimplePostRequestExecutor.java
@@ -4,14 +4,15 @@
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.RequestHttp;
 import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
-import org.apache.http.Consts;
 import org.apache.http.HttpHost;
 import org.apache.http.client.config.RequestConfig;
 import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
 import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.CloseableHttpClient;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 
 /**
  * .
@@ -33,8 +34,7 @@ public String execute(String uri, String postEntity, WxType wxType) throws WxErr
     }
 
     if (postEntity != null) {
-      StringEntity entity = new StringEntity(postEntity, Consts.UTF_8);
-      entity.setContentType("application/json; charset=utf-8");
+      StringEntity entity = new StringEntity(postEntity, ContentType.APPLICATION_JSON.withCharset(StandardCharsets.UTF_8));
       httpPost.setEntity(entity);
     }
 
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpServiceApacheHttpClientImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpServiceApacheHttpClientImpl.java
index 449ca5b6b5..a5948a99c4 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpServiceApacheHttpClientImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpServiceApacheHttpClientImpl.java
@@ -12,7 +12,6 @@
 import me.chanjar.weixin.common.util.json.GsonParser;
 import me.chanjar.weixin.cp.config.WxCpTpConfigStorage;
 import me.chanjar.weixin.cp.constant.WxCpApiPathConsts;
-import org.apache.http.Consts;
 import org.apache.http.HttpHost;
 import org.apache.http.client.config.RequestConfig;
 import org.apache.http.client.methods.HttpPost;
@@ -20,6 +19,7 @@
 import org.apache.http.impl.client.CloseableHttpClient;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 
 /**
  * The type Wx cp tp service apache http client.
@@ -63,7 +63,7 @@ public String getSuiteAccessToken(boolean forceRefresh) throws WxErrorException
         jsonObject.addProperty("suite_id", this.configStorage.getSuiteId());
         jsonObject.addProperty("suite_secret", this.configStorage.getSuiteSecret());
         jsonObject.addProperty("suite_ticket", this.getSuiteTicket());
-        StringEntity entity = new StringEntity(jsonObject.toString(), Consts.UTF_8);
+        StringEntity entity = new StringEntity(jsonObject.toString(), StandardCharsets.UTF_8);
         httpPost.setEntity(entity);
 
         String resultContent = getRequestHttpClient().execute(httpPost, ApacheBasicResponseHandler.INSTANCE);
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApacheApiSignaturePostRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApacheApiSignaturePostRequestExecutor.java
index 3d85a412ec..0a858256a8 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApacheApiSignaturePostRequestExecutor.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApacheApiSignaturePostRequestExecutor.java
@@ -5,18 +5,17 @@
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.RequestHttp;
 import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler;
-import org.apache.http.Consts;
 import org.apache.http.Header;
 import org.apache.http.HttpHost;
 import org.apache.http.client.config.RequestConfig;
 import org.apache.http.client.methods.CloseableHttpResponse;
 import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
 import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.CloseableHttpClient;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -47,8 +46,7 @@ public WxMaApiResponse execute(
     }
 
     if (postEntity != null) {
-      StringEntity entity = new StringEntity(postEntity, Consts.UTF_8);
-      entity.setContentType("application/json; charset=utf-8");
+      StringEntity entity = new StringEntity(postEntity, ContentType.APPLICATION_JSON.withCharset(StandardCharsets.UTF_8));
       httpPost.setEntity(entity);
     }
 
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadApacheHttpRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadApacheHttpRequestExecutor.java
index f4d354b0a4..bf1b42fb9b 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadApacheHttpRequestExecutor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/requestexecuter/material/MaterialUploadApacheHttpRequestExecutor.java
@@ -8,7 +8,6 @@
 import me.chanjar.weixin.common.util.json.WxGsonBuilder;
 import me.chanjar.weixin.mp.bean.material.WxMpMaterial;
 import me.chanjar.weixin.mp.bean.material.WxMpMaterialUploadResult;
-import org.apache.http.Consts;
 import org.apache.http.HttpHost;
 import org.apache.http.client.config.RequestConfig;
 import org.apache.http.client.methods.CloseableHttpResponse;
@@ -22,6 +21,7 @@
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.Map;
 
 /**
@@ -56,7 +56,7 @@ public WxMpMaterialUploadResult execute(String uri, WxMpMaterial material, WxTyp
     Map form = material.getForm();
     if (material.getForm() != null) {
       multipartEntityBuilder.addPart("description",
-        new StringBody(WxGsonBuilder.create().toJson(form), ContentType.create("text/plain", Consts.UTF_8)));
+        new StringBody(WxGsonBuilder.create().toJson(form), ContentType.TEXT_PLAIN.withCharset(StandardCharsets.UTF_8)));
     }
     httpPost.setEntity(multipartEntityBuilder.build());
 
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutorApacheImpl.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutorApacheImpl.java
index fab126a7bd..5717ded51e 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutorApacheImpl.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutorApacheImpl.java
@@ -10,7 +10,6 @@
 import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler;
 import me.chanjar.weixin.open.bean.CommonUploadMultiParam;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.http.Consts;
 import org.apache.http.HttpHost;
 import org.apache.http.client.config.RequestConfig;
 import org.apache.http.client.methods.HttpPost;
@@ -24,6 +23,7 @@
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.List;
 
 /**
@@ -50,7 +50,7 @@ public String execute(String uri, CommonUploadMultiParam param, WxType wxType) t
       List normalParams = param.getNormalParams();
       if (!CollectionUtils.isEmpty(normalParams)) {
         for (CommonUploadMultiParam.NormalParam normalParam : normalParams) {
-          entity.addPart(normalParam.getName(), new StringBody(normalParam.getValue(), ContentType.create("multipart/form-data", Consts.UTF_8)));
+          entity.addPart(normalParam.getName(), new StringBody(normalParam.getValue(), ContentType.MULTIPART_FORM_DATA.withCharset(StandardCharsets.UTF_8)));
         }
       }
 
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutorJoddHttpImpl.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutorJoddHttpImpl.java
index 1650c16740..8b2e801e51 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutorJoddHttpImpl.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/executor/CommonUploadMultiRequestExecutorJoddHttpImpl.java
@@ -9,13 +9,12 @@
 import lombok.Getter;
 import lombok.SneakyThrows;
 import me.chanjar.weixin.common.bean.CommonUploadData;
-import me.chanjar.weixin.open.bean.CommonUploadMultiParam;
 import me.chanjar.weixin.common.bean.CommonUploadParam;
 import me.chanjar.weixin.common.enums.WxType;
 import me.chanjar.weixin.common.error.WxError;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.RequestHttp;
-import org.apache.http.Consts;
+import me.chanjar.weixin.open.bean.CommonUploadMultiParam;
 import org.apache.http.entity.ContentType;
 import org.apache.http.entity.mime.content.StringBody;
 import org.springframework.util.CollectionUtils;
@@ -47,7 +46,7 @@ public String execute(String uri, CommonUploadMultiParam param, WxType wxType) t
     List normalParams = param.getNormalParams();
     if (!CollectionUtils.isEmpty(normalParams)) {
       for (CommonUploadMultiParam.NormalParam normalParam : normalParams) {
-        request.form(normalParam.getName(), new StringBody(normalParam.getValue(), ContentType.create("multipart/form-data", Consts.UTF_8)));
+        request.form(normalParam.getName(), new StringBody(normalParam.getValue(), ContentType.MULTIPART_FORM_DATA.withCharset(StandardCharsets.UTF_8)));
       }
     }