From 7553130cd5f906ec35c20db8a66834fdfd00e34c Mon Sep 17 00:00:00 2001 From: ecoolper Date: Tue, 18 Apr 2017 17:29:13 +0800 Subject: [PATCH 01/27] weixin-java-tools usage jodd-http --- .../wxpay/service/impl/WxPayServiceImplTest.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImplTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImplTest.java index 93b0b8b5..b59bd1eb 100644 --- a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImplTest.java +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImplTest.java @@ -1,5 +1,7 @@ package com.github.binarywang.wxpay.service.impl; +import static org.testng.Assert.*; + import com.github.binarywang.utils.qrcode.QrcodeUtils; import com.github.binarywang.wxpay.bean.request.*; import com.github.binarywang.wxpay.bean.result.*; @@ -10,15 +12,14 @@ import com.google.inject.Inject; import me.chanjar.weixin.common.exception.WxErrorException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.testng.annotations.*; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.util.Map; -import static org.testng.Assert.*; - /** * 测试支付相关接口 * Created by Binary Wang on 2016/7/28. @@ -264,4 +265,5 @@ public class WxPayServiceImplTest { this.logger.info(result); } + } From 30cdad539c33b103cb9b79e5aaf7815e844b299d Mon Sep 17 00:00:00 2001 From: ecoolper Date: Tue, 18 Apr 2017 17:33:11 +0800 Subject: [PATCH 02/27] weixin-java-tools pay usage jodd-http --- .../wxpay/service/impl/WxPayServiceImpl.java | 34 +++++-------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImpl.java index c26d0583..ed609c23 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImpl.java @@ -9,27 +9,19 @@ import com.github.binarywang.wxpay.util.SignUtils; import com.google.common.collect.Maps; import jodd.http.HttpRequest; import jodd.http.HttpResponse; +import jodd.http.net.SSLSocketHttpConnectionProvider; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import org.apache.commons.lang3.CharEncoding; import org.apache.commons.lang3.StringUtils; -import org.apache.http.Consts; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.conn.ssl.DefaultHostnameVerifier; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.net.ssl.SSLContext; import java.io.File; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Map; +import javax.net.ssl.SSLContext; /** * Created by Binary Wang on 2016/7/28. @@ -384,6 +376,7 @@ public class WxPayServiceImpl implements WxPayService { /** * 由于暂时未找到使用jodd-http实现证书配置的办法,故而暂时使用httpclient + * ecoolper(20170418),修改为jodd-http方式 */ private String postWithKey(String url, String requestStr) throws WxErrorException { try { @@ -392,21 +385,12 @@ public class WxPayServiceImpl implements WxPayService { sslContext = this.getConfig().initSSLContext(); } - SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, - new String[]{"TLSv1"}, null, new DefaultHostnameVerifier()); - - HttpPost httpPost = new HttpPost(url); - - try (CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build()) { - httpPost.setEntity(new StringEntity(new String(requestStr.getBytes(CharEncoding.UTF_8), CharEncoding.ISO_8859_1))); - try (CloseableHttpResponse response = httpclient.execute(httpPost)) { - String result = EntityUtils.toString(response.getEntity(), Consts.UTF_8); - this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", url, requestStr, result); - return result; - } - } finally { - httpPost.releaseConnection(); - } + HttpRequest request =HttpRequest.post(url).withConnectionProvider(new SSLSocketHttpConnectionProvider(sslContext)); + request.bodyText(requestStr); + HttpResponse response =request.send(); + String result = response.bodyText(); + this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", url, requestStr, result); + return result; } catch (Exception e) { this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[EXCEPTION]: {}", url, requestStr, e.getMessage()); throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg(e.getMessage()).build(), e); From 0e6113b7658af6020b29e0b945b2a084d11ef740 Mon Sep 17 00:00:00 2001 From: ecoolper Date: Wed, 19 Apr 2017 10:39:06 +0800 Subject: [PATCH 03/27] =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../binarywang/wxpay/service/impl/WxPayServiceImpl.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImpl.java index ed609c23..2572f091 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImpl.java @@ -375,7 +375,6 @@ public class WxPayServiceImpl implements WxPayService { } /** - * 由于暂时未找到使用jodd-http实现证书配置的办法,故而暂时使用httpclient * ecoolper(20170418),修改为jodd-http方式 */ private String postWithKey(String url, String requestStr) throws WxErrorException { @@ -385,9 +384,9 @@ public class WxPayServiceImpl implements WxPayService { sslContext = this.getConfig().initSSLContext(); } - HttpRequest request =HttpRequest.post(url).withConnectionProvider(new SSLSocketHttpConnectionProvider(sslContext)); + HttpRequest request = HttpRequest.post(url).withConnectionProvider(new SSLSocketHttpConnectionProvider(sslContext)); request.bodyText(requestStr); - HttpResponse response =request.send(); + HttpResponse response = request.send(); String result = response.bodyText(); this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", url, requestStr, result); return result; From 897e13958707361effb6f0724f71d6899f0b4e0e Mon Sep 17 00:00:00 2001 From: ecoolper Date: Thu, 20 Apr 2017 17:34:45 +0800 Subject: [PATCH 04/27] jodd --- .../http/jodd/ApacheHttpClientBuilder.java | 53 ++++ .../jodd/DefaultApacheHttpClientBuilder.java | 292 ++++++++++++++++++ .../http/jodd/InputStreamResponseHandler.java | 28 ++ .../jodd/MediaDownloadRequestExecutor.java | 76 +++++ .../http/jodd/MediaUploadRequestExecutor.java | 39 +++ .../util/http/jodd/RequestExecutor.java | 25 ++ .../http/jodd/SimpleGetRequestExecutor.java | 43 +++ .../http/jodd/SimplePostRequestExecutor.java | 51 +++ .../weixin/common/util/http/jodd/URIUtil.java | 48 +++ .../util/http/jodd/Utf8ResponseHandler.java | 33 ++ 10 files changed, 688 insertions(+) create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/ApacheHttpClientBuilder.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/DefaultApacheHttpClientBuilder.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/InputStreamResponseHandler.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/MediaDownloadRequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/MediaUploadRequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/RequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimpleGetRequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimplePostRequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/URIUtil.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/Utf8ResponseHandler.java diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/ApacheHttpClientBuilder.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/ApacheHttpClientBuilder.java new file mode 100644 index 00000000..ce021a04 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/ApacheHttpClientBuilder.java @@ -0,0 +1,53 @@ +package me.chanjar.weixin.common.util.http.jodd; + +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.impl.client.CloseableHttpClient; + +/** + * httpclient build interface + * @author kakotor + */ +public interface ApacheHttpClientBuilder { + + /** + * 构建httpclient实例 + * + * @return new instance of CloseableHttpClient + */ + CloseableHttpClient build(); + + /** + * 代理服务器地址 + * + * @param httpProxyHost + */ + ApacheHttpClientBuilder httpProxyHost(String httpProxyHost); + + /** + * 代理服务器端口 + * + * @param httpProxyPort + */ + ApacheHttpClientBuilder httpProxyPort(int httpProxyPort); + + /** + * 代理服务器用户名 + * + * @param httpProxyUsername + */ + ApacheHttpClientBuilder httpProxyUsername(String httpProxyUsername); + + /** + * 代理服务器密码 + * + * @param httpProxyPassword + */ + ApacheHttpClientBuilder httpProxyPassword(String httpProxyPassword); + + /** + * ssl连接socket工厂 + * + * @param sslConnectionSocketFactory + */ + ApacheHttpClientBuilder sslConnectionSocketFactory(SSLConnectionSocketFactory sslConnectionSocketFactory); +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/DefaultApacheHttpClientBuilder.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/DefaultApacheHttpClientBuilder.java new file mode 100644 index 00000000..3f667abe --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/DefaultApacheHttpClientBuilder.java @@ -0,0 +1,292 @@ +package me.chanjar.weixin.common.util.http.jodd; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.annotation.NotThreadSafe; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.HttpRequestRetryHandler; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.config.SocketConfig; +import org.apache.http.conn.HttpClientConnectionManager; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +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.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.protocol.HttpContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * httpclient 连接管理器 + * + * @author kakotor + */ +@NotThreadSafe +public class DefaultApacheHttpClientBuilder implements ApacheHttpClientBuilder { + protected final Logger log = LoggerFactory.getLogger(DefaultApacheHttpClientBuilder.class); + private final AtomicBoolean prepared = new AtomicBoolean(false); + private int connectionRequestTimeout = 3000; + private int connectionTimeout = 5000; + private int soTimeout = 5000; + private int idleConnTimeout = 60000; + private int checkWaitTime = 60000; + private int maxConnPerHost = 10; + private int maxTotalConn = 50; + private String userAgent; + private HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() { + @Override + public boolean retryRequest(IOException exception, int executionCount, HttpContext context) { + return false; + } + }; + private SSLConnectionSocketFactory sslConnectionSocketFactory = SSLConnectionSocketFactory.getSocketFactory(); + private PlainConnectionSocketFactory plainConnectionSocketFactory = PlainConnectionSocketFactory.getSocketFactory(); + private String httpProxyHost; + private int httpProxyPort; + private String httpProxyUsername; + private String httpProxyPassword; + /** + * 闲置连接监控线程 + */ + private IdleConnectionMonitorThread idleConnectionMonitorThread; + private HttpClientBuilder httpClientBuilder; + + private DefaultApacheHttpClientBuilder() { + } + + public static DefaultApacheHttpClientBuilder get() { + return new DefaultApacheHttpClientBuilder(); + } + + @Override + public ApacheHttpClientBuilder httpProxyHost(String httpProxyHost) { + this.httpProxyHost = httpProxyHost; + return this; + } + + @Override + public ApacheHttpClientBuilder httpProxyPort(int httpProxyPort) { + this.httpProxyPort = httpProxyPort; + return this; + } + + @Override + public ApacheHttpClientBuilder httpProxyUsername(String httpProxyUsername) { + this.httpProxyUsername = httpProxyUsername; + return this; + } + + @Override + public ApacheHttpClientBuilder httpProxyPassword(String httpProxyPassword) { + this.httpProxyPassword = httpProxyPassword; + return this; + } + + @Override + public ApacheHttpClientBuilder sslConnectionSocketFactory(SSLConnectionSocketFactory sslConnectionSocketFactory) { + this.sslConnectionSocketFactory = sslConnectionSocketFactory; + return this; + } + + /** + * 获取链接的超时时间设置,默认3000ms + *

+ * 设置为零时不超时,一直等待. + * 设置为负数是使用系统默认设置(非上述的3000ms的默认值,而是httpclient的默认设置). + *

+ * + * @param connectionRequestTimeout 获取链接的超时时间设置(单位毫秒),默认3000ms + */ + public void setConnectionRequestTimeout(int connectionRequestTimeout) { + this.connectionRequestTimeout = connectionRequestTimeout; + } + + /** + * 建立链接的超时时间,默认为5000ms.由于是在链接池获取链接,此设置应该并不起什么作用 + *

+ * 设置为零时不超时,一直等待. + * 设置为负数是使用系统默认设置(非上述的5000ms的默认值,而是httpclient的默认设置). + *

+ * + * @param connectionTimeout 建立链接的超时时间设置(单位毫秒),默认5000ms + */ + public void setConnectionTimeout(int connectionTimeout) { + this.connectionTimeout = connectionTimeout; + } + + /** + * 默认NIO的socket超时设置,默认5000ms. + * + * @param soTimeout 默认NIO的socket超时设置,默认5000ms. + * @see java.net.SocketOptions#SO_TIMEOUT + */ + public void setSoTimeout(int soTimeout) { + this.soTimeout = soTimeout; + } + + /** + * 空闲链接的超时时间,默认60000ms. + *

+ * 超时的链接将在下一次空闲链接检查是被销毁 + *

+ * + * @param idleConnTimeout 空闲链接的超时时间,默认60000ms. + */ + public void setIdleConnTimeout(int idleConnTimeout) { + this.idleConnTimeout = idleConnTimeout; + } + + /** + * 检查空间链接的间隔周期,默认60000ms. + * + * @param checkWaitTime 检查空间链接的间隔周期,默认60000ms. + */ + public void setCheckWaitTime(int checkWaitTime) { + this.checkWaitTime = checkWaitTime; + } + + /** + * 每路的最大链接数,默认10 + * + * @param maxConnPerHost 每路的最大链接数,默认10 + */ + public void setMaxConnPerHost(int maxConnPerHost) { + this.maxConnPerHost = maxConnPerHost; + } + + /** + * 最大总连接数,默认50 + * + * @param maxTotalConn 最大总连接数,默认50 + */ + public void setMaxTotalConn(int maxTotalConn) { + this.maxTotalConn = maxTotalConn; + } + + /** + * 自定义httpclient的User Agent + * + * @param userAgent User Agent + */ + public void setUserAgent(String userAgent) { + this.userAgent = userAgent; + } + + public IdleConnectionMonitorThread getIdleConnectionMonitorThread() { + return this.idleConnectionMonitorThread; + } + + private synchronized void prepare() { + if(prepared.get()){ + return; + } + Registry registry = RegistryBuilder.create() + .register("http", this.plainConnectionSocketFactory) + .register("https", this.sslConnectionSocketFactory) + .build(); + + @SuppressWarnings("resource") + PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry); + connectionManager.setMaxTotal(this.maxTotalConn); + connectionManager.setDefaultMaxPerRoute(this.maxConnPerHost); + connectionManager.setDefaultSocketConfig( + SocketConfig.copy(SocketConfig.DEFAULT) + .setSoTimeout(this.soTimeout) + .build() + ); + + this.idleConnectionMonitorThread = new IdleConnectionMonitorThread( + connectionManager, this.idleConnTimeout, this.checkWaitTime); + this.idleConnectionMonitorThread.setDaemon(true); + this.idleConnectionMonitorThread.start(); + + this.httpClientBuilder = HttpClients.custom() + .setConnectionManager(connectionManager) + .setConnectionManagerShared(true) + .setDefaultRequestConfig( + RequestConfig.custom() + .setSocketTimeout(this.soTimeout) + .setConnectTimeout(this.connectionTimeout) + .setConnectionRequestTimeout(this.connectionRequestTimeout) + .build() + ) + .setRetryHandler(this.httpRequestRetryHandler); + + if (StringUtils.isNotBlank(this.httpProxyHost) + && StringUtils.isNotBlank(this.httpProxyUsername)) { + // 使用代理服务器 需要用户认证的代理服务器 + CredentialsProvider provider = new BasicCredentialsProvider(); + provider.setCredentials( + new AuthScope(this.httpProxyHost, this.httpProxyPort), + new UsernamePasswordCredentials(this.httpProxyUsername, + this.httpProxyPassword)); + this.httpClientBuilder.setDefaultCredentialsProvider(provider); + } + + if (StringUtils.isNotBlank(this.userAgent)) { + this.httpClientBuilder.setUserAgent(this.userAgent); + } + prepared.set(true); + } + + @Override + public CloseableHttpClient build() { + if(!prepared.get()){ + prepare(); + } + return this.httpClientBuilder.build(); + } + + public static class IdleConnectionMonitorThread extends Thread { + private final HttpClientConnectionManager connMgr; + private final int idleConnTimeout; + private final int checkWaitTime; + private volatile boolean shutdown; + + public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr, int idleConnTimeout, int checkWaitTime) { + super("IdleConnectionMonitorThread"); + this.connMgr = connMgr; + this.idleConnTimeout = idleConnTimeout; + this.checkWaitTime = checkWaitTime; + } + + @Override + public void run() { + try { + while (!this.shutdown) { + synchronized (this) { + wait(this.checkWaitTime); + this.connMgr.closeExpiredConnections(); + this.connMgr.closeIdleConnections(this.idleConnTimeout, + TimeUnit.MILLISECONDS); + } + } + } catch (InterruptedException ignore) { + } + } + + public void trigger() { + synchronized (this) { + notifyAll(); + } + } + + public void shutdown() { + this.shutdown = true; + synchronized (this) { + notifyAll(); + } + } + } +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/InputStreamResponseHandler.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/InputStreamResponseHandler.java new file mode 100644 index 00000000..a766d4c2 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/InputStreamResponseHandler.java @@ -0,0 +1,28 @@ +package me.chanjar.weixin.common.util.http.jodd; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.StatusLine; +import org.apache.http.client.HttpResponseException; +import org.apache.http.client.ResponseHandler; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; +import java.io.InputStream; + +public class InputStreamResponseHandler implements ResponseHandler { + + public static final ResponseHandler INSTANCE = new InputStreamResponseHandler(); + + @Override + public InputStream handleResponse(final HttpResponse response) throws IOException { + final StatusLine statusLine = response.getStatusLine(); + final HttpEntity entity = response.getEntity(); + if (statusLine.getStatusCode() >= 300) { + EntityUtils.consume(entity); + throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase()); + } + return entity == null ? null : entity.getContent(); + } + +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/MediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/MediaDownloadRequestExecutor.java new file mode 100644 index 00000000..ff617e8e --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/MediaDownloadRequestExecutor.java @@ -0,0 +1,76 @@ +package me.chanjar.weixin.common.util.http.jodd; + +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.fs.FileUtils; +import org.apache.commons.lang3.StringUtils; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 下载媒体文件请求执行器,请求的参数是String, 返回的结果是File + * 视频文件不支持下载 + * + * @author Daniel Qian + */ +public class MediaDownloadRequestExecutor implements RequestExecutor { + + private File tmpDirFile; + + public MediaDownloadRequestExecutor() { + } + + public MediaDownloadRequestExecutor(File tmpDirFile) { + this.tmpDirFile = tmpDirFile; + } + + @Override + public File execute(ProxyInfo httpProxy, String uri, String queryParam) throws WxErrorException, IOException { + if (queryParam != null) { + if (uri.indexOf('?') == -1) { + uri += '?'; + } + uri += uri.endsWith("?") ? queryParam : '&' + queryParam; + } + + HttpRequest httpRequest = HttpRequest.post(uri); + HttpResponse response = httpRequest.send(); + String contentType = response.header("Content-Type"); + if (contentType != null && contentType.startsWith("application/json")) { + // application/json; encoding=utf-8 下载媒体文件出错 + throw new WxErrorException(WxError.fromJson(response.bodyText())); + } + + String fileName = getFileName(response); + if (StringUtils.isBlank(fileName)) { + return null; + } + + InputStream inputStream = new ByteArrayInputStream(response.bodyBytes()); + String[] nameAndExt = fileName.split("\\."); + return FileUtils.createTmpFile(inputStream, nameAndExt[0], nameAndExt[1], this.tmpDirFile); + } + + private String getFileName(HttpResponse response) throws WxErrorException { + String content = response.header("Content-disposition"); + if (content == null || content.length() == 0) { + throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); + } + + Pattern p = Pattern.compile(".*filename=\"(.*)\""); + Matcher m = p.matcher(content); + if (m.matches()) { + return m.group(1); + } + throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); + } + +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/MediaUploadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/MediaUploadRequestExecutor.java new file mode 100644 index 00000000..43d7bbae --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/MediaUploadRequestExecutor.java @@ -0,0 +1,39 @@ +package me.chanjar.weixin.common.util.http.jodd; + +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import jodd.http.net.SocketHttpConnectionProvider; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; +import me.chanjar.weixin.common.exception.WxErrorException; + +import java.io.File; +import java.io.IOException; + +/** + * 上传媒体文件请求执行器,请求的参数是File, 返回的结果是String + * + * @author Daniel Qian + */ +public class MediaUploadRequestExecutor implements RequestExecutor { + + @Override + public WxMediaUploadResult execute(ProxyInfo httpProxy, String uri, File file) throws WxErrorException, IOException { + HttpRequest request = HttpRequest.post(uri); + if (httpProxy != null) { + SocketHttpConnectionProvider provider = new SocketHttpConnectionProvider(); + provider.useProxy(httpProxy); + request.withConnectionProvider(provider); + } + request.form("media", file); + HttpResponse response = request.send(); + String responseContent =response.bodyText(); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return WxMediaUploadResult.fromJson(responseContent); + } + +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/RequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/RequestExecutor.java new file mode 100644 index 00000000..ccc82702 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/RequestExecutor.java @@ -0,0 +1,25 @@ +package me.chanjar.weixin.common.util.http.jodd; + +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.exception.WxErrorException; + +import java.io.IOException; + +/** + * http请求执行器 + * + * @param 返回值类型 + * @param 请求参数类型 + */ +public interface RequestExecutor { + + /** + * @param httpProxy http代理对象,如果没有配置代理则为空 + * @param uri uri + * @param data 数据 + * @throws WxErrorException + * @throws IOException + */ + T execute(ProxyInfo httpProxy, String uri, E data) throws WxErrorException, IOException; + +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimpleGetRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimpleGetRequestExecutor.java new file mode 100644 index 00000000..de84ad7b --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimpleGetRequestExecutor.java @@ -0,0 +1,43 @@ +package me.chanjar.weixin.common.util.http.jodd; + +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import jodd.http.net.SocketHttpConnectionProvider; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; + +import java.io.IOException; + +/** + * 简单的GET请求执行器,请求的参数是String, 返回的结果也是String + * + * @author Daniel Qian + */ +public class SimpleGetRequestExecutor implements RequestExecutor { + + @Override + public String execute(ProxyInfo httpProxy, String uri, String queryParam) throws WxErrorException, IOException { + if (queryParam != null) { + if (uri.indexOf('?') == -1) { + uri += '?'; + } + uri += uri.endsWith("?") ? queryParam : '&' + queryParam; + } + + HttpRequest request = HttpRequest.get(uri); + if (httpProxy != null) { + SocketHttpConnectionProvider provider = new SocketHttpConnectionProvider(); + provider.useProxy(httpProxy); + request.withConnectionProvider(provider); + } + HttpResponse response = request.send(); + String responseContent = response.bodyText(); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return responseContent; + } + +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimplePostRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimplePostRequestExecutor.java new file mode 100644 index 00000000..276b1310 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimplePostRequestExecutor.java @@ -0,0 +1,51 @@ +package me.chanjar.weixin.common.util.http.jodd; + +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import jodd.http.net.SocketHttpConnectionProvider; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; + +import java.io.IOException; + +/** + * 简单的POST请求执行器,请求的参数是String, 返回的结果也是String + * + * @author Daniel Qian + */ +public class SimplePostRequestExecutor implements RequestExecutor { + + @Override + public String execute(ProxyInfo httpProxy, String uri, String postEntity) throws WxErrorException, IOException { + HttpRequest request = HttpRequest.post(uri); + if (httpProxy != null) { + SocketHttpConnectionProvider provider = new SocketHttpConnectionProvider(); + provider.useProxy(httpProxy); + request.withConnectionProvider(provider); + } + if (postEntity != null) { + request.bodyText(postEntity); + } + HttpResponse response = request.send(); + + String responseContent = response.bodyText(); + if (responseContent.isEmpty()) { + throw new WxErrorException( + WxError.newBuilder().setErrorCode(9999).setErrorMsg("无响应内容") + .build()); + } + + if (responseContent.startsWith("")) { + //xml格式输出直接返回 + return responseContent; + } + + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return responseContent; + } + +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/URIUtil.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/URIUtil.java new file mode 100644 index 00000000..ac293d79 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/URIUtil.java @@ -0,0 +1,48 @@ +package me.chanjar.weixin.common.util.http.jodd; + + +import org.apache.commons.lang3.StringUtils; + +import java.io.UnsupportedEncodingException; + +public class URIUtil { + + private static final String ALLOWED_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'()"; + + public static String encodeURIComponent(String input) { + if (StringUtils.isEmpty(input)) { + return input; + } + + int l = input.length(); + StringBuilder o = new StringBuilder(l * 3); + try { + for (int i = 0; i < l; i++) { + String e = input.substring(i, i + 1); + if (ALLOWED_CHARS.indexOf(e) == -1) { + byte[] b = e.getBytes("utf-8"); + o.append(getHex(b)); + continue; + } + o.append(e); + } + return o.toString(); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return input; + } + + private static String getHex(byte buf[]) { + StringBuilder o = new StringBuilder(buf.length * 3); + for (int i = 0; i < buf.length; i++) { + int n = buf[i] & 0xff; + o.append("%"); + if (n < 0x10) { + o.append("0"); + } + o.append(Long.toString(n, 16).toUpperCase()); + } + return o.toString(); + } +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/Utf8ResponseHandler.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/Utf8ResponseHandler.java new file mode 100644 index 00000000..e26d3e33 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/Utf8ResponseHandler.java @@ -0,0 +1,33 @@ +package me.chanjar.weixin.common.util.http.jodd; + +import org.apache.http.Consts; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.StatusLine; +import org.apache.http.client.HttpResponseException; +import org.apache.http.client.ResponseHandler; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; + +/** + * copy from {@link org.apache.http.impl.client.BasicResponseHandler} + * + * @author Daniel Qian + */ +public class Utf8ResponseHandler implements ResponseHandler { + + public static final ResponseHandler INSTANCE = new Utf8ResponseHandler(); + + @Override + public String handleResponse(final HttpResponse response) throws IOException { + final StatusLine statusLine = response.getStatusLine(); + final HttpEntity entity = response.getEntity(); + if (statusLine.getStatusCode() >= 300) { + EntityUtils.consume(entity); + throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase()); + } + return entity == null ? null : EntityUtils.toString(entity, Consts.UTF_8); + } + +} From d476047c4cf2c1382965c1fe885dc36d4e779905 Mon Sep 17 00:00:00 2001 From: ecoolper Date: Fri, 21 Apr 2017 21:55:02 +0800 Subject: [PATCH 05/27] mp usage jodd-http --- .../weixin/mp/api/WxMpCardService.java | 10 +- .../weixin/mp/api/WxMpConfigStorage.java | 2 +- .../mp/api/WxMpInMemoryConfigStorage.java | 2 +- .../me/chanjar/weixin/mp/api/WxMpService.java | 32 +- .../weixin/mp/api/WxMpStoreService.java | 2 +- .../mp/api/impl/WxMpDeviceServiceImpl.java | 2 +- .../mp/api/impl/WxMpUserTagServiceImpl.java | 8 +- .../api/impl/apache/WxMpCardServiceImpl.java | 251 +++++++++ .../{ => apache}/WxMpKefuServiceImpl.java | 29 +- .../{ => apache}/WxMpMaterialServiceImpl.java | 12 +- .../impl/apache/WxMpQrcodeServiceImpl.java | 120 +++++ .../impl/{ => apache}/WxMpServiceImpl.java | 26 +- .../apache/WxMpUserBlacklistServiceImpl.java | 52 ++ .../impl/{ => jodd}/WxMpCardServiceImpl.java | 43 +- .../mp/api/impl/jodd/WxMpKefuServiceImpl.java | 183 +++++++ .../impl/jodd/WxMpMaterialServiceImpl.java | 165 ++++++ .../{ => jodd}/WxMpQrcodeServiceImpl.java | 8 +- .../mp/api/impl/jodd/WxMpServiceImpl.java | 510 ++++++++++++++++++ .../WxMpUserBlacklistServiceImpl.java | 8 +- .../MaterialDeleteRequestExecutor.java | 6 +- .../MaterialNewsInfoRequestExecutor.java | 6 +- .../MaterialUploadRequestExecutor.java | 10 +- .../MaterialVideoInfoRequestExecutor.java | 6 +- ...lVoiceAndImageDownloadRequestExecutor.java | 27 +- .../MediaImgUploadRequestExecutor.java | 6 +- .../{ => apache}/QrCodeRequestExecutor.java | 16 +- .../jodd/MaterialDeleteRequestExecutor.java | 39 ++ .../jodd/MaterialNewsInfoRequestExecutor.java | 41 ++ .../jodd/MaterialUploadRequestExecutor.java | 53 ++ .../MaterialVideoInfoRequestExecutor.java | 39 ++ ...lVoiceAndImageDownloadRequestExecutor.java | 57 ++ .../jodd/MediaImgUploadRequestExecutor.java | 42 ++ .../util/http/jodd/QrCodeRequestExecutor.java | 60 +++ .../weixin/mp/api/WxMpBusyRetryTest.java | 11 +- .../mp/api/impl/WxMpStoreServiceImplTest.java | 2 +- .../weixin/mp/api/test/ApiTestModule.java | 2 +- .../weixin/mp/demo/WxMpDemoServer.java | 2 +- 37 files changed, 1772 insertions(+), 118 deletions(-) create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpCardServiceImpl.java rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/{ => apache}/WxMpKefuServiceImpl.java (92%) rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/{ => apache}/WxMpMaterialServiceImpl.java (94%) create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpQrcodeServiceImpl.java rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/{ => apache}/WxMpServiceImpl.java (93%) create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpUserBlacklistServiceImpl.java rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/{ => jodd}/WxMpCardServiceImpl.java (89%) create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpKefuServiceImpl.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpMaterialServiceImpl.java rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/{ => jodd}/WxMpQrcodeServiceImpl.java (94%) create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpServiceImpl.java rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/{ => jodd}/WxMpUserBlacklistServiceImpl.java (87%) rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/{ => apache}/MaterialDeleteRequestExecutor.java (90%) rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/{ => apache}/MaterialNewsInfoRequestExecutor.java (91%) rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/{ => apache}/MaterialUploadRequestExecutor.java (89%) rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/{ => apache}/MaterialVideoInfoRequestExecutor.java (90%) rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/{ => apache}/MaterialVoiceAndImageDownloadRequestExecutor.java (92%) rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/{ => apache}/MediaImgUploadRequestExecutor.java (91%) rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/{ => apache}/QrCodeRequestExecutor.java (87%) create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialDeleteRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialNewsInfoRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialUploadRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialVideoInfoRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialVoiceAndImageDownloadRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MediaImgUploadRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/QrCodeRequestExecutor.java diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpCardService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpCardService.java index d4a36c65..362da84e 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpCardService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpCardService.java @@ -6,9 +6,15 @@ import me.chanjar.weixin.mp.bean.result.WxMpCardResult; /** * 卡券相关接口 - * @author YuJian(mgcnrx11@hotmail.com) on 01/11/2016 + * @author YuJian(mgcnrx11@hotmail.com) on 01/11/2016 */ -public interface WxMpCardService { +public interface WxMpCardService { + + /** + * 得到WxMpService + * @return + */ + WxMpService getWxMpService(); /** * 获得卡券api_ticket,不强制刷新卡券api_ticket diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java index f4053899..dbff2a7a 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java @@ -1,7 +1,7 @@ package me.chanjar.weixin.mp.api; import me.chanjar.weixin.common.bean.WxAccessToken; -import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; import java.io.File; import java.util.concurrent.locks.Lock; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java index 4bd1daec..9181a401 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java @@ -2,7 +2,7 @@ package me.chanjar.weixin.mp.api; import me.chanjar.weixin.common.bean.WxAccessToken; import me.chanjar.weixin.common.util.ToStringUtils; -import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; import java.io.File; import java.util.concurrent.locks.Lock; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java index cf1401a5..edaa72c1 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java @@ -3,14 +3,14 @@ package me.chanjar.weixin.mp.api; import me.chanjar.weixin.common.bean.WxJsapiSignature; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.apache.MediaUploadRequestExecutor; import me.chanjar.weixin.mp.bean.*; import me.chanjar.weixin.mp.bean.result.*; -import org.apache.http.HttpHost; /** * 微信API的Service */ -public interface WxMpService { +public interface WxMpService { /** *
@@ -224,15 +224,18 @@ public interface WxMpService {
    * 
    * Service没有实现某个API的时候,可以用这个,
    * 比{@link #get}和{@link #post}方法更灵活,可以自己构造RequestExecutor用来处理不同的参数和不同的返回类型。
-   * 可以参考,{@link me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor}的实现方法
+   * 可以参考,{@link MediaUploadRequestExecutor}的实现方法
    * 
*/ - T execute(RequestExecutor executor, String uri, E data) throws WxErrorException; + T execute(RequestExecutor executor, String uri, E data) throws WxErrorException; - /** - * 获取代理对象 - */ - HttpHost getHttpProxy(); + T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException; + + + /** + * 获取代理对象 + */ + //HttpHost getHttpProxy(); /** * 注入 {@link WxMpConfigStorage} 的实现 @@ -345,4 +348,17 @@ public interface WxMpService { * @return WxMpDeviceService */ WxMpDeviceService getDeviceService(); + + /** + * + * @return + */ + H getHttpclient(); + + /** + * + * @return + */ + P getHttpProxy(); + } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpStoreService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpStoreService.java index c214c46d..38dde803 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpStoreService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpStoreService.java @@ -12,7 +12,7 @@ import java.util.List; * @author binarywang(Binary Wang) * Created by Binary Wang on 2016-09-23. */ -public interface WxMpStoreService { +public interface WxMpStoreService { /** *
    * 创建门店
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpDeviceServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpDeviceServiceImpl.java
index 5c942365..3f7378e3 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpDeviceServiceImpl.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpDeviceServiceImpl.java
@@ -16,7 +16,7 @@ public class WxMpDeviceServiceImpl implements WxMpDeviceService {
 
   private WxMpService wxMpService;
 
-  WxMpDeviceServiceImpl(WxMpService wxMpService) {
+  public WxMpDeviceServiceImpl(WxMpService wxMpService) {
     this.wxMpService = wxMpService;
   }
 
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpUserTagServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpUserTagServiceImpl.java
index d1bdae1e..a1fee937 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpUserTagServiceImpl.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpUserTagServiceImpl.java
@@ -1,14 +1,9 @@
 package me.chanjar.weixin.mp.api.impl;
 
-import java.util.List;
-
-import org.apache.commons.lang3.StringUtils;
-
 import com.google.gson.JsonArray;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
 import com.google.gson.reflect.TypeToken;
-
 import me.chanjar.weixin.common.bean.result.WxError;
 import me.chanjar.weixin.common.exception.WxErrorException;
 import me.chanjar.weixin.mp.api.WxMpService;
@@ -16,6 +11,9 @@ import me.chanjar.weixin.mp.api.WxMpUserTagService;
 import me.chanjar.weixin.mp.bean.tag.WxTagListUser;
 import me.chanjar.weixin.mp.bean.tag.WxUserTag;
 import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.List;
 
 /**
  *
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpCardServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpCardServiceImpl.java
new file mode 100644
index 00000000..e9d9c789
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpCardServiceImpl.java
@@ -0,0 +1,251 @@
+package me.chanjar.weixin.mp.api.impl.apache;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.reflect.TypeToken;
+import me.chanjar.weixin.common.bean.WxCardApiSignature;
+import me.chanjar.weixin.common.bean.result.WxError;
+import me.chanjar.weixin.common.exception.WxErrorException;
+import me.chanjar.weixin.common.util.RandomUtils;
+import me.chanjar.weixin.common.util.crypto.SHA1;
+import me.chanjar.weixin.common.util.http.apache.SimpleGetRequestExecutor;
+import me.chanjar.weixin.mp.api.WxMpCardService;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.result.WxMpCardResult;
+import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
+import org.apache.http.HttpHost;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Arrays;
+import java.util.concurrent.locks.Lock;
+
+/**
+ * Created by Binary Wang on 2016/7/27.
+ */
+public class WxMpCardServiceImpl implements WxMpCardService {
+
+  private final Logger log = LoggerFactory.getLogger(WxMpCardServiceImpl.class);
+
+  private WxMpService wxMpService;
+
+  public WxMpCardServiceImpl(WxMpService wxMpService) {
+    this.wxMpService = wxMpService;
+  }
+
+  /**
+   * 得到WxMpService
+   * @return
+   */
+  @Override
+  public WxMpService getWxMpService(){
+      return this.wxMpService;
+  }
+
+  /**
+   * 获得卡券api_ticket,不强制刷新卡券api_ticket
+   *
+   * @return 卡券api_ticket
+   * @see #getCardApiTicket(boolean)
+   */
+  @Override
+  public String getCardApiTicket() throws WxErrorException {
+    return getCardApiTicket(false);
+  }
+
+  /**
+   * 
+   * 获得卡券api_ticket
+   * 获得时会检查卡券apiToken是否过期,如果过期了,那么就刷新一下,否则就什么都不干
+   *
+   * 详情请见:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD
+   * .954-.E5.8D.A1.E5.88.B8.E6.89.A9.E5.B1.95.E5.AD.97.E6.AE.B5.E5.8F.8A.E7.AD.BE.E5.90.8D.E7.94
+   * .9F.E6.88.90.E7.AE.97.E6.B3.95
+   * 
+ * + * @param forceRefresh 强制刷新 + * @return 卡券api_ticket + */ + @Override + public String getCardApiTicket(boolean forceRefresh) throws WxErrorException { + Lock lock = getWxMpService().getWxMpConfigStorage().getCardApiTicketLock(); + try { + lock.lock(); + + if (forceRefresh) { + this.getWxMpService().getWxMpConfigStorage().expireCardApiTicket(); + } + + if (this.getWxMpService().getWxMpConfigStorage().isCardApiTicketExpired()) { + String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=wx_card"; + String responseContent = this.wxMpService.execute(new SimpleGetRequestExecutor(), url, null); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); + String cardApiTicket = tmpJsonObject.get("ticket").getAsString(); + int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); + this.getWxMpService().getWxMpConfigStorage().updateCardApiTicket(cardApiTicket, expiresInSeconds); + } + } finally { + lock.unlock(); + } + return this.getWxMpService().getWxMpConfigStorage().getCardApiTicket(); + } + + /** + *
+   * 创建调用卡券api时所需要的签名
+   *
+   * 详情请见:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD
+   * .954-.E5.8D.A1.E5.88.B8.E6.89.A9.E5.B1.95.E5.AD.97.E6.AE.B5.E5.8F.8A.E7.AD.BE.E5.90.8D.E7.94
+   * .9F.E6.88.90.E7.AE.97.E6.B3.95
+   * 
+ * + * @param optionalSignParam 参与签名的参数数组。 + * 可以为下列字段:app_id, card_id, card_type, code, openid, location_id + *
注意:当做wx.chooseCard调用时,必须传入app_id参与签名,否则会造成签名失败导致拉取卡券列表为空 + * @return 卡券Api签名对象 + */ + @Override + public WxCardApiSignature createCardApiSignature(String... optionalSignParam) throws + WxErrorException { + long timestamp = System.currentTimeMillis() / 1000; + String nonceStr = RandomUtils.getRandomStr(); + String cardApiTicket = getCardApiTicket(false); + + String[] signParam = Arrays.copyOf(optionalSignParam, optionalSignParam.length + 3); + signParam[optionalSignParam.length] = String.valueOf(timestamp); + signParam[optionalSignParam.length + 1] = nonceStr; + signParam[optionalSignParam.length + 2] = cardApiTicket; + String signature = SHA1.gen(signParam); + WxCardApiSignature cardApiSignature = new WxCardApiSignature(); + cardApiSignature.setTimestamp(timestamp); + cardApiSignature.setNonceStr(nonceStr); + cardApiSignature.setSignature(signature); + return cardApiSignature; + } + + /** + * 卡券Code解码 + * + * @param encryptCode 加密Code,通过JSSDK的chooseCard接口获得 + * @return 解密后的Code + */ + @Override + public String decryptCardCode(String encryptCode) throws WxErrorException { + String url = "https://api.weixin.qq.com/card/code/decrypt"; + JsonObject param = new JsonObject(); + param.addProperty("encrypt_code", encryptCode); + String responseContent = this.wxMpService.post(url, param.toString()); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); + JsonPrimitive jsonPrimitive = tmpJsonObject.getAsJsonPrimitive("code"); + return jsonPrimitive.getAsString(); + } + + /** + * 卡券Code查询 + * + * @param cardId 卡券ID代表一类卡券 + * @param code 单张卡券的唯一标准 + * @param checkConsume 是否校验code核销状态,填入true和false时的code异常状态返回数据不同 + * @return WxMpCardResult对象 + */ + @Override + public WxMpCardResult queryCardCode(String cardId, String code, boolean checkConsume) throws WxErrorException { + String url = "https://api.weixin.qq.com/card/code/get"; + JsonObject param = new JsonObject(); + param.addProperty("card_id", cardId); + param.addProperty("code", code); + param.addProperty("check_consume", checkConsume); + String responseContent = this.wxMpService.post(url, param.toString()); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + return WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement, + new TypeToken() { + }.getType()); + } + + /** + * 卡券Code核销。核销失败会抛出异常 + * + * @param code 单张卡券的唯一标准 + * @return 调用返回的JSON字符串。 + *
可用 com.google.gson.JsonParser#parse 等方法直接取JSON串中的errcode等信息。 + */ + @Override + public String consumeCardCode(String code) throws WxErrorException { + return consumeCardCode(code, null); + } + + /** + * 卡券Code核销。核销失败会抛出异常 + * + * @param code 单张卡券的唯一标准 + * @param cardId 当自定义Code卡券时需要传入card_id + * @return 调用返回的JSON字符串。 + *
可用 com.google.gson.JsonParser#parse 等方法直接取JSON串中的errcode等信息。 + */ + @Override + public String consumeCardCode(String code, String cardId) throws WxErrorException { + String url = "https://api.weixin.qq.com/card/code/consume"; + JsonObject param = new JsonObject(); + param.addProperty("code", code); + + if (cardId != null && !"".equals(cardId)) { + param.addProperty("card_id", cardId); + } + + return this.wxMpService.post(url, param.toString()); + } + + /** + * 卡券Mark接口。 + * 开发者在帮助消费者核销卡券之前,必须帮助先将此code(卡券串码)与一个openid绑定(即mark住), + * 才能进一步调用核销接口,否则报错。 + * + * @param code 卡券的code码 + * @param cardId 卡券的ID + * @param openId 用券用户的openid + * @param isMark 是否要mark(占用)这个code,填写true或者false,表示占用或解除占用 + */ + @Override + public void markCardCode(String code, String cardId, String openId, boolean isMark) throws + WxErrorException { + String url = "https://api.weixin.qq.com/card/code/mark"; + JsonObject param = new JsonObject(); + param.addProperty("code", code); + param.addProperty("card_id", cardId); + param.addProperty("openid", openId); + param.addProperty("is_mark", isMark); + String responseContent = this.getWxMpService().post(url, param.toString()); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + WxMpCardResult cardResult = WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement, + new TypeToken() { }.getType()); + if (!cardResult.getErrorCode().equals("0")) { + this.log.warn("朋友的券mark失败:{}", cardResult.getErrorMsg()); + } + } + + @Override + public String getCardDetail(String cardId) throws WxErrorException { + String url = "https://api.weixin.qq.com/card/get"; + JsonObject param = new JsonObject(); + param.addProperty("card_id", cardId); + String responseContent = this.wxMpService.post(url, param.toString()); + + // 判断返回值 + JsonObject json = (new JsonParser()).parse(responseContent).getAsJsonObject(); + String errcode = json.get("errcode").getAsString(); + if (!"0".equals(errcode)) { + String errmsg = json.get("errmsg").getAsString(); + WxError error = new WxError(); + error.setErrorCode(Integer.valueOf(errcode)); + error.setErrorMsg(errmsg); + throw new WxErrorException(error); + } + + return responseContent; + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpKefuServiceImpl.java similarity index 92% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpKefuServiceImpl.java index 09a68adf..0dc921f1 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpKefuServiceImpl.java @@ -1,28 +1,23 @@ -package me.chanjar.weixin.mp.api.impl; - -import java.io.File; -import java.util.Date; - -import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +package me.chanjar.weixin.mp.api.impl.apache; import com.google.gson.JsonObject; - import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; +import me.chanjar.weixin.common.util.http.apache.MediaUploadRequestExecutor; import me.chanjar.weixin.mp.api.WxMpKefuService; import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage; import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfSessionRequest; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfList; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfMsgList; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionGetResult; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionList; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionWaitCaseList; +import me.chanjar.weixin.mp.bean.kefu.result.*; +import org.apache.http.HttpHost; +import org.apache.http.impl.client.CloseableHttpClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.Date; /** * @@ -34,7 +29,7 @@ public class WxMpKefuServiceImpl implements WxMpKefuService { .getLogger(WxMpKefuServiceImpl.class); private static final String API_URL_PREFIX = "https://api.weixin.qq.com/customservice"; private static final String API_URL_PREFIX_WITH_CGI_BIN = "https://api.weixin.qq.com/cgi-bin/customservice"; - private WxMpService wxMpService; + private WxMpService wxMpService; public WxMpKefuServiceImpl(WxMpService wxMpService) { this.wxMpService = wxMpService; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpMaterialServiceImpl.java similarity index 94% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpMaterialServiceImpl.java index af9fa54c..13d5a754 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpMaterialServiceImpl.java @@ -1,12 +1,12 @@ -package me.chanjar.weixin.mp.api.impl; +package me.chanjar.weixin.mp.api.impl.apache; import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.fs.FileUtils; -import me.chanjar.weixin.common.util.http.MediaDownloadRequestExecutor; -import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; +import me.chanjar.weixin.common.util.http.apache.MediaDownloadRequestExecutor; +import me.chanjar.weixin.common.util.http.apache.MediaUploadRequestExecutor; import me.chanjar.weixin.common.util.json.WxGsonBuilder; import me.chanjar.weixin.mp.api.WxMpMaterialService; import me.chanjar.weixin.mp.api.WxMpService; @@ -14,8 +14,10 @@ import me.chanjar.weixin.mp.bean.material.WxMpMaterial; import me.chanjar.weixin.mp.bean.material.WxMpMaterialArticleUpdate; import me.chanjar.weixin.mp.bean.material.WxMpMaterialNews; import me.chanjar.weixin.mp.bean.material.*; -import me.chanjar.weixin.mp.util.http.*; +import me.chanjar.weixin.mp.util.http.apache.*; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; +import org.apache.http.HttpHost; +import org.apache.http.impl.client.CloseableHttpClient; import java.io.File; import java.io.IOException; @@ -30,7 +32,7 @@ import java.util.UUID; public class WxMpMaterialServiceImpl implements WxMpMaterialService { private static final String MEDIA_API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/media"; private static final String MATERIAL_API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/material"; - private WxMpService wxMpService; + private WxMpService wxMpService; public WxMpMaterialServiceImpl(WxMpService wxMpService) { this.wxMpService = wxMpService; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpQrcodeServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpQrcodeServiceImpl.java new file mode 100644 index 00000000..5db81fe1 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpQrcodeServiceImpl.java @@ -0,0 +1,120 @@ +package me.chanjar.weixin.mp.api.impl.apache; + +import com.google.gson.JsonObject; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpQrcodeService; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; +import me.chanjar.weixin.mp.util.http.apache.QrCodeRequestExecutor; +import org.apache.http.HttpHost; +import org.apache.http.impl.client.CloseableHttpClient; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +/** + * Created by Binary Wang on 2016/7/21. + */ +public class WxMpQrcodeServiceImpl implements WxMpQrcodeService { + private static final String API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/qrcode"; + private WxMpService wxMpService; + + public WxMpQrcodeServiceImpl(WxMpService wxMpService) { + this.wxMpService = wxMpService; + } + + @Override + public WxMpQrCodeTicket qrCodeCreateTmpTicket(int sceneId, Integer expireSeconds) throws WxErrorException { + if (sceneId == 0) { + throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("临时二维码场景值不能为0!").build()); + } + + //expireSeconds 该二维码有效时间,以秒为单位。 最大不超过2592000(即30天),此字段如果不填,则默认有效期为30秒。 + if (expireSeconds != null && expireSeconds > 2592000) { + throw new WxErrorException(WxError.newBuilder().setErrorCode(-1) + .setErrorMsg("临时二维码有效时间最大不能超过2592000(即30天)!").build()); + } + + if (expireSeconds == null) { + expireSeconds = 30; + } + + String url = API_URL_PREFIX + "/create"; + JsonObject json = new JsonObject(); + json.addProperty("action_name", "QR_SCENE"); + json.addProperty("expire_seconds", expireSeconds); + + JsonObject actionInfo = new JsonObject(); + JsonObject scene = new JsonObject(); + scene.addProperty("scene_id", sceneId); + actionInfo.add("scene", scene); + json.add("action_info", actionInfo); + String responseContent = this.wxMpService.post(url, json.toString()); + return WxMpQrCodeTicket.fromJson(responseContent); + } + + @Override + public WxMpQrCodeTicket qrCodeCreateLastTicket(int sceneId) throws WxErrorException { + if (sceneId < 1 || sceneId > 100000) { + throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("永久二维码的场景值目前只支持1--100000!").build()); + } + + String url = API_URL_PREFIX + "/create"; + JsonObject json = new JsonObject(); + json.addProperty("action_name", "QR_LIMIT_SCENE"); + JsonObject actionInfo = new JsonObject(); + JsonObject scene = new JsonObject(); + scene.addProperty("scene_id", sceneId); + actionInfo.add("scene", scene); + json.add("action_info", actionInfo); + String responseContent = this.wxMpService.post(url, json.toString()); + return WxMpQrCodeTicket.fromJson(responseContent); + } + + @Override + public WxMpQrCodeTicket qrCodeCreateLastTicket(String sceneStr) throws WxErrorException { + String url = API_URL_PREFIX + "/create"; + JsonObject json = new JsonObject(); + json.addProperty("action_name", "QR_LIMIT_STR_SCENE"); + JsonObject actionInfo = new JsonObject(); + JsonObject scene = new JsonObject(); + scene.addProperty("scene_str", sceneStr); + actionInfo.add("scene", scene); + json.add("action_info", actionInfo); + String responseContent = this.wxMpService.post(url, json.toString()); + return WxMpQrCodeTicket.fromJson(responseContent); + } + + @Override + public File qrCodePicture(WxMpQrCodeTicket ticket) throws WxErrorException { + String url = "https://mp.weixin.qq.com/cgi-bin/showqrcode"; + return this.wxMpService.execute(new QrCodeRequestExecutor(), url, ticket); + } + + @Override + public String qrCodePictureUrl(String ticket, boolean needShortUrl) throws WxErrorException { + String url = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=%s"; + try { + String resultUrl = String.format(url, + URLEncoder.encode(ticket, StandardCharsets.UTF_8.name())); + if (needShortUrl) { + return this.wxMpService.shortUrl(resultUrl); + } + + return resultUrl; + } catch (UnsupportedEncodingException e) { + WxError error = WxError.newBuilder().setErrorCode(-1) + .setErrorMsg(e.getMessage()).build(); + throw new WxErrorException(error); + } + } + + @Override + public String qrCodePictureUrl(String ticket) throws WxErrorException { + return qrCodePictureUrl(ticket, false); + } + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpServiceImpl.java similarity index 93% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpServiceImpl.java index 406e8712..75a6bd96 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpServiceImpl.java @@ -1,4 +1,4 @@ -package me.chanjar.weixin.mp.api.impl; +package me.chanjar.weixin.mp.api.impl.apache; import com.google.gson.JsonArray; import com.google.gson.JsonElement; @@ -12,8 +12,14 @@ import me.chanjar.weixin.common.session.StandardSessionManager; import me.chanjar.weixin.common.session.WxSessionManager; import me.chanjar.weixin.common.util.RandomUtils; import me.chanjar.weixin.common.util.crypto.SHA1; -import me.chanjar.weixin.common.util.http.*; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.URIUtil; +import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.apache.SimpleGetRequestExecutor; +import me.chanjar.weixin.common.util.http.apache.SimplePostRequestExecutor; import me.chanjar.weixin.mp.api.*; +import me.chanjar.weixin.mp.api.impl.*; import me.chanjar.weixin.mp.bean.*; import me.chanjar.weixin.mp.bean.result.*; import org.apache.http.HttpHost; @@ -28,7 +34,7 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.concurrent.locks.Lock; -public class WxMpServiceImpl implements WxMpService { +public class WxMpServiceImpl implements WxMpService { private static final JsonParser JSON_PARSER = new JsonParser(); @@ -242,7 +248,7 @@ public class WxMpServiceImpl implements WxMpService { private WxMpOAuth2AccessToken getOAuth2AccessToken(StringBuilder url) throws WxErrorException { try { - RequestExecutor executor = new SimpleGetRequestExecutor(); + RequestExecutor executor = new SimpleGetRequestExecutor(); String responseText = executor.execute(this.getHttpclient(), this.httpProxy, url.toString(), null); return WxMpOAuth2AccessToken.fromJson(responseText); } catch (IOException e) { @@ -286,7 +292,7 @@ public class WxMpServiceImpl implements WxMpService { } try { - RequestExecutor executor = new SimpleGetRequestExecutor(); + RequestExecutor executor = new SimpleGetRequestExecutor(); String responseText = executor.execute(getHttpclient(), this.httpProxy, url.toString(), null); return WxMpUser.fromJson(responseText); } catch (IOException e) { @@ -302,7 +308,7 @@ public class WxMpServiceImpl implements WxMpService { url.append("&openid=").append(oAuth2AccessToken.getOpenId()); try { - RequestExecutor executor = new SimpleGetRequestExecutor(); + RequestExecutor executor = new SimpleGetRequestExecutor(); executor.execute(getHttpclient(), this.httpProxy, url.toString(), null); } catch (IOException e) { throw new RuntimeException(e); @@ -339,7 +345,7 @@ public class WxMpServiceImpl implements WxMpService { * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 */ @Override - public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { + public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { int retryTimes = 0; do { try { @@ -373,7 +379,8 @@ public class WxMpServiceImpl implements WxMpService { throw new RuntimeException("微信服务端异常,超出重试次数"); } - protected synchronized T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { + @Override + public synchronized T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { if (uri.indexOf("access_token=") != -1) { throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); } @@ -383,7 +390,7 @@ public class WxMpServiceImpl implements WxMpService { uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken; try { - return executor.execute(getHttpclient(), this.httpProxy, uriWithAccessToken, data); + return executor.execute(getHttpclient(), getHttpProxy(), uriWithAccessToken, data); } catch (WxErrorException e) { WxError error = e.getError(); /* @@ -415,6 +422,7 @@ public class WxMpServiceImpl implements WxMpService { return this.httpProxy; } + @Override public CloseableHttpClient getHttpclient() { return this.httpClient; } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpUserBlacklistServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpUserBlacklistServiceImpl.java new file mode 100644 index 00000000..bf99b5fb --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpUserBlacklistServiceImpl.java @@ -0,0 +1,52 @@ +package me.chanjar.weixin.mp.api.impl.apache; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.apache.SimplePostRequestExecutor; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.api.WxMpUserBlacklistService; +import me.chanjar.weixin.mp.bean.result.WxMpUserBlacklistGetResult; +import org.apache.http.HttpHost; +import org.apache.http.impl.client.CloseableHttpClient; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author miller + */ +public class WxMpUserBlacklistServiceImpl implements WxMpUserBlacklistService { + private static final String API_BLACKLIST_PREFIX = "https://api.weixin.qq.com/cgi-bin/tags/members"; + private WxMpService wxMpService; + + public WxMpUserBlacklistServiceImpl(WxMpService wxMpService) { + this.wxMpService = wxMpService; + } + + @Override + public WxMpUserBlacklistGetResult getBlacklist(String nextOpenid) throws WxErrorException { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("begin_openid", nextOpenid); + String url = API_BLACKLIST_PREFIX + "/getblacklist"; + String responseContent = this.wxMpService.execute(new SimplePostRequestExecutor(), url, jsonObject.toString()); + return WxMpUserBlacklistGetResult.fromJson(responseContent); + } + + @Override + public void pushToBlacklist(List openidList) throws WxErrorException { + Map map = new HashMap<>(); + map.put("openid_list", openidList); + String url = API_BLACKLIST_PREFIX + "/batchblacklist"; + this.wxMpService.execute(new SimplePostRequestExecutor(), url, new Gson().toJson(map)); + } + + @Override + public void pullFromBlacklist(List openidList) throws WxErrorException { + Map map = new HashMap<>(); + map.put("openid_list", openidList); + String url = API_BLACKLIST_PREFIX + "/batchunblacklist"; + this.wxMpService.execute(new SimplePostRequestExecutor(), url, new Gson().toJson(map)); + } +} 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/jodd/WxMpCardServiceImpl.java similarity index 89% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpCardServiceImpl.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpCardServiceImpl.java index 2e6bf88e..0789b7ea 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/jodd/WxMpCardServiceImpl.java @@ -1,41 +1,50 @@ -package me.chanjar.weixin.mp.api.impl; - -import java.util.Arrays; -import java.util.concurrent.locks.Lock; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +package me.chanjar.weixin.mp.api.impl.jodd; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonPrimitive; import com.google.gson.reflect.TypeToken; - +import jodd.http.HttpConnectionProvider; +import jodd.http.ProxyInfo; import me.chanjar.weixin.common.bean.WxCardApiSignature; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.RandomUtils; import me.chanjar.weixin.common.util.crypto.SHA1; -import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; +import me.chanjar.weixin.common.util.http.jodd.SimpleGetRequestExecutor; import me.chanjar.weixin.mp.api.WxMpCardService; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.bean.result.WxMpCardResult; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.concurrent.locks.Lock; /** * Created by Binary Wang on 2016/7/27. */ -public class WxMpCardServiceImpl implements WxMpCardService { +public class WxMpCardServiceImpl implements WxMpCardService { private final Logger log = LoggerFactory.getLogger(WxMpCardServiceImpl.class); - private WxMpService wxMpService; + private WxMpService wxMpService; public WxMpCardServiceImpl(WxMpService wxMpService) { this.wxMpService = wxMpService; } + /** + * 得到WxMpService + * @return + */ + @Override + public WxMpService getWxMpService(){ + return this.wxMpService; + } + /** * 获得卡券api_ticket,不强制刷新卡券api_ticket * @@ -62,27 +71,27 @@ public class WxMpCardServiceImpl implements WxMpCardService { */ @Override public String getCardApiTicket(boolean forceRefresh) throws WxErrorException { - Lock lock = wxMpService.getWxMpConfigStorage().getCardApiTicketLock(); + Lock lock = getWxMpService().getWxMpConfigStorage().getCardApiTicketLock(); try { lock.lock(); if (forceRefresh) { - this.wxMpService.getWxMpConfigStorage().expireCardApiTicket(); + this.getWxMpService().getWxMpConfigStorage().expireCardApiTicket(); } - if (this.wxMpService.getWxMpConfigStorage().isCardApiTicketExpired()) { + if (this.getWxMpService().getWxMpConfigStorage().isCardApiTicketExpired()) { String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=wx_card"; String responseContent = this.wxMpService.execute(new SimpleGetRequestExecutor(), url, null); JsonElement tmpJsonElement = new JsonParser().parse(responseContent); JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); String cardApiTicket = tmpJsonObject.get("ticket").getAsString(); int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); - this.wxMpService.getWxMpConfigStorage().updateCardApiTicket(cardApiTicket, expiresInSeconds); + this.getWxMpService().getWxMpConfigStorage().updateCardApiTicket(cardApiTicket, expiresInSeconds); } } finally { lock.unlock(); } - return this.wxMpService.getWxMpConfigStorage().getCardApiTicket(); + return this.getWxMpService().getWxMpConfigStorage().getCardApiTicket(); } /** @@ -210,7 +219,7 @@ public class WxMpCardServiceImpl implements WxMpCardService { param.addProperty("card_id", cardId); param.addProperty("openid", openId); param.addProperty("is_mark", isMark); - String responseContent = this.wxMpService.post(url, param.toString()); + String responseContent = this.getWxMpService().post(url, param.toString()); JsonElement tmpJsonElement = new JsonParser().parse(responseContent); WxMpCardResult cardResult = WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement, new TypeToken() { }.getType()); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpKefuServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpKefuServiceImpl.java new file mode 100644 index 00000000..9e7685b5 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpKefuServiceImpl.java @@ -0,0 +1,183 @@ +package me.chanjar.weixin.mp.api.impl.jodd; + +import com.google.gson.JsonObject; +import jodd.http.HttpConnectionProvider; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.jodd.MediaUploadRequestExecutor; +import me.chanjar.weixin.mp.api.WxMpKefuService; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage; +import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; +import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfSessionRequest; +import me.chanjar.weixin.mp.bean.kefu.result.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.Date; + +/** + * + * @author Binary Wang + * + */ +public class WxMpKefuServiceImpl implements WxMpKefuService { + protected final Logger log = LoggerFactory + .getLogger(WxMpKefuServiceImpl.class); + private static final String API_URL_PREFIX = "https://api.weixin.qq.com/customservice"; + private static final String API_URL_PREFIX_WITH_CGI_BIN = "https://api.weixin.qq.com/cgi-bin/customservice"; + private WxMpService wxMpService; + + public WxMpKefuServiceImpl(WxMpService wxMpService) { + this.wxMpService = wxMpService; + } + + @Override + public boolean sendKefuMessage(WxMpKefuMessage message) + throws WxErrorException { + String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send"; + String responseContent = this.wxMpService.post(url, message.toJson()); + return responseContent != null; + } + + @Override + public WxMpKfList kfList() throws WxErrorException { + String url = API_URL_PREFIX_WITH_CGI_BIN + "/getkflist"; + String responseContent = this.wxMpService.get(url, null); + return WxMpKfList.fromJson(responseContent); + } + + @Override + public WxMpKfOnlineList kfOnlineList() throws WxErrorException { + String url = API_URL_PREFIX_WITH_CGI_BIN + "/getonlinekflist"; + String responseContent = this.wxMpService.get(url, null); + return WxMpKfOnlineList.fromJson(responseContent); + } + + @Override + public boolean kfAccountAdd(WxMpKfAccountRequest request) + throws WxErrorException { + String url = API_URL_PREFIX + "/kfaccount/add"; + String responseContent = this.wxMpService.post(url, request.toJson()); + return responseContent != null; + } + + @Override + public boolean kfAccountUpdate(WxMpKfAccountRequest request) + throws WxErrorException { + String url = API_URL_PREFIX + "/kfaccount/update"; + String responseContent = this.wxMpService.post(url, request.toJson()); + return responseContent != null; + } + + @Override + public boolean kfAccountInviteWorker(WxMpKfAccountRequest request) throws WxErrorException { + String url = API_URL_PREFIX + "/kfaccount/inviteworker"; + String responseContent = this.wxMpService.post(url, request.toJson()); + return responseContent != null; + } + + @Override + public boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) + throws WxErrorException { + String url = API_URL_PREFIX + "/kfaccount/uploadheadimg?kf_account=" + kfAccount; + WxMediaUploadResult responseContent = this.wxMpService + .execute(new MediaUploadRequestExecutor(), url, imgFile); + return responseContent != null; + } + + @Override + public boolean kfAccountDel(String kfAccount) throws WxErrorException { + String url = API_URL_PREFIX + "/kfaccount/del?kf_account=" + kfAccount; + String responseContent = this.wxMpService.get(url, null); + return responseContent != null; + } + + @Override + public boolean kfSessionCreate(String openid, String kfAccount) + throws WxErrorException { + WxMpKfSessionRequest request = new WxMpKfSessionRequest(kfAccount, openid); + String url = API_URL_PREFIX + "/kfsession/create"; + String responseContent = this.wxMpService.post(url, request.toJson()); + return responseContent != null; + } + + @Override + public boolean kfSessionClose(String openid, String kfAccount) + throws WxErrorException { + WxMpKfSessionRequest request = new WxMpKfSessionRequest(kfAccount, openid); + String url = API_URL_PREFIX + "/kfsession/close"; + String responseContent = this.wxMpService.post(url, request.toJson()); + return responseContent != null; + } + + @Override + public WxMpKfSessionGetResult kfSessionGet(String openid) + throws WxErrorException { + String url = API_URL_PREFIX + "/kfsession/getsession?openid=" + openid; + String responseContent = this.wxMpService.get(url, null); + return WxMpKfSessionGetResult.fromJson(responseContent); + } + + @Override + public WxMpKfSessionList kfSessionList(String kfAccount) + throws WxErrorException { + String url = API_URL_PREFIX + "/kfsession/getsessionlist?kf_account=" + kfAccount; + String responseContent = this.wxMpService.get(url, null); + return WxMpKfSessionList.fromJson(responseContent); + } + + @Override + public WxMpKfSessionWaitCaseList kfSessionGetWaitCase() + throws WxErrorException { + String url = API_URL_PREFIX + "/kfsession/getwaitcase"; + String responseContent = this.wxMpService.get(url, null); + return WxMpKfSessionWaitCaseList.fromJson(responseContent); + } + + @Override + public WxMpKfMsgList kfMsgList(Date startTime, Date endTime, Long msgId, Integer number) throws WxErrorException { + if(number > 10000){ + throw new WxErrorException(WxError.newBuilder().setErrorMsg("非法参数请求,每次最多查询10000条记录!").build()); + } + + if(startTime.after(endTime)){ + throw new WxErrorException(WxError.newBuilder().setErrorMsg("起始时间不能晚于结束时间!").build()); + } + + String url = API_URL_PREFIX + "/msgrecord/getmsglist"; + + JsonObject param = new JsonObject(); + param.addProperty("starttime", startTime.getTime() / 1000); //starttime 起始时间,unix时间戳 + param.addProperty("endtime", endTime.getTime() / 1000); //endtime 结束时间,unix时间戳,每次查询时段不能超过24小时 + param.addProperty("msgid", msgId); //msgid 消息id顺序从小到大,从1开始 + param.addProperty("number", number); //number 每次获取条数,最多10000条 + + String responseContent = this.wxMpService.post(url, param.toString()); + + return WxMpKfMsgList.fromJson(responseContent); + } + + @Override + public WxMpKfMsgList kfMsgList(Date startTime, Date endTime) throws WxErrorException { + int number = 10000; + WxMpKfMsgList result = this.kfMsgList(startTime,endTime, 1L, number); + + if(result != null && result.getNumber() == number){ + Long msgId = result.getMsgId(); + WxMpKfMsgList followingResult = this.kfMsgList(startTime,endTime, msgId, number); + while(followingResult != null && followingResult.getRecords().size() > 0){ + result.getRecords().addAll(followingResult.getRecords()); + result.setNumber(result.getNumber() + followingResult.getNumber()); + result.setMsgId(followingResult.getMsgId()); + followingResult = this.kfMsgList(startTime,endTime, followingResult.getMsgId(), number); + } + } + + return result; + } + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpMaterialServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpMaterialServiceImpl.java new file mode 100644 index 00000000..f6c48f9a --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpMaterialServiceImpl.java @@ -0,0 +1,165 @@ +package me.chanjar.weixin.mp.api.impl.jodd; + +import jodd.http.HttpConnectionProvider; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.fs.FileUtils; +import me.chanjar.weixin.common.util.http.jodd.MediaDownloadRequestExecutor; +import me.chanjar.weixin.common.util.http.jodd.MediaUploadRequestExecutor; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import me.chanjar.weixin.mp.api.WxMpMaterialService; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.material.*; +import me.chanjar.weixin.mp.util.http.jodd.*; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * Created by Binary Wang on 2016/7/21. + */ +public class WxMpMaterialServiceImpl implements WxMpMaterialService { + private static final String MEDIA_API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/media"; + private static final String MATERIAL_API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/material"; + private WxMpService wxMpService; + + public WxMpMaterialServiceImpl(WxMpService wxMpService) { + this.wxMpService = wxMpService; + } + + @Override + public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) throws WxErrorException { + try { + return this.mediaUpload(mediaType, FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType)); + } catch (IOException e) { + e.printStackTrace(); + throw new WxErrorException(WxError.newBuilder().setErrorMsg(e.getMessage()).build()); + } + } + + @Override + public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException { + String url = MEDIA_API_URL_PREFIX + "/upload?type=" + mediaType; + return this.wxMpService.execute(new MediaUploadRequestExecutor(), url, file); + } + + @Override + public File mediaDownload(String media_id) throws WxErrorException { + String url = MEDIA_API_URL_PREFIX + "/get"; + return this.wxMpService.execute( + new MediaDownloadRequestExecutor(this.wxMpService.getWxMpConfigStorage().getTmpDirFile()), + url, + "media_id=" + media_id); + } + + @Override + public WxMediaImgUploadResult mediaImgUpload(File file) throws WxErrorException { + String url = MEDIA_API_URL_PREFIX + "/uploadimg"; + return this.wxMpService.execute(new MediaImgUploadRequestExecutor(), url, file); + } + + @Override + public WxMpMaterialUploadResult materialFileUpload(String mediaType, WxMpMaterial material) throws WxErrorException { + String url = MATERIAL_API_URL_PREFIX + "/add_material?type=" + mediaType; + return this.wxMpService.execute(new MaterialUploadRequestExecutor(), url, material); + } + + @Override + public WxMpMaterialUploadResult materialNewsUpload(WxMpMaterialNews news) throws WxErrorException { + if (news == null || news.isEmpty()) { + throw new IllegalArgumentException("news is empty!"); + } + String url = MATERIAL_API_URL_PREFIX + "/add_news"; + String responseContent = this.wxMpService.post(url, news.toJson()); + return WxMpMaterialUploadResult.fromJson(responseContent); + } + + @Override + public InputStream materialImageOrVoiceDownload(String media_id) throws WxErrorException { + String url = MATERIAL_API_URL_PREFIX + "/get_material"; + return this.wxMpService.execute(new MaterialVoiceAndImageDownloadRequestExecutor(this.wxMpService.getWxMpConfigStorage().getTmpDirFile()), url, media_id); + } + + @Override + public WxMpMaterialVideoInfoResult materialVideoInfo(String media_id) throws WxErrorException { + String url = MATERIAL_API_URL_PREFIX + "/get_material"; + return this.wxMpService.execute(new MaterialVideoInfoRequestExecutor(), url, media_id); + } + + @Override + public WxMpMaterialNews materialNewsInfo(String media_id) throws WxErrorException { + String url = MATERIAL_API_URL_PREFIX + "/get_material"; + return this.wxMpService.execute(new MaterialNewsInfoRequestExecutor(), url, media_id); + } + + @Override + public boolean materialNewsUpdate(WxMpMaterialArticleUpdate wxMpMaterialArticleUpdate) throws WxErrorException { + String url = MATERIAL_API_URL_PREFIX + "/update_news"; + String responseText = this.wxMpService.post(url, wxMpMaterialArticleUpdate.toJson()); + WxError wxError = WxError.fromJson(responseText); + if (wxError.getErrorCode() == 0) { + return true; + } else { + throw new WxErrorException(wxError); + } + } + + @Override + public boolean materialDelete(String media_id) throws WxErrorException { + String url = MATERIAL_API_URL_PREFIX + "/del_material"; + return this.wxMpService.execute(new MaterialDeleteRequestExecutor(), url, media_id); + } + + @Override + public WxMpMaterialCountResult materialCount() throws WxErrorException { + String url = MATERIAL_API_URL_PREFIX + "/get_materialcount"; + String responseText = this.wxMpService.get(url, null); + WxError wxError = WxError.fromJson(responseText); + if (wxError.getErrorCode() == 0) { + return WxMpGsonBuilder.create().fromJson(responseText, WxMpMaterialCountResult.class); + } else { + throw new WxErrorException(wxError); + } + } + + @Override + public WxMpMaterialNewsBatchGetResult materialNewsBatchGet(int offset, int count) throws WxErrorException { + String url = MATERIAL_API_URL_PREFIX + "/batchget_material"; + Map params = new HashMap<>(); + params.put("type", WxConsts.MATERIAL_NEWS); + params.put("offset", offset); + params.put("count", count); + String responseText = this.wxMpService.post(url, WxGsonBuilder.create().toJson(params)); + WxError wxError = WxError.fromJson(responseText); + if (wxError.getErrorCode() == 0) { + return WxMpGsonBuilder.create().fromJson(responseText, WxMpMaterialNewsBatchGetResult.class); + } else { + throw new WxErrorException(wxError); + } + } + + @Override + public WxMpMaterialFileBatchGetResult materialFileBatchGet(String type, int offset, int count) throws WxErrorException { + String url = MATERIAL_API_URL_PREFIX + "/batchget_material"; + Map params = new HashMap<>(); + params.put("type", type); + params.put("offset", offset); + params.put("count", count); + String responseText = this.wxMpService.post(url, WxGsonBuilder.create().toJson(params)); + WxError wxError = WxError.fromJson(responseText); + if (wxError.getErrorCode() == 0) { + return WxMpGsonBuilder.create().fromJson(responseText, WxMpMaterialFileBatchGetResult.class); + } else { + throw new WxErrorException(wxError); + } + } + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpQrcodeServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpQrcodeServiceImpl.java similarity index 94% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpQrcodeServiceImpl.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpQrcodeServiceImpl.java index 8659f2af..fba822b3 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpQrcodeServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpQrcodeServiceImpl.java @@ -1,12 +1,14 @@ -package me.chanjar.weixin.mp.api.impl; +package me.chanjar.weixin.mp.api.impl.jodd; import com.google.gson.JsonObject; +import jodd.http.HttpConnectionProvider; +import jodd.http.ProxyInfo; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.mp.api.WxMpQrcodeService; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; -import me.chanjar.weixin.mp.util.http.QrCodeRequestExecutor; +import me.chanjar.weixin.mp.util.http.jodd.QrCodeRequestExecutor; import java.io.File; import java.io.UnsupportedEncodingException; @@ -18,7 +20,7 @@ import java.nio.charset.StandardCharsets; */ public class WxMpQrcodeServiceImpl implements WxMpQrcodeService { private static final String API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/qrcode"; - private WxMpService wxMpService; + private WxMpService wxMpService; public WxMpQrcodeServiceImpl(WxMpService wxMpService) { this.wxMpService = wxMpService; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpServiceImpl.java new file mode 100644 index 00000000..1480270c --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpServiceImpl.java @@ -0,0 +1,510 @@ +package me.chanjar.weixin.mp.api.impl.jodd; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import jodd.http.*; +import jodd.http.net.SocketHttpConnectionProvider; +import me.chanjar.weixin.common.bean.WxAccessToken; +import me.chanjar.weixin.common.bean.WxJsapiSignature; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.session.StandardSessionManager; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.common.util.RandomUtils; +import me.chanjar.weixin.common.util.crypto.SHA1; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.URIUtil; +import me.chanjar.weixin.common.util.http.jodd.SimpleGetRequestExecutor; +import me.chanjar.weixin.common.util.http.jodd.SimplePostRequestExecutor; +import me.chanjar.weixin.mp.api.*; +import me.chanjar.weixin.mp.api.impl.*; +import me.chanjar.weixin.mp.bean.*; +import me.chanjar.weixin.mp.bean.result.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.concurrent.locks.Lock; + +public class WxMpServiceImpl implements WxMpService { + + private static final JsonParser JSON_PARSER = new JsonParser(); + + protected final Logger log = LoggerFactory.getLogger(this.getClass()); + protected WxSessionManager sessionManager = new StandardSessionManager(); + private WxMpConfigStorage wxMpConfigStorage; + private WxMpKefuService kefuService = new WxMpKefuServiceImpl(this); + private WxMpMaterialService materialService = new WxMpMaterialServiceImpl(this); + private WxMpMenuService menuService = new WxMpMenuServiceImpl(this); + private WxMpUserService userService = new WxMpUserServiceImpl(this); + private WxMpUserTagService tagService = new WxMpUserTagServiceImpl(this); + private WxMpQrcodeService qrCodeService = new WxMpQrcodeServiceImpl(this); + private WxMpCardService cardService = new WxMpCardServiceImpl(this); + private WxMpStoreService storeService = new WxMpStoreServiceImpl(this); + private WxMpDataCubeService dataCubeService = new WxMpDataCubeServiceImpl(this); + private WxMpUserBlacklistService blackListService = new WxMpUserBlacklistServiceImpl(this); + private WxMpTemplateMsgService templateMsgService = new WxMpTemplateMsgServiceImpl(this); + private WxMpDeviceService deviceService = new WxMpDeviceServiceImpl(this); + + private HttpConnectionProvider httpClient; + private ProxyInfo httpProxy; + private int retrySleepMillis = 1000; + private int maxRetryTimes = 5; + + private void initHttpClient() { + WxMpConfigStorage configStorage = this.getWxMpConfigStorage(); + + if (configStorage.getHttpProxyHost() != null && configStorage.getHttpProxyPort() > 0) { + httpProxy = new ProxyInfo(ProxyInfo.ProxyType.HTTP, configStorage.getHttpProxyHost(), configStorage.getHttpProxyPort(), configStorage.getHttpProxyUsername(), configStorage.getHttpProxyPassword()); + } + + httpClient = JoddHttp.httpConnectionProvider; + } + + @Override + public boolean checkSignature(String timestamp, String nonce, String signature) { + try { + return SHA1.gen(this.getWxMpConfigStorage().getToken(), timestamp, nonce) + .equals(signature); + } catch (Exception e) { + return false; + } + } + + @Override + public String getAccessToken() throws WxErrorException { + return getAccessToken(false); + } + + @Override + public String getAccessToken(boolean forceRefresh) throws WxErrorException { + Lock lock = this.getWxMpConfigStorage().getAccessTokenLock(); + try { + lock.lock(); + + if (forceRefresh) { + this.getWxMpConfigStorage().expireAccessToken(); + } + + if (this.getWxMpConfigStorage().isAccessTokenExpired()) { + String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" + + "&appid=" + this.getWxMpConfigStorage().getAppId() + "&secret=" + + this.getWxMpConfigStorage().getSecret(); + + HttpRequest request = HttpRequest.get(url); + if (this.httpProxy != null) { + SocketHttpConnectionProvider provider = new SocketHttpConnectionProvider(); + provider.useProxy(httpProxy); + request.withConnectionProvider(provider); + } + HttpResponse response = request.send(); + String resultContent = response.bodyText(); + WxError error = WxError.fromJson(resultContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + WxAccessToken accessToken = WxAccessToken.fromJson(resultContent); + this.getWxMpConfigStorage().updateAccessToken(accessToken.getAccessToken(), + accessToken.getExpiresIn()); + } + } finally { + lock.unlock(); + } + return this.getWxMpConfigStorage().getAccessToken(); + } + + @Override + public String getJsapiTicket() throws WxErrorException { + return getJsapiTicket(false); + } + + @Override + public String getJsapiTicket(boolean forceRefresh) throws WxErrorException { + Lock lock = this.getWxMpConfigStorage().getJsapiTicketLock(); + try { + lock.lock(); + + if (forceRefresh) { + this.getWxMpConfigStorage().expireJsapiTicket(); + } + + if (this.getWxMpConfigStorage().isJsapiTicketExpired()) { + String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi"; + String responseContent = execute(new SimpleGetRequestExecutor(), url, null); + JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); + JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); + String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); + int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); + this.getWxMpConfigStorage().updateJsapiTicket(jsapiTicket, expiresInSeconds); + } + } finally { + lock.unlock(); + } + return this.getWxMpConfigStorage().getJsapiTicket(); + } + + @Override + public WxJsapiSignature createJsapiSignature(String url) throws WxErrorException { + long timestamp = System.currentTimeMillis() / 1000; + String noncestr = RandomUtils.getRandomStr(); + String jsapiTicket = getJsapiTicket(false); + String signature = SHA1.genWithAmple("jsapi_ticket=" + jsapiTicket, + "noncestr=" + noncestr, "timestamp=" + timestamp, "url=" + url); + WxJsapiSignature jsapiSignature = new WxJsapiSignature(); + jsapiSignature.setAppId(this.getWxMpConfigStorage().getAppId()); + jsapiSignature.setTimestamp(timestamp); + jsapiSignature.setNonceStr(noncestr); + jsapiSignature.setUrl(url); + jsapiSignature.setSignature(signature); + return jsapiSignature; + } + + @Override + public WxMpMassUploadResult massNewsUpload(WxMpMassNews news) throws WxErrorException { + String url = "https://api.weixin.qq.com/cgi-bin/media/uploadnews"; + String responseContent = this.post(url, news.toJson()); + return WxMpMassUploadResult.fromJson(responseContent); + } + + @Override + public WxMpMassUploadResult massVideoUpload(WxMpMassVideo video) throws WxErrorException { + String url = "https://api.weixin.qq.com/cgi-bin/media/uploadvideo"; + String responseContent = this.post(url, video.toJson()); + return WxMpMassUploadResult.fromJson(responseContent); + } + + @Override + public WxMpMassSendResult massGroupMessageSend(WxMpMassTagMessage message) throws WxErrorException { + String url = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall"; + String responseContent = this.post(url, message.toJson()); + return WxMpMassSendResult.fromJson(responseContent); + } + + @Override + public WxMpMassSendResult massOpenIdsMessageSend(WxMpMassOpenIdsMessage message) throws WxErrorException { + String url = "https://api.weixin.qq.com/cgi-bin/message/mass/send"; + String responseContent = this.post(url, message.toJson()); + return WxMpMassSendResult.fromJson(responseContent); + } + + @Override + public WxMpMassSendResult massMessagePreview(WxMpMassPreviewMessage wxMpMassPreviewMessage) throws Exception { + String url = "https://api.weixin.qq.com/cgi-bin/message/mass/preview"; + String responseContent = this.post(url, wxMpMassPreviewMessage.toJson()); + return WxMpMassSendResult.fromJson(responseContent); + } + + @Override + public String shortUrl(String long_url) throws WxErrorException { + String url = "https://api.weixin.qq.com/cgi-bin/shorturl"; + JsonObject o = new JsonObject(); + o.addProperty("action", "long2short"); + o.addProperty("long_url", long_url); + String responseContent = this.post(url, o.toString()); + JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); + return tmpJsonElement.getAsJsonObject().get("short_url").getAsString(); + } + + @Override + public WxMpSemanticQueryResult semanticQuery(WxMpSemanticQuery semanticQuery) throws WxErrorException { + String url = "https://api.weixin.qq.com/semantic/semproxy/search"; + String responseContent = this.post(url, semanticQuery.toJson()); + return WxMpSemanticQueryResult.fromJson(responseContent); + } + + @Override + public String oauth2buildAuthorizationUrl(String redirectURI, String scope, String state) { + StringBuilder url = new StringBuilder(); + url.append("https://open.weixin.qq.com/connect/oauth2/authorize?"); + url.append("appid=").append(this.getWxMpConfigStorage().getAppId()); + url.append("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectURI)); + url.append("&response_type=code"); + url.append("&scope=").append(scope); + if (state != null) { + url.append("&state=").append(state); + } + url.append("#wechat_redirect"); + return url.toString(); + } + + @Override + public String buildQrConnectUrl(String redirectURI, String scope, + String state) { + StringBuilder url = new StringBuilder(); + url.append("https://open.weixin.qq.com/connect/qrconnect?"); + url.append("appid=").append(this.getWxMpConfigStorage().getAppId()); + url.append("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectURI)); + url.append("&response_type=code"); + url.append("&scope=").append(scope); + if (state != null) { + url.append("&state=").append(state); + } + + url.append("#wechat_redirect"); + return url.toString(); + } + + private WxMpOAuth2AccessToken getOAuth2AccessToken(StringBuilder url) throws WxErrorException { + try { + RequestExecutor executor = new SimpleGetRequestExecutor(); + String responseText = executor.execute(getHttpclient(), getHttpProxy(), url.toString(), null); + return WxMpOAuth2AccessToken.fromJson(responseText); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public WxMpOAuth2AccessToken oauth2getAccessToken(String code) throws WxErrorException { + StringBuilder url = new StringBuilder(); + url.append("https://api.weixin.qq.com/sns/oauth2/access_token?"); + url.append("appid=").append(this.getWxMpConfigStorage().getAppId()); + url.append("&secret=").append(this.getWxMpConfigStorage().getSecret()); + url.append("&code=").append(code); + url.append("&grant_type=authorization_code"); + + return this.getOAuth2AccessToken(url); + } + + @Override + public WxMpOAuth2AccessToken oauth2refreshAccessToken(String refreshToken) throws WxErrorException { + StringBuilder url = new StringBuilder(); + url.append("https://api.weixin.qq.com/sns/oauth2/refresh_token?"); + url.append("appid=").append(this.getWxMpConfigStorage().getAppId()); + url.append("&grant_type=refresh_token"); + url.append("&refresh_token=").append(refreshToken); + + return this.getOAuth2AccessToken(url); + } + + @Override + public WxMpUser oauth2getUserInfo(WxMpOAuth2AccessToken oAuth2AccessToken, String lang) throws WxErrorException { + StringBuilder url = new StringBuilder(); + url.append("https://api.weixin.qq.com/sns/userinfo?"); + url.append("access_token=").append(oAuth2AccessToken.getAccessToken()); + url.append("&openid=").append(oAuth2AccessToken.getOpenId()); + if (lang == null) { + url.append("&lang=zh_CN"); + } else { + url.append("&lang=").append(lang); + } + + try { + RequestExecutor executor = new SimpleGetRequestExecutor(); + String responseText = executor.execute(getHttpclient(), getHttpProxy(), url.toString(), null); + return WxMpUser.fromJson(responseText); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public boolean oauth2validateAccessToken(WxMpOAuth2AccessToken oAuth2AccessToken) { + StringBuilder url = new StringBuilder(); + url.append("https://api.weixin.qq.com/sns/auth?"); + url.append("access_token=").append(oAuth2AccessToken.getAccessToken()); + url.append("&openid=").append(oAuth2AccessToken.getOpenId()); + + try { + RequestExecutor executor = new SimpleGetRequestExecutor(); + executor.execute(getHttpclient(), getHttpProxy(), url.toString(), null); + } catch (IOException e) { + throw new RuntimeException(e); + } catch (WxErrorException e) { + return false; + } + return true; + } + + @Override + public String[] getCallbackIP() throws WxErrorException { + String url = "https://api.weixin.qq.com/cgi-bin/getcallbackip"; + String responseContent = get(url, null); + JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); + JsonArray ipList = tmpJsonElement.getAsJsonObject().get("ip_list").getAsJsonArray(); + String[] ipArray = new String[ipList.size()]; + for (int i = 0; i < ipList.size(); i++) { + ipArray[i] = ipList.get(i).getAsString(); + } + return ipArray; + } + + @Override + public String get(String url, String queryParam) throws WxErrorException { + return execute(new SimpleGetRequestExecutor(), url, queryParam); + } + + @Override + public String post(String url, String postData) throws WxErrorException { + return execute(new SimplePostRequestExecutor(), url, postData); + } + + @Override + public HttpConnectionProvider getHttpclient() { + return this.httpClient; + } + + /** + * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 + */ + public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { + int retryTimes = 0; + do { + try { + T result = executeInternal(executor, uri, data); + this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", uri, data, result); + return result; + } catch (WxErrorException e) { + if (retryTimes + 1 > this.maxRetryTimes) { + this.log.warn("重试达到最大次数【{}】", maxRetryTimes); + //最后一次重试失败后,直接抛出异常,不再等待 + throw new RuntimeException("微信服务端异常,超出重试次数"); + } + + WxError error = e.getError(); + // -1 系统繁忙, 1000ms后重试 + if (error.getErrorCode() == -1) { + int sleepMillis = this.retrySleepMillis * (1 << retryTimes); + try { + this.log.warn("微信系统繁忙,{} ms 后重试(第{}次)", sleepMillis, retryTimes + 1); + Thread.sleep(sleepMillis); + } catch (InterruptedException e1) { + throw new RuntimeException(e1); + } + } else { + throw e; + } + } + } while (retryTimes++ < this.maxRetryTimes); + + this.log.warn("重试达到最大次数【{}】", this.maxRetryTimes); + throw new RuntimeException("微信服务端异常,超出重试次数"); + } + + @Override + public synchronized T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { + if (uri.indexOf("access_token=") != -1) { + throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); + } + String accessToken = getAccessToken(false); + + String uriWithAccessToken = uri; + uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken; + + try { + return executor.execute(getHttpclient(), getHttpProxy(), uriWithAccessToken, data); + } catch (WxErrorException e) { + WxError error = e.getError(); + /* + * 发生以下情况时尝试刷新access_token + * 40001 获取access_token时AppSecret错误,或者access_token无效 + * 42001 access_token超时 + */ + if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) { + // 强制设置wxMpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token + this.getWxMpConfigStorage().expireAccessToken(); + if (this.getWxMpConfigStorage().autoRefreshToken()) { + return this.execute(executor, uri, data); + } + } + + if (error.getErrorCode() != 0) { + this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", uri, data, error); + throw new WxErrorException(error); + } + return null; + } catch (IOException e) { + this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[EXCEPTION]: {}", uri, data, e.getMessage()); + throw new RuntimeException(e); + } + } + + @Override + public ProxyInfo getHttpProxy() { + return this.httpProxy; + } + + + @Override + public WxMpConfigStorage getWxMpConfigStorage() { + return this.wxMpConfigStorage; + } + + @Override + public void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider) { + this.wxMpConfigStorage = wxConfigProvider; + this.initHttpClient(); + } + + @Override + public void setRetrySleepMillis(int retrySleepMillis) { + this.retrySleepMillis = retrySleepMillis; + } + + @Override + public void setMaxRetryTimes(int maxRetryTimes) { + this.maxRetryTimes = maxRetryTimes; + } + + @Override + public WxMpKefuService getKefuService() { + return this.kefuService; + } + + @Override + public WxMpMaterialService getMaterialService() { + return this.materialService; + } + + @Override + public WxMpMenuService getMenuService() { + return this.menuService; + } + + @Override + public WxMpUserService getUserService() { + return this.userService; + } + + @Override + public WxMpUserTagService getUserTagService() { + return this.tagService; + } + + @Override + public WxMpQrcodeService getQrcodeService() { + return this.qrCodeService; + } + + @Override + public WxMpCardService getCardService() { + return this.cardService; + } + + @Override + public WxMpDataCubeService getDataCubeService() { + return this.dataCubeService; + } + + @Override + public WxMpUserBlacklistService getBlackListService() { + return this.blackListService; + } + + @Override + public WxMpStoreService getStoreService() { + return this.storeService; + } + + @Override + public WxMpTemplateMsgService getTemplateMsgService() { + return this.templateMsgService; + } + + @Override + public WxMpDeviceService getDeviceService() { + return this.deviceService; + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpUserBlacklistServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpUserBlacklistServiceImpl.java similarity index 87% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpUserBlacklistServiceImpl.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpUserBlacklistServiceImpl.java index b0b35343..f310b3d4 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpUserBlacklistServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpUserBlacklistServiceImpl.java @@ -1,9 +1,11 @@ -package me.chanjar.weixin.mp.api.impl; +package me.chanjar.weixin.mp.api.impl.jodd; import com.google.gson.Gson; import com.google.gson.JsonObject; +import jodd.http.HttpConnectionProvider; +import jodd.http.ProxyInfo; import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; +import me.chanjar.weixin.common.util.http.jodd.SimplePostRequestExecutor; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpUserBlacklistService; import me.chanjar.weixin.mp.bean.result.WxMpUserBlacklistGetResult; @@ -17,7 +19,7 @@ import java.util.Map; */ public class WxMpUserBlacklistServiceImpl implements WxMpUserBlacklistService { private static final String API_BLACKLIST_PREFIX = "https://api.weixin.qq.com/cgi-bin/tags/members"; - private WxMpService wxMpService; + private WxMpService wxMpService; public WxMpUserBlacklistServiceImpl(WxMpService wxMpService) { this.wxMpService = wxMpService; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialDeleteRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialDeleteRequestExecutor.java similarity index 90% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialDeleteRequestExecutor.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialDeleteRequestExecutor.java index 9502afe6..b25d668d 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialDeleteRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialDeleteRequestExecutor.java @@ -1,9 +1,9 @@ -package me.chanjar.weixin.mp.util.http; +package me.chanjar.weixin.mp.util.http.apache; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.http.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; import me.chanjar.weixin.common.util.json.WxGsonBuilder; import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; @@ -16,7 +16,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -public class MaterialDeleteRequestExecutor implements RequestExecutor { +public class MaterialDeleteRequestExecutor implements RequestExecutor { public MaterialDeleteRequestExecutor() { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialNewsInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialNewsInfoRequestExecutor.java similarity index 91% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialNewsInfoRequestExecutor.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialNewsInfoRequestExecutor.java index f61602ab..f29de11f 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialNewsInfoRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialNewsInfoRequestExecutor.java @@ -1,9 +1,9 @@ -package me.chanjar.weixin.mp.util.http; +package me.chanjar.weixin.mp.util.http.apache; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.http.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.http.apache.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; @@ -18,7 +18,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -public class MaterialNewsInfoRequestExecutor implements RequestExecutor { +public class MaterialNewsInfoRequestExecutor implements RequestExecutor { public MaterialNewsInfoRequestExecutor() { super(); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialUploadRequestExecutor.java similarity index 89% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialUploadRequestExecutor.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialUploadRequestExecutor.java index b06c34a6..d0c16f2d 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialUploadRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialUploadRequestExecutor.java @@ -1,9 +1,9 @@ -package me.chanjar.weixin.mp.util.http; +package me.chanjar.weixin.mp.util.http.apache; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.http.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.http.apache.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; @@ -16,10 +16,12 @@ import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.impl.client.CloseableHttpClient; -import java.io.*; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; import java.util.Map; -public class MaterialUploadRequestExecutor implements RequestExecutor { +public class MaterialUploadRequestExecutor implements RequestExecutor { @Override public WxMpMaterialUploadResult execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, WxMpMaterial material) throws WxErrorException, IOException { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVideoInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialVideoInfoRequestExecutor.java similarity index 90% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVideoInfoRequestExecutor.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialVideoInfoRequestExecutor.java index 4eb15e46..16176755 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVideoInfoRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialVideoInfoRequestExecutor.java @@ -1,9 +1,9 @@ -package me.chanjar.weixin.mp.util.http; +package me.chanjar.weixin.mp.util.http.apache; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.http.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; import me.chanjar.weixin.common.util.json.WxGsonBuilder; import me.chanjar.weixin.mp.bean.material.WxMpMaterialVideoInfoResult; import org.apache.http.HttpHost; @@ -17,7 +17,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -public class MaterialVideoInfoRequestExecutor implements RequestExecutor { +public class MaterialVideoInfoRequestExecutor implements RequestExecutor { public MaterialVideoInfoRequestExecutor() { super(); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVoiceAndImageDownloadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialVoiceAndImageDownloadRequestExecutor.java similarity index 92% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVoiceAndImageDownloadRequestExecutor.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialVoiceAndImageDownloadRequestExecutor.java index ceda65a6..3a29ccfa 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVoiceAndImageDownloadRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialVoiceAndImageDownloadRequestExecutor.java @@ -1,12 +1,10 @@ -package me.chanjar.weixin.mp.util.http; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; +package me.chanjar.weixin.mp.util.http.apache; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.apache.InputStreamResponseHandler; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; import org.apache.commons.io.IOUtils; import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; @@ -15,13 +13,14 @@ import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.InputStreamResponseHandler; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; -public class MaterialVoiceAndImageDownloadRequestExecutor implements RequestExecutor { +public class MaterialVoiceAndImageDownloadRequestExecutor implements RequestExecutor { public MaterialVoiceAndImageDownloadRequestExecutor() { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MediaImgUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MediaImgUploadRequestExecutor.java similarity index 91% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MediaImgUploadRequestExecutor.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MediaImgUploadRequestExecutor.java index 2129e8a7..e253f4ee 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MediaImgUploadRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MediaImgUploadRequestExecutor.java @@ -1,9 +1,9 @@ -package me.chanjar.weixin.mp.util.http; +package me.chanjar.weixin.mp.util.http.apache; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.http.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; @@ -21,7 +21,7 @@ import java.io.IOException; /** * @author miller */ -public class MediaImgUploadRequestExecutor implements RequestExecutor { +public class MediaImgUploadRequestExecutor implements RequestExecutor { @Override public WxMediaImgUploadResult execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, File data) throws WxErrorException, IOException { if (data == null) { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/QrCodeRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/QrCodeRequestExecutor.java similarity index 87% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/QrCodeRequestExecutor.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/QrCodeRequestExecutor.java index 2486ca80..b0823365 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/QrCodeRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/QrCodeRequestExecutor.java @@ -1,11 +1,11 @@ -package me.chanjar.weixin.mp.util.http; +package me.chanjar.weixin.mp.util.http.apache; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.fs.FileUtils; -import me.chanjar.weixin.common.util.http.InputStreamResponseHandler; import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.http.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.http.apache.InputStreamResponseHandler; +import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; import org.apache.http.Header; import org.apache.http.HttpHost; @@ -26,20 +26,20 @@ import java.util.UUID; * @author chanjarster * */ -public class QrCodeRequestExecutor implements RequestExecutor { +public class QrCodeRequestExecutor implements RequestExecutor { @Override - public File execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, + public File execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, WxMpQrCodeTicket ticket) throws WxErrorException, IOException { if (ticket != null) { if (uri.indexOf('?') == -1) { uri += '?'; } - uri += uri.endsWith("?") - ? "ticket=" + URLEncoder.encode(ticket.getTicket(), "UTF-8") + uri += uri.endsWith("?") + ? "ticket=" + URLEncoder.encode(ticket.getTicket(), "UTF-8") : "&ticket=" + URLEncoder.encode(ticket.getTicket(), "UTF-8"); } - + HttpGet httpGet = new HttpGet(uri); if (httpProxy != null) { RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialDeleteRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialDeleteRequestExecutor.java new file mode 100644 index 00000000..26485742 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialDeleteRequestExecutor.java @@ -0,0 +1,39 @@ +package me.chanjar.weixin.mp.util.http.jodd; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; + +import java.io.IOException; + +public class MaterialDeleteRequestExecutor implements RequestExecutor { + + + public MaterialDeleteRequestExecutor() { + super(); + } + + @Override + public Boolean execute(HttpConnectionProvider httpclient, ProxyInfo httpProxy, String uri, String materialId) throws WxErrorException, IOException { + HttpRequest request = HttpRequest.post(uri); + if (httpProxy != null) { + httpclient.useProxy(httpProxy); + } + request.withConnectionProvider(httpclient); + + request.query("media_id", materialId); + HttpResponse response = request.send(); + String responseContent = response.bodyText(); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } else { + return true; + } + } + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialNewsInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialNewsInfoRequestExecutor.java new file mode 100644 index 00000000..93b3a735 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialNewsInfoRequestExecutor.java @@ -0,0 +1,41 @@ +package me.chanjar.weixin.mp.util.http.jodd; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.mp.bean.material.WxMpMaterialNews; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +import java.io.IOException; + +public class MaterialNewsInfoRequestExecutor implements RequestExecutor { + + public MaterialNewsInfoRequestExecutor() { + super(); + } + + @Override + public WxMpMaterialNews execute(HttpConnectionProvider httpclient, ProxyInfo httpProxy, String uri, String materialId) throws WxErrorException, IOException { + HttpRequest request = HttpRequest.post(uri); + if (httpProxy != null) { + httpclient.useProxy(httpProxy); + } + request.withConnectionProvider(httpclient); + + request.query("media_id", materialId); + HttpResponse response = request.send(); + + String responseContent = request.bodyText(); + WxError error = WxError.fromJson(responseContent); + 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/http/jodd/MaterialUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialUploadRequestExecutor.java new file mode 100644 index 00000000..85b6665e --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialUploadRequestExecutor.java @@ -0,0 +1,53 @@ +package me.chanjar.weixin.mp.util.http.jodd; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; +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 java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Map; + +public class MaterialUploadRequestExecutor implements RequestExecutor { + + @Override + public WxMpMaterialUploadResult execute(HttpConnectionProvider provider, ProxyInfo httpProxy, String uri, WxMpMaterial material) throws WxErrorException, IOException { + HttpRequest request = HttpRequest.post(uri); + if (httpProxy != null) { + provider.useProxy(httpProxy); + } + request.withConnectionProvider(provider); + + if (material == null) { + throw new WxErrorException(WxError.newBuilder().setErrorMsg("非法请求,material参数为空").build()); + } + + File file = material.getFile(); + if (file == null || !file.exists()) { + throw new FileNotFoundException(); + } + request.form("media", file); + Map form = material.getForm(); + if (material.getForm() != null) { + request.form("description", WxGsonBuilder.create().toJson(form)); + } + + HttpResponse response = request.send(); + String responseContent = response.bodyText(); + WxError error = WxError.fromJson(responseContent); + 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/http/jodd/MaterialVideoInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialVideoInfoRequestExecutor.java new file mode 100644 index 00000000..7b7272b7 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialVideoInfoRequestExecutor.java @@ -0,0 +1,39 @@ +package me.chanjar.weixin.mp.util.http.jodd; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.mp.bean.material.WxMpMaterialVideoInfoResult; + +import java.io.IOException; + +public class MaterialVideoInfoRequestExecutor implements RequestExecutor { + + public MaterialVideoInfoRequestExecutor() { + super(); + } + + @Override + public WxMpMaterialVideoInfoResult execute(HttpConnectionProvider provider, ProxyInfo httpProxy, String uri, String materialId) throws WxErrorException, IOException { + HttpRequest request = HttpRequest.post(uri); + if (httpProxy != null) { + provider.useProxy(httpProxy); + } + request.withConnectionProvider(provider); + + request.query("media_id", materialId); + HttpResponse response =request.send(); + String responseContent = response.bodyText(); + WxError error = WxError.fromJson(responseContent); + 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/http/jodd/MaterialVoiceAndImageDownloadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialVoiceAndImageDownloadRequestExecutor.java new file mode 100644 index 00000000..4d988bad --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialVoiceAndImageDownloadRequestExecutor.java @@ -0,0 +1,57 @@ +package me.chanjar.weixin.mp.util.http.jodd; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import org.apache.commons.io.IOUtils; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +public class MaterialVoiceAndImageDownloadRequestExecutor implements RequestExecutor { + + + public MaterialVoiceAndImageDownloadRequestExecutor() { + super(); + } + + public MaterialVoiceAndImageDownloadRequestExecutor(File tmpDirFile) { + super(); + } + + @Override + public InputStream execute(HttpConnectionProvider provider, ProxyInfo httpProxy, String uri, String materialId) throws WxErrorException, IOException { + HttpRequest request = HttpRequest.post(uri); + if (httpProxy != null) { + provider.useProxy(httpProxy); + } + request.withConnectionProvider(provider); + + request.query("media_id", materialId); + HttpResponse response = request.send(); + + InputStream inputStream = new ByteArrayInputStream(response.bodyBytes()); + // 下载媒体文件出错 + byte[] responseContent = IOUtils.toByteArray(inputStream); + String responseContentString = new String(responseContent, "UTF-8"); + if (responseContentString.length() < 100) { + 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); + } + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MediaImgUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MediaImgUploadRequestExecutor.java new file mode 100644 index 00000000..7c4b13f9 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MediaImgUploadRequestExecutor.java @@ -0,0 +1,42 @@ +package me.chanjar.weixin.mp.util.http.jodd; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult; + +import java.io.File; +import java.io.IOException; + +/** + * @author miller + */ +public class MediaImgUploadRequestExecutor implements RequestExecutor { + @Override + public WxMediaImgUploadResult execute(HttpConnectionProvider provider, ProxyInfo httpProxy, String uri, File data) throws WxErrorException, IOException { + if (data == null) { + throw new WxErrorException(WxError.newBuilder().setErrorMsg("文件对象为空").build()); + } + + HttpRequest request = HttpRequest.post(uri); + if (httpProxy != null) { + provider.useProxy(httpProxy); + } + request.withConnectionProvider(provider); + + request.form("media", data); + HttpResponse response =request.send(); + + String responseContent =response.bodyText(); + WxError error = WxError.fromJson(responseContent); + 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/http/jodd/QrCodeRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/QrCodeRequestExecutor.java new file mode 100644 index 00000000..d1b6f2c5 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/QrCodeRequestExecutor.java @@ -0,0 +1,60 @@ +package me.chanjar.weixin.mp.util.http.jodd; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import jodd.util.MimeTypes; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.fs.FileUtils; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URLEncoder; +import java.util.UUID; + +/** + * 获得QrCode图片 请求执行器 + * + * @author chanjarster + */ +public class QrCodeRequestExecutor implements RequestExecutor { + + @Override + public File execute(HttpConnectionProvider provider, ProxyInfo httpProxy, String uri, + WxMpQrCodeTicket ticket) 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"); + } + + + HttpRequest request = HttpRequest.get(uri); + if (httpProxy != null) { + provider.useProxy(httpProxy); + } + request.withConnectionProvider(provider); + + HttpResponse response = request.send(); + try ( + InputStream inputStream = new ByteArrayInputStream(response.bodyBytes());) { + String contentTypeHeader = response.header("Content-Type"); + // 出错 + if (MimeTypes.MIME_TEXT_PLAIN.equals(contentTypeHeader)) { + String responseContent = response.bodyText(); + throw new WxErrorException(WxError.fromJson(responseContent)); + } + return FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), "jpg"); + } + } + +} diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBusyRetryTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBusyRetryTest.java index da646087..25dedbaa 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBusyRetryTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBusyRetryTest.java @@ -3,8 +3,11 @@ package me.chanjar.weixin.mp.api; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; -import org.testng.annotations.*; +import me.chanjar.weixin.mp.api.impl.apache.WxMpServiceImpl; +import org.apache.http.HttpHost; +import org.apache.http.impl.client.CloseableHttpClient; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -19,8 +22,8 @@ public class WxMpBusyRetryTest { WxMpService service = new WxMpServiceImpl() { @Override - protected synchronized T executeInternal( - RequestExecutor executor, String uri, E data) + public synchronized T executeInternal( + RequestExecutor executor, String uri, E data) throws WxErrorException { this.log.info("Executed"); WxError error = new WxError(); diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpStoreServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpStoreServiceImplTest.java index e4edca74..baa34443 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpStoreServiceImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpStoreServiceImplTest.java @@ -25,7 +25,7 @@ public class WxMpStoreServiceImplTest { private WxMpService wxMpService; /** - * Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpStoreServiceImpl#add(me.chanjar.weixin.mp.bean.store.WxMpStoreBaseInfo)}. + * Test method for {@link WxMpStoreServiceImpl#add(me.chanjar.weixin.mp.bean.store.WxMpStoreBaseInfo)}. * * @throws WxErrorException */ diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/ApiTestModule.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/ApiTestModule.java index 31ad47b6..2cfaec54 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/ApiTestModule.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/ApiTestModule.java @@ -6,7 +6,7 @@ import com.thoughtworks.xstream.XStream; import me.chanjar.weixin.common.util.xml.XStreamInitializer; import me.chanjar.weixin.mp.api.WxMpConfigStorage; import me.chanjar.weixin.mp.api.WxMpService; -import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; +import me.chanjar.weixin.mp.api.impl.apache.WxMpServiceImpl; import java.io.IOException; import java.io.InputStream; diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java index 1c189376..e2c75f83 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java @@ -5,7 +5,7 @@ import me.chanjar.weixin.mp.api.WxMpConfigStorage; import me.chanjar.weixin.mp.api.WxMpMessageHandler; import me.chanjar.weixin.mp.api.WxMpMessageRouter; import me.chanjar.weixin.mp.api.WxMpService; -import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; +import me.chanjar.weixin.mp.api.impl.apache.WxMpServiceImpl; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHolder; From 0b0b5a90fc79e8e93238b3367a6311dbeed10aea Mon Sep 17 00:00:00 2001 From: ecoolper Date: Fri, 21 Apr 2017 23:36:22 +0800 Subject: [PATCH 06/27] common usage jodd-http --- .../http/DefaultApacheHttpClientBuilder.java | 292 ------------------ .../common/util/http/RequestExecutor.java | 8 +- .../common/util/http/Utf8ResponseHandler.java | 33 -- .../{ => apache}/ApacheHttpClientBuilder.java | 2 +- .../DefaultApacheHttpClientBuilder.java | 2 +- .../InputStreamResponseHandler.java | 2 +- .../MediaDownloadRequestExecutor.java | 5 +- .../MediaUploadRequestExecutor.java | 5 +- .../SimpleGetRequestExecutor.java | 5 +- .../SimplePostRequestExecutor.java | 12 +- .../{jodd => apache}/Utf8ResponseHandler.java | 2 +- .../http/jodd/ApacheHttpClientBuilder.java | 53 ---- .../http/jodd/InputStreamResponseHandler.java | 28 -- .../jodd/MediaDownloadRequestExecutor.java | 14 +- .../http/jodd/MediaUploadRequestExecutor.java | 10 +- .../util/http/jodd/RequestExecutor.java | 25 -- .../http/jodd/SimpleGetRequestExecutor.java | 10 +- .../http/jodd/SimplePostRequestExecutor.java | 10 +- .../weixin/common/util/http/jodd/URIUtil.java | 48 --- 19 files changed, 47 insertions(+), 519 deletions(-) delete mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/DefaultApacheHttpClientBuilder.java delete mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/Utf8ResponseHandler.java rename weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/{ => apache}/ApacheHttpClientBuilder.java (95%) rename weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/{jodd => apache}/DefaultApacheHttpClientBuilder.java (99%) rename weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/{ => apache}/InputStreamResponseHandler.java (94%) rename weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/{ => apache}/MediaDownloadRequestExecutor.java (95%) rename weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/{ => apache}/MediaUploadRequestExecutor.java (92%) rename weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/{ => apache}/SimpleGetRequestExecutor.java (90%) rename weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/{ => apache}/SimplePostRequestExecutor.java (92%) rename weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/{jodd => apache}/Utf8ResponseHandler.java (95%) delete mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/ApacheHttpClientBuilder.java delete mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/InputStreamResponseHandler.java delete mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/RequestExecutor.java delete mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/URIUtil.java diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/DefaultApacheHttpClientBuilder.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/DefaultApacheHttpClientBuilder.java deleted file mode 100644 index 030fe98f..00000000 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/DefaultApacheHttpClientBuilder.java +++ /dev/null @@ -1,292 +0,0 @@ -package me.chanjar.weixin.common.util.http; - -import org.apache.commons.lang3.StringUtils; -import org.apache.http.annotation.NotThreadSafe; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.client.HttpRequestRetryHandler; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.config.Registry; -import org.apache.http.config.RegistryBuilder; -import org.apache.http.config.SocketConfig; -import org.apache.http.conn.HttpClientConnectionManager; -import org.apache.http.conn.socket.ConnectionSocketFactory; -import org.apache.http.conn.socket.PlainConnectionSocketFactory; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -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.impl.conn.PoolingHttpClientConnectionManager; -import org.apache.http.protocol.HttpContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * httpclient 连接管理器 - * - * @author kakotor - */ -@NotThreadSafe -public class DefaultApacheHttpClientBuilder implements ApacheHttpClientBuilder { - protected final Logger log = LoggerFactory.getLogger(DefaultApacheHttpClientBuilder.class); - private final AtomicBoolean prepared = new AtomicBoolean(false); - private int connectionRequestTimeout = 3000; - private int connectionTimeout = 5000; - private int soTimeout = 5000; - private int idleConnTimeout = 60000; - private int checkWaitTime = 60000; - private int maxConnPerHost = 10; - private int maxTotalConn = 50; - private String userAgent; - private HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() { - @Override - public boolean retryRequest(IOException exception, int executionCount, HttpContext context) { - return false; - } - }; - private SSLConnectionSocketFactory sslConnectionSocketFactory = SSLConnectionSocketFactory.getSocketFactory(); - private PlainConnectionSocketFactory plainConnectionSocketFactory = PlainConnectionSocketFactory.getSocketFactory(); - private String httpProxyHost; - private int httpProxyPort; - private String httpProxyUsername; - private String httpProxyPassword; - /** - * 闲置连接监控线程 - */ - private IdleConnectionMonitorThread idleConnectionMonitorThread; - private HttpClientBuilder httpClientBuilder; - - private DefaultApacheHttpClientBuilder() { - } - - public static DefaultApacheHttpClientBuilder get() { - return new DefaultApacheHttpClientBuilder(); - } - - @Override - public ApacheHttpClientBuilder httpProxyHost(String httpProxyHost) { - this.httpProxyHost = httpProxyHost; - return this; - } - - @Override - public ApacheHttpClientBuilder httpProxyPort(int httpProxyPort) { - this.httpProxyPort = httpProxyPort; - return this; - } - - @Override - public ApacheHttpClientBuilder httpProxyUsername(String httpProxyUsername) { - this.httpProxyUsername = httpProxyUsername; - return this; - } - - @Override - public ApacheHttpClientBuilder httpProxyPassword(String httpProxyPassword) { - this.httpProxyPassword = httpProxyPassword; - return this; - } - - @Override - public ApacheHttpClientBuilder sslConnectionSocketFactory(SSLConnectionSocketFactory sslConnectionSocketFactory) { - this.sslConnectionSocketFactory = sslConnectionSocketFactory; - return this; - } - - /** - * 获取链接的超时时间设置,默认3000ms - *

- * 设置为零时不超时,一直等待. - * 设置为负数是使用系统默认设置(非上述的3000ms的默认值,而是httpclient的默认设置). - *

- * - * @param connectionRequestTimeout 获取链接的超时时间设置(单位毫秒),默认3000ms - */ - public void setConnectionRequestTimeout(int connectionRequestTimeout) { - this.connectionRequestTimeout = connectionRequestTimeout; - } - - /** - * 建立链接的超时时间,默认为5000ms.由于是在链接池获取链接,此设置应该并不起什么作用 - *

- * 设置为零时不超时,一直等待. - * 设置为负数是使用系统默认设置(非上述的5000ms的默认值,而是httpclient的默认设置). - *

- * - * @param connectionTimeout 建立链接的超时时间设置(单位毫秒),默认5000ms - */ - public void setConnectionTimeout(int connectionTimeout) { - this.connectionTimeout = connectionTimeout; - } - - /** - * 默认NIO的socket超时设置,默认5000ms. - * - * @param soTimeout 默认NIO的socket超时设置,默认5000ms. - * @see java.net.SocketOptions#SO_TIMEOUT - */ - public void setSoTimeout(int soTimeout) { - this.soTimeout = soTimeout; - } - - /** - * 空闲链接的超时时间,默认60000ms. - *

- * 超时的链接将在下一次空闲链接检查是被销毁 - *

- * - * @param idleConnTimeout 空闲链接的超时时间,默认60000ms. - */ - public void setIdleConnTimeout(int idleConnTimeout) { - this.idleConnTimeout = idleConnTimeout; - } - - /** - * 检查空间链接的间隔周期,默认60000ms. - * - * @param checkWaitTime 检查空间链接的间隔周期,默认60000ms. - */ - public void setCheckWaitTime(int checkWaitTime) { - this.checkWaitTime = checkWaitTime; - } - - /** - * 每路的最大链接数,默认10 - * - * @param maxConnPerHost 每路的最大链接数,默认10 - */ - public void setMaxConnPerHost(int maxConnPerHost) { - this.maxConnPerHost = maxConnPerHost; - } - - /** - * 最大总连接数,默认50 - * - * @param maxTotalConn 最大总连接数,默认50 - */ - public void setMaxTotalConn(int maxTotalConn) { - this.maxTotalConn = maxTotalConn; - } - - /** - * 自定义httpclient的User Agent - * - * @param userAgent User Agent - */ - public void setUserAgent(String userAgent) { - this.userAgent = userAgent; - } - - public IdleConnectionMonitorThread getIdleConnectionMonitorThread() { - return this.idleConnectionMonitorThread; - } - - private synchronized void prepare() { - if(prepared.get()){ - return; - } - Registry registry = RegistryBuilder.create() - .register("http", this.plainConnectionSocketFactory) - .register("https", this.sslConnectionSocketFactory) - .build(); - - @SuppressWarnings("resource") - PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry); - connectionManager.setMaxTotal(this.maxTotalConn); - connectionManager.setDefaultMaxPerRoute(this.maxConnPerHost); - connectionManager.setDefaultSocketConfig( - SocketConfig.copy(SocketConfig.DEFAULT) - .setSoTimeout(this.soTimeout) - .build() - ); - - this.idleConnectionMonitorThread = new IdleConnectionMonitorThread( - connectionManager, this.idleConnTimeout, this.checkWaitTime); - this.idleConnectionMonitorThread.setDaemon(true); - this.idleConnectionMonitorThread.start(); - - this.httpClientBuilder = HttpClients.custom() - .setConnectionManager(connectionManager) - .setConnectionManagerShared(true) - .setDefaultRequestConfig( - RequestConfig.custom() - .setSocketTimeout(this.soTimeout) - .setConnectTimeout(this.connectionTimeout) - .setConnectionRequestTimeout(this.connectionRequestTimeout) - .build() - ) - .setRetryHandler(this.httpRequestRetryHandler); - - if (StringUtils.isNotBlank(this.httpProxyHost) - && StringUtils.isNotBlank(this.httpProxyUsername)) { - // 使用代理服务器 需要用户认证的代理服务器 - CredentialsProvider provider = new BasicCredentialsProvider(); - provider.setCredentials( - new AuthScope(this.httpProxyHost, this.httpProxyPort), - new UsernamePasswordCredentials(this.httpProxyUsername, - this.httpProxyPassword)); - this.httpClientBuilder.setDefaultCredentialsProvider(provider); - } - - if (StringUtils.isNotBlank(this.userAgent)) { - this.httpClientBuilder.setUserAgent(this.userAgent); - } - prepared.set(true); - } - - @Override - public CloseableHttpClient build() { - if(!prepared.get()){ - prepare(); - } - return this.httpClientBuilder.build(); - } - - public static class IdleConnectionMonitorThread extends Thread { - private final HttpClientConnectionManager connMgr; - private final int idleConnTimeout; - private final int checkWaitTime; - private volatile boolean shutdown; - - public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr, int idleConnTimeout, int checkWaitTime) { - super("IdleConnectionMonitorThread"); - this.connMgr = connMgr; - this.idleConnTimeout = idleConnTimeout; - this.checkWaitTime = checkWaitTime; - } - - @Override - public void run() { - try { - while (!this.shutdown) { - synchronized (this) { - wait(this.checkWaitTime); - this.connMgr.closeExpiredConnections(); - this.connMgr.closeIdleConnections(this.idleConnTimeout, - TimeUnit.MILLISECONDS); - } - } - } catch (InterruptedException ignore) { - } - } - - public void trigger() { - synchronized (this) { - notifyAll(); - } - } - - public void shutdown() { - this.shutdown = true; - synchronized (this) { - notifyAll(); - } - } - } -} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestExecutor.java index 6d2dbe9a..9110e12a 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestExecutor.java @@ -1,8 +1,6 @@ package me.chanjar.weixin.common.util.http; import me.chanjar.weixin.common.exception.WxErrorException; -import org.apache.http.HttpHost; -import org.apache.http.impl.client.CloseableHttpClient; import java.io.IOException; @@ -12,16 +10,16 @@ import java.io.IOException; * @param 返回值类型 * @param 请求参数类型 */ -public interface RequestExecutor { +public interface RequestExecutor { /** - * @param httpclient 传入的httpClient + * @param httpClient * @param httpProxy http代理对象,如果没有配置代理则为空 * @param uri uri * @param data 数据 * @throws WxErrorException * @throws IOException */ - T execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, E data) throws WxErrorException, IOException; + T execute(H httpClient, P httpProxy, String uri, E data) throws WxErrorException, IOException; } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/Utf8ResponseHandler.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/Utf8ResponseHandler.java deleted file mode 100644 index 148ef965..00000000 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/Utf8ResponseHandler.java +++ /dev/null @@ -1,33 +0,0 @@ -package me.chanjar.weixin.common.util.http; - -import org.apache.http.Consts; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.StatusLine; -import org.apache.http.client.HttpResponseException; -import org.apache.http.client.ResponseHandler; -import org.apache.http.util.EntityUtils; - -import java.io.IOException; - -/** - * copy from {@link org.apache.http.impl.client.BasicResponseHandler} - * - * @author Daniel Qian - */ -public class Utf8ResponseHandler implements ResponseHandler { - - public static final ResponseHandler INSTANCE = new Utf8ResponseHandler(); - - @Override - public String handleResponse(final HttpResponse response) throws IOException { - final StatusLine statusLine = response.getStatusLine(); - final HttpEntity entity = response.getEntity(); - if (statusLine.getStatusCode() >= 300) { - EntityUtils.consume(entity); - throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase()); - } - return entity == null ? null : EntityUtils.toString(entity, Consts.UTF_8); - } - -} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/ApacheHttpClientBuilder.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpClientBuilder.java similarity index 95% rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/ApacheHttpClientBuilder.java rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpClientBuilder.java index c932445d..87a86dba 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/ApacheHttpClientBuilder.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpClientBuilder.java @@ -1,4 +1,4 @@ -package me.chanjar.weixin.common.util.http; +package me.chanjar.weixin.common.util.http.apache; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.client.CloseableHttpClient; diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/DefaultApacheHttpClientBuilder.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/DefaultApacheHttpClientBuilder.java similarity index 99% rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/DefaultApacheHttpClientBuilder.java rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/DefaultApacheHttpClientBuilder.java index 3f667abe..2bb1f072 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/DefaultApacheHttpClientBuilder.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/DefaultApacheHttpClientBuilder.java @@ -1,4 +1,4 @@ -package me.chanjar.weixin.common.util.http.jodd; +package me.chanjar.weixin.common.util.http.apache; import org.apache.commons.lang3.StringUtils; import org.apache.http.annotation.NotThreadSafe; diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/InputStreamResponseHandler.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/InputStreamResponseHandler.java similarity index 94% rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/InputStreamResponseHandler.java rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/InputStreamResponseHandler.java index 0cc1562b..d4cea91d 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/InputStreamResponseHandler.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/InputStreamResponseHandler.java @@ -1,4 +1,4 @@ -package me.chanjar.weixin.common.util.http; +package me.chanjar.weixin.common.util.http.apache; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/MediaDownloadRequestExecutor.java similarity index 95% rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/MediaDownloadRequestExecutor.java index 57024f50..5479a0b6 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/MediaDownloadRequestExecutor.java @@ -1,8 +1,9 @@ -package me.chanjar.weixin.common.util.http; +package me.chanjar.weixin.common.util.http.apache; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.fs.FileUtils; +import me.chanjar.weixin.common.util.http.RequestExecutor; import org.apache.commons.lang3.StringUtils; import org.apache.http.Header; import org.apache.http.HttpHost; @@ -23,7 +24,7 @@ import java.util.regex.Pattern; * 视频文件不支持下载 * @author Daniel Qian */ -public class MediaDownloadRequestExecutor implements RequestExecutor { +public class MediaDownloadRequestExecutor implements RequestExecutor { private File tmpDirFile; 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/apache/MediaUploadRequestExecutor.java similarity index 92% rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaUploadRequestExecutor.java rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/MediaUploadRequestExecutor.java index 54ded05a..66901d3b 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/apache/MediaUploadRequestExecutor.java @@ -1,8 +1,9 @@ -package me.chanjar.weixin.common.util.http; +package me.chanjar.weixin.common.util.http.apache; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; @@ -21,7 +22,7 @@ import java.io.IOException; * * @author Daniel Qian */ -public class MediaUploadRequestExecutor implements RequestExecutor { +public class MediaUploadRequestExecutor implements RequestExecutor { @Override public WxMediaUploadResult execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, File file) throws WxErrorException, IOException { 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/apache/SimpleGetRequestExecutor.java similarity index 90% rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/SimpleGetRequestExecutor.java rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/SimpleGetRequestExecutor.java index ec221e28..fce598f4 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/apache/SimpleGetRequestExecutor.java @@ -1,7 +1,8 @@ -package me.chanjar.weixin.common.util.http; +package me.chanjar.weixin.common.util.http.apache; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; @@ -15,7 +16,7 @@ import java.io.IOException; * * @author Daniel Qian */ -public class SimpleGetRequestExecutor implements RequestExecutor { +public class SimpleGetRequestExecutor implements RequestExecutor { @Override public String execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String queryParam) throws WxErrorException, IOException { 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/apache/SimplePostRequestExecutor.java similarity index 92% rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/SimplePostRequestExecutor.java rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/SimplePostRequestExecutor.java index bdea8573..a63944bc 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/apache/SimplePostRequestExecutor.java @@ -1,7 +1,8 @@ -package me.chanjar.weixin.common.util.http; - -import java.io.IOException; +package me.chanjar.weixin.common.util.http.apache; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; import org.apache.http.Consts; import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; @@ -10,15 +11,14 @@ import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; +import java.io.IOException; /** * 简单的POST请求执行器,请求的参数是String, 返回的结果也是String * * @author Daniel Qian */ -public class SimplePostRequestExecutor implements RequestExecutor { +public class SimplePostRequestExecutor implements RequestExecutor { @Override public String execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String postEntity) throws WxErrorException, IOException { diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/Utf8ResponseHandler.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/Utf8ResponseHandler.java similarity index 95% rename from weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/Utf8ResponseHandler.java rename to weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/Utf8ResponseHandler.java index e26d3e33..697d4695 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/Utf8ResponseHandler.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/Utf8ResponseHandler.java @@ -1,4 +1,4 @@ -package me.chanjar.weixin.common.util.http.jodd; +package me.chanjar.weixin.common.util.http.apache; import org.apache.http.Consts; import org.apache.http.HttpEntity; diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/ApacheHttpClientBuilder.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/ApacheHttpClientBuilder.java deleted file mode 100644 index ce021a04..00000000 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/ApacheHttpClientBuilder.java +++ /dev/null @@ -1,53 +0,0 @@ -package me.chanjar.weixin.common.util.http.jodd; - -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.impl.client.CloseableHttpClient; - -/** - * httpclient build interface - * @author kakotor - */ -public interface ApacheHttpClientBuilder { - - /** - * 构建httpclient实例 - * - * @return new instance of CloseableHttpClient - */ - CloseableHttpClient build(); - - /** - * 代理服务器地址 - * - * @param httpProxyHost - */ - ApacheHttpClientBuilder httpProxyHost(String httpProxyHost); - - /** - * 代理服务器端口 - * - * @param httpProxyPort - */ - ApacheHttpClientBuilder httpProxyPort(int httpProxyPort); - - /** - * 代理服务器用户名 - * - * @param httpProxyUsername - */ - ApacheHttpClientBuilder httpProxyUsername(String httpProxyUsername); - - /** - * 代理服务器密码 - * - * @param httpProxyPassword - */ - ApacheHttpClientBuilder httpProxyPassword(String httpProxyPassword); - - /** - * ssl连接socket工厂 - * - * @param sslConnectionSocketFactory - */ - ApacheHttpClientBuilder sslConnectionSocketFactory(SSLConnectionSocketFactory sslConnectionSocketFactory); -} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/InputStreamResponseHandler.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/InputStreamResponseHandler.java deleted file mode 100644 index a766d4c2..00000000 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/InputStreamResponseHandler.java +++ /dev/null @@ -1,28 +0,0 @@ -package me.chanjar.weixin.common.util.http.jodd; - -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.StatusLine; -import org.apache.http.client.HttpResponseException; -import org.apache.http.client.ResponseHandler; -import org.apache.http.util.EntityUtils; - -import java.io.IOException; -import java.io.InputStream; - -public class InputStreamResponseHandler implements ResponseHandler { - - public static final ResponseHandler INSTANCE = new InputStreamResponseHandler(); - - @Override - public InputStream handleResponse(final HttpResponse response) throws IOException { - final StatusLine statusLine = response.getStatusLine(); - final HttpEntity entity = response.getEntity(); - if (statusLine.getStatusCode() >= 300) { - EntityUtils.consume(entity); - throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase()); - } - return entity == null ? null : entity.getContent(); - } - -} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/MediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/MediaDownloadRequestExecutor.java index ff617e8e..9e4b092f 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/MediaDownloadRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/MediaDownloadRequestExecutor.java @@ -1,11 +1,13 @@ package me.chanjar.weixin.common.util.http.jodd; +import jodd.http.HttpConnectionProvider; import jodd.http.HttpRequest; import jodd.http.HttpResponse; import jodd.http.ProxyInfo; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.fs.FileUtils; +import me.chanjar.weixin.common.util.http.RequestExecutor; import org.apache.commons.lang3.StringUtils; import java.io.ByteArrayInputStream; @@ -21,7 +23,7 @@ import java.util.regex.Pattern; * * @author Daniel Qian */ -public class MediaDownloadRequestExecutor implements RequestExecutor { +public class MediaDownloadRequestExecutor implements RequestExecutor { private File tmpDirFile; @@ -33,7 +35,7 @@ public class MediaDownloadRequestExecutor implements RequestExecutor { +public class MediaUploadRequestExecutor implements RequestExecutor { @Override - public WxMediaUploadResult execute(ProxyInfo httpProxy, String uri, File file) throws WxErrorException, IOException { + public WxMediaUploadResult execute(HttpConnectionProvider provider, ProxyInfo httpProxy, String uri, File file) throws WxErrorException, IOException { HttpRequest request = HttpRequest.post(uri); if (httpProxy != null) { - SocketHttpConnectionProvider provider = new SocketHttpConnectionProvider(); provider.useProxy(httpProxy); - request.withConnectionProvider(provider); } + request.withConnectionProvider(provider); request.form("media", file); HttpResponse response = request.send(); String responseContent =response.bodyText(); diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/RequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/RequestExecutor.java deleted file mode 100644 index ccc82702..00000000 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/RequestExecutor.java +++ /dev/null @@ -1,25 +0,0 @@ -package me.chanjar.weixin.common.util.http.jodd; - -import jodd.http.ProxyInfo; -import me.chanjar.weixin.common.exception.WxErrorException; - -import java.io.IOException; - -/** - * http请求执行器 - * - * @param 返回值类型 - * @param 请求参数类型 - */ -public interface RequestExecutor { - - /** - * @param httpProxy http代理对象,如果没有配置代理则为空 - * @param uri uri - * @param data 数据 - * @throws WxErrorException - * @throws IOException - */ - T execute(ProxyInfo httpProxy, String uri, E data) throws WxErrorException, IOException; - -} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimpleGetRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimpleGetRequestExecutor.java index de84ad7b..221e3b1e 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimpleGetRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimpleGetRequestExecutor.java @@ -1,11 +1,12 @@ package me.chanjar.weixin.common.util.http.jodd; +import jodd.http.HttpConnectionProvider; import jodd.http.HttpRequest; import jodd.http.HttpResponse; import jodd.http.ProxyInfo; -import jodd.http.net.SocketHttpConnectionProvider; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; import java.io.IOException; @@ -14,10 +15,10 @@ import java.io.IOException; * * @author Daniel Qian */ -public class SimpleGetRequestExecutor implements RequestExecutor { +public class SimpleGetRequestExecutor implements RequestExecutor { @Override - public String execute(ProxyInfo httpProxy, String uri, String queryParam) throws WxErrorException, IOException { + public String execute(HttpConnectionProvider provider, ProxyInfo httpProxy, String uri, String queryParam) throws WxErrorException, IOException { if (queryParam != null) { if (uri.indexOf('?') == -1) { uri += '?'; @@ -27,10 +28,9 @@ public class SimpleGetRequestExecutor implements RequestExecutor HttpRequest request = HttpRequest.get(uri); if (httpProxy != null) { - SocketHttpConnectionProvider provider = new SocketHttpConnectionProvider(); provider.useProxy(httpProxy); - request.withConnectionProvider(provider); } + request.withConnectionProvider(provider); HttpResponse response = request.send(); String responseContent = response.bodyText(); WxError error = WxError.fromJson(responseContent); diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimplePostRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimplePostRequestExecutor.java index 276b1310..057abf8e 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimplePostRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimplePostRequestExecutor.java @@ -1,11 +1,12 @@ package me.chanjar.weixin.common.util.http.jodd; +import jodd.http.HttpConnectionProvider; import jodd.http.HttpRequest; import jodd.http.HttpResponse; import jodd.http.ProxyInfo; -import jodd.http.net.SocketHttpConnectionProvider; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; import java.io.IOException; @@ -14,16 +15,15 @@ import java.io.IOException; * * @author Daniel Qian */ -public class SimplePostRequestExecutor implements RequestExecutor { +public class SimplePostRequestExecutor implements RequestExecutor { @Override - public String execute(ProxyInfo httpProxy, String uri, String postEntity) throws WxErrorException, IOException { + public String execute(HttpConnectionProvider provider, ProxyInfo httpProxy, String uri, String postEntity) throws WxErrorException, IOException { HttpRequest request = HttpRequest.post(uri); if (httpProxy != null) { - SocketHttpConnectionProvider provider = new SocketHttpConnectionProvider(); provider.useProxy(httpProxy); - request.withConnectionProvider(provider); } + request.withConnectionProvider(provider); if (postEntity != null) { request.bodyText(postEntity); } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/URIUtil.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/URIUtil.java deleted file mode 100644 index ac293d79..00000000 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/URIUtil.java +++ /dev/null @@ -1,48 +0,0 @@ -package me.chanjar.weixin.common.util.http.jodd; - - -import org.apache.commons.lang3.StringUtils; - -import java.io.UnsupportedEncodingException; - -public class URIUtil { - - private static final String ALLOWED_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'()"; - - public static String encodeURIComponent(String input) { - if (StringUtils.isEmpty(input)) { - return input; - } - - int l = input.length(); - StringBuilder o = new StringBuilder(l * 3); - try { - for (int i = 0; i < l; i++) { - String e = input.substring(i, i + 1); - if (ALLOWED_CHARS.indexOf(e) == -1) { - byte[] b = e.getBytes("utf-8"); - o.append(getHex(b)); - continue; - } - o.append(e); - } - return o.toString(); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - return input; - } - - private static String getHex(byte buf[]) { - StringBuilder o = new StringBuilder(buf.length * 3); - for (int i = 0; i < buf.length; i++) { - int n = buf[i] & 0xff; - o.append("%"); - if (n < 0x10) { - o.append("0"); - } - o.append(Long.toString(n, 16).toUpperCase()); - } - return o.toString(); - } -} From 5726ca9c0443a6ee35fe9f5d5b298d99f16aaee6 Mon Sep 17 00:00:00 2001 From: ecoolper Date: Sat, 22 Apr 2017 00:29:42 +0800 Subject: [PATCH 07/27] cp usage jodd-http --- .../chanjar/weixin/cp/api/WxCpConfigStorage.java | 2 +- .../weixin/cp/api/WxCpInMemoryConfigStorage.java | 2 +- .../weixin/cp/api/WxCpJedisConfigStorage.java | 2 +- .../java/me/chanjar/weixin/cp/api/WxCpService.java | 8 +++++--- .../cp/api/{ => impl/apache}/WxCpServiceImpl.java | 14 +++++++++----- .../me/chanjar/weixin/cp/api/ApiTestModule.java | 1 + .../chanjar/weixin/cp/api/WxCpDepartAPITest.java | 1 + .../me/chanjar/weixin/cp/api/WxCpMediaAPITest.java | 1 + .../me/chanjar/weixin/cp/api/WxCpTagAPITest.java | 1 + .../me/chanjar/weixin/cp/api/WxCpUserAPITest.java | 1 + .../me/chanjar/weixin/cp/api/WxMenuAPITest.java | 1 + .../cp/api/{ => impl/apache}/WxCpBaseAPITest.java | 4 +++- .../api/{ => impl/apache}/WxCpBusyRetryTest.java | 9 ++++++--- .../api/{ => impl/apache}/WxCpMessageAPITest.java | 9 ++++----- .../me/chanjar/weixin/cp/demo/WxCpDemoServer.java | 2 +- weixin-java-cp/src/test/resources/testng.xml | 6 +++--- 16 files changed, 40 insertions(+), 24 deletions(-) rename weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/{ => impl/apache}/WxCpServiceImpl.java (97%) rename weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/{ => impl/apache}/WxCpBaseAPITest.java (85%) rename weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/{ => impl/apache}/WxCpBusyRetryTest.java (86%) rename weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/{ => impl/apache}/WxCpMessageAPITest.java (93%) diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpConfigStorage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpConfigStorage.java index eb1e57ca..3484db3b 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpConfigStorage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpConfigStorage.java @@ -1,7 +1,7 @@ package me.chanjar.weixin.cp.api; import me.chanjar.weixin.common.bean.WxAccessToken; -import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; import java.io.File; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpInMemoryConfigStorage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpInMemoryConfigStorage.java index 867dd6bb..b1eeb827 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpInMemoryConfigStorage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpInMemoryConfigStorage.java @@ -2,7 +2,7 @@ package me.chanjar.weixin.cp.api; import me.chanjar.weixin.common.bean.WxAccessToken; import me.chanjar.weixin.common.util.ToStringUtils; -import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; import java.io.File; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpJedisConfigStorage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpJedisConfigStorage.java index 92513965..07f38ebb 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpJedisConfigStorage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpJedisConfigStorage.java @@ -1,7 +1,7 @@ package me.chanjar.weixin.cp.api; import me.chanjar.weixin.common.bean.WxAccessToken; -import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java index bd0b322f..e8a0baf7 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java @@ -20,7 +20,7 @@ import java.util.List; /** * 微信API的Service */ -public interface WxCpService { +public interface WxCpService { /** *
@@ -469,7 +469,7 @@ public interface WxCpService {
    * 
    * Service没有实现某个API的时候,可以用这个,
    * 比{@link #get}和{@link #post}方法更灵活,可以自己构造RequestExecutor用来处理不同的参数和不同的返回类型。
-   * 可以参考,{@link me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor}的实现方法
+   * 可以参考,{@link me.chanjar.weixin.common.util.http.jodd.MediaUploadRequestExecutor}的实现方法
    * 
* * @param executor 执行器 @@ -478,7 +478,9 @@ public interface WxCpService { * @param 请求值类型 * @param 返回值类型 */ - T execute(RequestExecutor executor, String uri, E data) throws WxErrorException; + T execute(RequestExecutor executor, String uri, E data) throws WxErrorException; + + T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException; /** * 注入 {@link WxCpConfigStorage} 的实现 diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java similarity index 97% rename from weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpServiceImpl.java rename to weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java index 0105e78d..522c449f 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java @@ -1,4 +1,4 @@ -package me.chanjar.weixin.cp.api; +package me.chanjar.weixin.cp.api.impl.apache; import com.google.gson.*; import com.google.gson.reflect.TypeToken; @@ -14,8 +14,12 @@ import me.chanjar.weixin.common.session.WxSessionManager; import me.chanjar.weixin.common.util.RandomUtils; import me.chanjar.weixin.common.util.crypto.SHA1; import me.chanjar.weixin.common.util.fs.FileUtils; -import me.chanjar.weixin.common.util.http.*; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.URIUtil; +import me.chanjar.weixin.common.util.http.apache.*; import me.chanjar.weixin.common.util.json.GsonHelper; +import me.chanjar.weixin.cp.api.WxCpConfigStorage; +import me.chanjar.weixin.cp.api.WxCpService; import me.chanjar.weixin.cp.bean.WxCpDepart; import me.chanjar.weixin.cp.bean.WxCpMessage; import me.chanjar.weixin.cp.bean.WxCpTag; @@ -37,7 +41,7 @@ import java.io.InputStream; import java.util.List; import java.util.UUID; -public class WxCpServiceImpl implements WxCpService { +public class WxCpServiceImpl implements WxCpService { protected final Logger log = LoggerFactory.getLogger(WxCpServiceImpl.class); @@ -534,7 +538,7 @@ public class WxCpServiceImpl implements WxCpService { * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 */ @Override - public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { + public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { int retryTimes = 0; do { try { @@ -570,7 +574,7 @@ public class WxCpServiceImpl implements WxCpService { throw new RuntimeException("微信服务端异常,超出重试次数"); } - protected synchronized T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { + public synchronized T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { if (uri.contains("access_token=")) { throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); } diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/ApiTestModule.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/ApiTestModule.java index 2a694ff3..80265168 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/ApiTestModule.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/ApiTestModule.java @@ -9,6 +9,7 @@ import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; import me.chanjar.weixin.common.util.xml.XStreamInitializer; +import me.chanjar.weixin.cp.api.impl.apache.WxCpServiceImpl; public class ApiTestModule implements Module { diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpDepartAPITest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpDepartAPITest.java index c0cc3251..1a3fb795 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpDepartAPITest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpDepartAPITest.java @@ -2,6 +2,7 @@ package me.chanjar.weixin.cp.api; import java.util.List; +import me.chanjar.weixin.cp.api.impl.apache.WxCpServiceImpl; import org.testng.Assert; import org.testng.annotations.Guice; import org.testng.annotations.Test; diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMediaAPITest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMediaAPITest.java index d9fb2605..3f297968 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMediaAPITest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMediaAPITest.java @@ -5,6 +5,7 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.List; +import me.chanjar.weixin.cp.api.impl.apache.WxCpServiceImpl; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Guice; diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpTagAPITest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpTagAPITest.java index aa26e962..d5ff3a3a 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpTagAPITest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpTagAPITest.java @@ -1,6 +1,7 @@ package me.chanjar.weixin.cp.api; import com.google.inject.Inject; +import me.chanjar.weixin.cp.api.impl.apache.WxCpServiceImpl; import me.chanjar.weixin.cp.bean.WxCpTag; import me.chanjar.weixin.cp.bean.WxCpUser; import org.testng.Assert; diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpUserAPITest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpUserAPITest.java index 4d5a7a91..450cefa2 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpUserAPITest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpUserAPITest.java @@ -2,6 +2,7 @@ package me.chanjar.weixin.cp.api; import com.google.inject.Inject; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.cp.api.impl.apache.WxCpServiceImpl; import me.chanjar.weixin.cp.bean.WxCpDepart; import me.chanjar.weixin.cp.bean.WxCpUser; import org.testng.Assert; diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxMenuAPITest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxMenuAPITest.java index c837e51e..a6fdfa9d 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxMenuAPITest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxMenuAPITest.java @@ -5,6 +5,7 @@ import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.bean.menu.WxMenu; import me.chanjar.weixin.common.bean.menu.WxMenuButton; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.cp.api.impl.apache.WxCpServiceImpl; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Guice; diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpBaseAPITest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/apache/WxCpBaseAPITest.java similarity index 85% rename from weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpBaseAPITest.java rename to weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/apache/WxCpBaseAPITest.java index 894bb3b6..6fecf6e7 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpBaseAPITest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/apache/WxCpBaseAPITest.java @@ -1,7 +1,9 @@ -package me.chanjar.weixin.cp.api; +package me.chanjar.weixin.cp.api.impl.apache; import com.google.inject.Inject; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.cp.api.ApiTestModule; +import me.chanjar.weixin.cp.api.WxCpConfigStorage; import org.apache.commons.lang3.StringUtils; import org.testng.Assert; import org.testng.annotations.Guice; diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpBusyRetryTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/apache/WxCpBusyRetryTest.java similarity index 86% rename from weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpBusyRetryTest.java rename to weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/apache/WxCpBusyRetryTest.java index e1b005bd..90b1d1b3 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpBusyRetryTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/apache/WxCpBusyRetryTest.java @@ -1,8 +1,11 @@ -package me.chanjar.weixin.cp.api; +package me.chanjar.weixin.cp.api.impl.apache; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.cp.api.WxCpService; +import org.apache.http.HttpHost; +import org.apache.http.impl.client.CloseableHttpClient; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -19,8 +22,8 @@ public class WxCpBusyRetryTest { WxCpService service = new WxCpServiceImpl() { @Override - protected synchronized T executeInternal( - RequestExecutor executor, String uri, E data) + public synchronized T executeInternal( + RequestExecutor executor, String uri, E data) throws WxErrorException { this.log.info("Executed"); WxError error = new WxError(); diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMessageAPITest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/apache/WxCpMessageAPITest.java similarity index 93% rename from weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMessageAPITest.java rename to weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/apache/WxCpMessageAPITest.java index b7bcf7a3..968cfea9 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMessageAPITest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/apache/WxCpMessageAPITest.java @@ -1,13 +1,12 @@ -package me.chanjar.weixin.cp.api; - -import org.testng.annotations.Guice; -import org.testng.annotations.Test; +package me.chanjar.weixin.cp.api.impl.apache; import com.google.inject.Inject; - import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.cp.api.ApiTestModule; import me.chanjar.weixin.cp.bean.WxCpMessage; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; /*** * 测试发送消息 diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/demo/WxCpDemoServer.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/demo/WxCpDemoServer.java index dc667d88..eb78d667 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/demo/WxCpDemoServer.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/demo/WxCpDemoServer.java @@ -13,7 +13,7 @@ import me.chanjar.weixin.cp.api.WxCpConfigStorage; import me.chanjar.weixin.cp.api.WxCpMessageHandler; import me.chanjar.weixin.cp.api.WxCpMessageRouter; import me.chanjar.weixin.cp.api.WxCpService; -import me.chanjar.weixin.cp.api.WxCpServiceImpl; +import me.chanjar.weixin.cp.api.impl.apache.WxCpServiceImpl; import me.chanjar.weixin.cp.bean.WxCpXmlMessage; import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; import me.chanjar.weixin.cp.bean.WxCpXmlOutTextMessage; diff --git a/weixin-java-cp/src/test/resources/testng.xml b/weixin-java-cp/src/test/resources/testng.xml index ba92bc0c..04f960ed 100644 --- a/weixin-java-cp/src/test/resources/testng.xml +++ b/weixin-java-cp/src/test/resources/testng.xml @@ -3,9 +3,9 @@ - - - + + + From 76330ef3c646704044a53cd3a595385c6dd48a80 Mon Sep 17 00:00:00 2001 From: ecoolper Date: Sat, 22 Apr 2017 13:34:22 +0800 Subject: [PATCH 08/27] =?UTF-8?q?=E8=A3=85=E9=A5=B0=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../http/MediaDownloadRequestExecutor.java | 161 ++++++++++++++++++ .../util/http/MediaUploadRequestExecutor.java | 95 +++++++++++ .../common/util/http/RequestExecutor.java | 10 +- .../weixin/common/util/http/RequestHttp.java | 20 +++ .../util/http/SimpleGetRequestExecutor.java | 91 ++++++++++ .../util/http/SimplePostRequestExecutor.java | 112 ++++++++++++ .../apache/MediaDownloadRequestExecutor.java | 94 ---------- .../apache/MediaUploadRequestExecutor.java | 55 ------ .../http/apache/SimpleGetRequestExecutor.java | 47 ----- .../apache/SimplePostRequestExecutor.java | 59 ------- .../jodd/MediaDownloadRequestExecutor.java | 82 --------- .../http/jodd/MediaUploadRequestExecutor.java | 39 ----- .../http/jodd/SimpleGetRequestExecutor.java | 43 ----- .../http/jodd/SimplePostRequestExecutor.java | 51 ------ 14 files changed, 483 insertions(+), 476 deletions(-) create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaUploadRequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestHttp.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/SimpleGetRequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/SimplePostRequestExecutor.java delete mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/MediaDownloadRequestExecutor.java delete mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/MediaUploadRequestExecutor.java delete mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/SimpleGetRequestExecutor.java delete mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/SimplePostRequestExecutor.java delete mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/MediaDownloadRequestExecutor.java delete mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/MediaUploadRequestExecutor.java delete mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimpleGetRequestExecutor.java delete mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimplePostRequestExecutor.java diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java new file mode 100644 index 00000000..cfe382e1 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java @@ -0,0 +1,161 @@ +package me.chanjar.weixin.common.util.http; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.fs.FileUtils; +import me.chanjar.weixin.common.util.http.apache.InputStreamResponseHandler; +import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +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.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 下载媒体文件请求执行器,请求的参数是String, 返回的结果是File + * 视频文件不支持下载 + * + * @author Daniel Qian + */ +public class MediaDownloadRequestExecutor implements RequestExecutor { + + private File tmpDirFile; + + public MediaDownloadRequestExecutor(File tmpDirFile) { + this.tmpDirFile = tmpDirFile; + } + + @Override + public File execute(RequestHttp requestHttp, String uri, String queryParam) throws WxErrorException, IOException { + if (requestHttp.getHttpClient() instanceof CloseableHttpClient) { + CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getHttpClient(); + HttpHost httpProxy = (HttpHost) requestHttp.getHttpProxy(); + return executeApache(httpClient, httpProxy, uri, queryParam); + } + if (requestHttp.getHttpClient() instanceof HttpConnectionProvider) { + HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getHttpClient(); + ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getHttpProxy(); + return executeJodd(provider, proxyInfo, uri, queryParam); + } else { + //这里需要抛出异常,需要优化 + return null; + } + } + + private String getFileNameJodd(HttpResponse response) throws WxErrorException { + String content = response.header("Content-disposition"); + if (content == null || content.length() == 0) { + throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); + } + + Pattern p = Pattern.compile(".*filename=\"(.*)\""); + Matcher m = p.matcher(content); + if (m.matches()) { + return m.group(1); + } + throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); + } + + private String getFileNameApache(CloseableHttpResponse response) throws WxErrorException { + Header[] contentDispositionHeader = response.getHeaders("Content-disposition"); + if(contentDispositionHeader == null || contentDispositionHeader.length == 0){ + throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); + } + + Pattern p = Pattern.compile(".*filename=\"(.*)\""); + Matcher m = p.matcher(contentDispositionHeader[0].getValue()); + if(m.matches()){ + return m.group(1); + } + throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); + } + + + private File executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String queryParam) throws WxErrorException, IOException { + if (queryParam != null) { + if (uri.indexOf('?') == -1) { + uri += '?'; + } + uri += uri.endsWith("?") ? queryParam : '&' + queryParam; + } + + HttpGet httpGet = new HttpGet(uri); + if (httpProxy != null) { + RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); + httpGet.setConfig(config); + } + + try (CloseableHttpResponse response = httpclient.execute(httpGet); + InputStream inputStream = InputStreamResponseHandler.INSTANCE + .handleResponse(response)) { + + Header[] contentTypeHeader = response.getHeaders("Content-Type"); + if (contentTypeHeader != null && contentTypeHeader.length > 0) { + if (contentTypeHeader[0].getValue().startsWith(ContentType.APPLICATION_JSON.getMimeType())) { + // application/json; encoding=utf-8 下载媒体文件出错 + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + throw new WxErrorException(WxError.fromJson(responseContent)); + } + } + + String fileName = getFileNameApache(response); + if (StringUtils.isBlank(fileName)) { + return null; + } + + String[] nameAndExt = fileName.split("\\."); + return FileUtils.createTmpFile(inputStream, nameAndExt[0], nameAndExt[1], this.tmpDirFile); + + } finally { + httpGet.releaseConnection(); + } + + } + + + private File executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, String queryParam) throws WxErrorException, IOException { + if (queryParam != null) { + if (uri.indexOf('?') == -1) { + uri += '?'; + } + uri += uri.endsWith("?") ? queryParam : '&' + queryParam; + } + + HttpRequest request = HttpRequest.post(uri); + if (proxyInfo != null) { + provider.useProxy(proxyInfo); + } + request.withConnectionProvider(provider); + HttpResponse response = request.send(); + String contentType = response.header("Content-Type"); + if (contentType != null && contentType.startsWith("application/json")) { + // application/json; encoding=utf-8 下载媒体文件出错 + throw new WxErrorException(WxError.fromJson(response.bodyText())); + } + + String fileName = getFileNameJodd(response); + if (StringUtils.isBlank(fileName)) { + return null; + } + + InputStream inputStream = new ByteArrayInputStream(response.bodyBytes()); + String[] nameAndExt = fileName.split("\\."); + return FileUtils.createTmpFile(inputStream, nameAndExt[0], nameAndExt[1], this.tmpDirFile); + } + + +} 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 new file mode 100644 index 00000000..b891c46b --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaUploadRequestExecutor.java @@ -0,0 +1,95 @@ +package me.chanjar.weixin.common.util.http; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; +import me.chanjar.weixin.common.exception.WxErrorException; +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.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ContentType; +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 Daniel Qian + */ +public class MediaUploadRequestExecutor implements RequestExecutor { + + @Override + public WxMediaUploadResult execute(RequestHttp requestHttp, String uri, File file) throws WxErrorException, IOException { + if (requestHttp.getHttpClient() instanceof CloseableHttpClient) { + CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getHttpClient(); + HttpHost httpProxy = (HttpHost) requestHttp.getHttpProxy(); + return executeApache(httpClient, httpProxy, uri, file); + } + if (requestHttp.getHttpClient() instanceof HttpConnectionProvider) { + HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getHttpClient(); + ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getHttpProxy(); + return executeJodd(provider, proxyInfo, uri, file); + } else { + //这里需要抛出异常,需要优化 + return null; + } + + + } + + private WxMediaUploadResult executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, File file) throws WxErrorException, IOException { + HttpPost httpPost = new HttpPost(uri); + if (httpProxy != null) { + RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); + httpPost.setConfig(config); + } + if (file != null) { + HttpEntity entity = MultipartEntityBuilder + .create() + .addBinaryBody("media", file) + .setMode(HttpMultipartMode.RFC6532) + .build(); + httpPost.setEntity(entity); + httpPost.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.toString()); + } + try (CloseableHttpResponse response = httpclient.execute(httpPost)) { + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return WxMediaUploadResult.fromJson(responseContent); + } finally { + httpPost.releaseConnection(); + } + } + + + private WxMediaUploadResult executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, File file) throws WxErrorException, IOException { + HttpRequest request = HttpRequest.post(uri); + if (proxyInfo != null) { + provider.useProxy(proxyInfo); + } + request.withConnectionProvider(provider); + request.form("media", file); + HttpResponse response = request.send(); + String responseContent = response.bodyText(); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return WxMediaUploadResult.fromJson(responseContent); + } + + +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestExecutor.java index 9110e12a..78834701 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestExecutor.java @@ -10,16 +10,14 @@ import java.io.IOException; * @param 返回值类型 * @param 请求参数类型 */ -public interface RequestExecutor { +public interface RequestExecutor { /** - * @param httpClient - * @param httpProxy http代理对象,如果没有配置代理则为空 - * @param uri uri - * @param data 数据 + * @param uri uri + * @param data 数据 * @throws WxErrorException * @throws IOException */ - T execute(H httpClient, P httpProxy, String uri, E data) throws WxErrorException, IOException; + T execute(RequestHttp requestHttp, String uri, E data) throws WxErrorException, IOException; } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestHttp.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestHttp.java new file mode 100644 index 00000000..785c1b84 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestHttp.java @@ -0,0 +1,20 @@ +package me.chanjar.weixin.common.util.http; + +/** + * Created by ecoolper on 2017/4/22. + */ +public interface RequestHttp { + + /** + * httpClient + * @return + */ + Object getHttpClient(); + + /** + * httpProxy + * @return + */ + Object getHttpProxy(); + +} 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 new file mode 100644 index 00000000..11823942 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/SimpleGetRequestExecutor.java @@ -0,0 +1,91 @@ +package me.chanjar.weixin.common.util.http; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +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.impl.client.CloseableHttpClient; + +import java.io.IOException; + +/** + * 简单的GET请求执行器,请求的参数是String, 返回的结果也是String + * + * @author Daniel Qian + */ +public class SimpleGetRequestExecutor implements RequestExecutor { + + @Override + public String execute(RequestHttp requestHttp, String uri, String queryParam) throws WxErrorException, IOException { + if (requestHttp.getHttpClient() instanceof CloseableHttpClient) { + CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getHttpClient(); + HttpHost httpProxy = (HttpHost) requestHttp.getHttpProxy(); + return executeApache(httpClient, httpProxy, uri, queryParam); + } + if (requestHttp.getHttpClient() instanceof HttpConnectionProvider) { + HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getHttpClient(); + ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getHttpProxy(); + return executeJodd(provider, proxyInfo, uri, queryParam); + } else { + //这里需要抛出异常,需要优化 + return null; + } + } + + + private String executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String queryParam) throws WxErrorException, IOException { + if (queryParam != null) { + if (uri.indexOf('?') == -1) { + uri += '?'; + } + uri += uri.endsWith("?") ? queryParam : '&' + queryParam; + } + HttpGet httpGet = new HttpGet(uri); + if (httpProxy != null) { + RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); + httpGet.setConfig(config); + } + + try (CloseableHttpResponse response = httpclient.execute(httpGet)) { + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return responseContent; + } finally { + httpGet.releaseConnection(); + } + } + + + private String executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, String queryParam) throws WxErrorException, IOException { + if (queryParam != null) { + if (uri.indexOf('?') == -1) { + uri += '?'; + } + uri += uri.endsWith("?") ? queryParam : '&' + queryParam; + } + + HttpRequest request = HttpRequest.get(uri); + if (proxyInfo != null) { + provider.useProxy(proxyInfo); + } + request.withConnectionProvider(provider); + HttpResponse response = request.send(); + String responseContent = response.bodyText(); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return responseContent; + } + +} 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 new file mode 100644 index 00000000..39cb90d6 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/SimplePostRequestExecutor.java @@ -0,0 +1,112 @@ +package me.chanjar.weixin.common.util.http; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import org.apache.http.Consts; +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.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; + +import java.io.IOException; + +/** + * 用装饰模式实现 + * 简单的POST请求执行器,请求的参数是String, 返回的结果也是String + * + * @author Daniel Qian + */ +public class SimplePostRequestExecutor implements RequestExecutor { + + @Override + public String execute(RequestHttp requestHttp, String uri, String postEntity) throws WxErrorException, IOException { + if (requestHttp.getHttpClient() instanceof CloseableHttpClient) { + CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getHttpClient(); + HttpHost httpProxy = (HttpHost) requestHttp.getHttpProxy(); + return executeApache(httpClient, httpProxy, uri, postEntity); + } + if (requestHttp.getHttpClient() instanceof HttpConnectionProvider) { + HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getHttpClient(); + ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getHttpProxy(); + return executeJodd(provider, proxyInfo, uri, postEntity); + } else { + //这里需要抛出异常,需要优化 + return null; + } + } + + private String executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String postEntity) throws WxErrorException, IOException { + HttpPost httpPost = new HttpPost(uri); + if (httpProxy != null) { + RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); + httpPost.setConfig(config); + } + + if (postEntity != null) { + StringEntity entity = new StringEntity(postEntity, Consts.UTF_8); + httpPost.setEntity(entity); + } + + try (CloseableHttpResponse response = httpclient.execute(httpPost)) { + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + if (responseContent.isEmpty()) { + throw new WxErrorException( + WxError.newBuilder().setErrorCode(9999).setErrorMsg("无响应内容") + .build()); + } + + if (responseContent.startsWith("")) { + //xml格式输出直接返回 + return responseContent; + } + + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return responseContent; + } finally { + httpPost.releaseConnection(); + } + } + + + private String executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, String postEntity) throws WxErrorException, IOException { + HttpRequest request = HttpRequest.post(uri); + if (proxyInfo != null) { + provider.useProxy(proxyInfo); + } + request.withConnectionProvider(provider); + if (postEntity != null) { + request.bodyText(postEntity); + } + HttpResponse response = request.send(); + + String responseContent = response.bodyText(); + if (responseContent.isEmpty()) { + throw new WxErrorException( + WxError.newBuilder().setErrorCode(9999).setErrorMsg("无响应内容") + .build()); + } + + if (responseContent.startsWith("")) { + //xml格式输出直接返回 + return responseContent; + } + + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return responseContent; + } + + +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/MediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/MediaDownloadRequestExecutor.java deleted file mode 100644 index 5479a0b6..00000000 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/MediaDownloadRequestExecutor.java +++ /dev/null @@ -1,94 +0,0 @@ -package me.chanjar.weixin.common.util.http.apache; - -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.fs.FileUtils; -import me.chanjar.weixin.common.util.http.RequestExecutor; -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; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * 下载媒体文件请求执行器,请求的参数是String, 返回的结果是File - * 视频文件不支持下载 - * @author Daniel Qian - */ -public class MediaDownloadRequestExecutor implements RequestExecutor { - - private File tmpDirFile; - - public MediaDownloadRequestExecutor() { - } - - public MediaDownloadRequestExecutor(File tmpDirFile) { - this.tmpDirFile = tmpDirFile; - } - - @Override - public File execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String queryParam) throws WxErrorException, IOException { - if (queryParam != null) { - if (uri.indexOf('?') == -1) { - uri += '?'; - } - uri += uri.endsWith("?") ? queryParam : '&' + queryParam; - } - - HttpGet httpGet = new HttpGet(uri); - if (httpProxy != null) { - RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); - httpGet.setConfig(config); - } - - try (CloseableHttpResponse response = httpclient.execute(httpGet); - InputStream inputStream = InputStreamResponseHandler.INSTANCE - .handleResponse(response)) { - - Header[] contentTypeHeader = response.getHeaders("Content-Type"); - if (contentTypeHeader != null && contentTypeHeader.length > 0) { - if (contentTypeHeader[0].getValue().startsWith(ContentType.APPLICATION_JSON.getMimeType())) { - // application/json; encoding=utf-8 下载媒体文件出错 - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - throw new WxErrorException(WxError.fromJson(responseContent)); - } - } - - String fileName = getFileName(response); - if (StringUtils.isBlank(fileName)) { - return null; - } - - String[] nameAndExt = fileName.split("\\."); - return FileUtils.createTmpFile(inputStream, nameAndExt[0], nameAndExt[1], this.tmpDirFile); - - } finally { - httpGet.releaseConnection(); - } - - } - - private String getFileName(CloseableHttpResponse response) throws WxErrorException { - Header[] contentDispositionHeader = response.getHeaders("Content-disposition"); - if(contentDispositionHeader == null || contentDispositionHeader.length == 0){ - throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); - } - - Pattern p = Pattern.compile(".*filename=\"(.*)\""); - Matcher m = p.matcher(contentDispositionHeader[0].getValue()); - if(m.matches()){ - return m.group(1); - } - throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); - } - -} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/MediaUploadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/MediaUploadRequestExecutor.java deleted file mode 100644 index 66901d3b..00000000 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/MediaUploadRequestExecutor.java +++ /dev/null @@ -1,55 +0,0 @@ -package me.chanjar.weixin.common.util.http.apache; - -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import org.apache.http.HttpEntity; -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.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 Daniel Qian - */ -public class MediaUploadRequestExecutor implements RequestExecutor { - - @Override - public WxMediaUploadResult execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, File file) throws WxErrorException, IOException { - HttpPost httpPost = new HttpPost(uri); - if (httpProxy != null) { - RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); - httpPost.setConfig(config); - } - if (file != null) { - HttpEntity entity = MultipartEntityBuilder - .create() - .addBinaryBody("media", file) - .setMode(HttpMultipartMode.RFC6532) - .build(); - httpPost.setEntity(entity); - httpPost.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.toString()); - } - try (CloseableHttpResponse response = httpclient.execute(httpPost)) { - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } - return WxMediaUploadResult.fromJson(responseContent); - } finally { - httpPost.releaseConnection(); - } - } - -} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/SimpleGetRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/SimpleGetRequestExecutor.java deleted file mode 100644 index fce598f4..00000000 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/SimpleGetRequestExecutor.java +++ /dev/null @@ -1,47 +0,0 @@ -package me.chanjar.weixin.common.util.http.apache; - -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestExecutor; -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.impl.client.CloseableHttpClient; - -import java.io.IOException; - -/** - * 简单的GET请求执行器,请求的参数是String, 返回的结果也是String - * - * @author Daniel Qian - */ -public class SimpleGetRequestExecutor implements RequestExecutor { - - @Override - public String execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String queryParam) throws WxErrorException, IOException { - if (queryParam != null) { - if (uri.indexOf('?') == -1) { - uri += '?'; - } - uri += uri.endsWith("?") ? queryParam : '&' + queryParam; - } - HttpGet httpGet = new HttpGet(uri); - if (httpProxy != null) { - RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); - httpGet.setConfig(config); - } - - try (CloseableHttpResponse response = httpclient.execute(httpGet)) { - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } - return responseContent; - } finally { - httpGet.releaseConnection(); - } - } - -} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/SimplePostRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/SimplePostRequestExecutor.java deleted file mode 100644 index a63944bc..00000000 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/SimplePostRequestExecutor.java +++ /dev/null @@ -1,59 +0,0 @@ -package me.chanjar.weixin.common.util.http.apache; - -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import org.apache.http.Consts; -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.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; - -import java.io.IOException; - -/** - * 简单的POST请求执行器,请求的参数是String, 返回的结果也是String - * - * @author Daniel Qian - */ -public class SimplePostRequestExecutor implements RequestExecutor { - - @Override - public String execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String postEntity) throws WxErrorException, IOException { - HttpPost httpPost = new HttpPost(uri); - if (httpProxy != null) { - RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); - httpPost.setConfig(config); - } - - if (postEntity != null) { - StringEntity entity = new StringEntity(postEntity, Consts.UTF_8); - httpPost.setEntity(entity); - } - - try (CloseableHttpResponse response = httpclient.execute(httpPost)) { - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - if (responseContent.isEmpty()) { - throw new WxErrorException( - WxError.newBuilder().setErrorCode(9999).setErrorMsg("无响应内容") - .build()); - } - - if (responseContent.startsWith("")) { - //xml格式输出直接返回 - return responseContent; - } - - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } - return responseContent; - } finally { - httpPost.releaseConnection(); - } - } - -} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/MediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/MediaDownloadRequestExecutor.java deleted file mode 100644 index 9e4b092f..00000000 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/MediaDownloadRequestExecutor.java +++ /dev/null @@ -1,82 +0,0 @@ -package me.chanjar.weixin.common.util.http.jodd; - -import jodd.http.HttpConnectionProvider; -import jodd.http.HttpRequest; -import jodd.http.HttpResponse; -import jodd.http.ProxyInfo; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.fs.FileUtils; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import org.apache.commons.lang3.StringUtils; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * 下载媒体文件请求执行器,请求的参数是String, 返回的结果是File - * 视频文件不支持下载 - * - * @author Daniel Qian - */ -public class MediaDownloadRequestExecutor implements RequestExecutor { - - private File tmpDirFile; - - public MediaDownloadRequestExecutor() { - } - - public MediaDownloadRequestExecutor(File tmpDirFile) { - this.tmpDirFile = tmpDirFile; - } - - @Override - public File execute(HttpConnectionProvider provider, ProxyInfo httpProxy, String uri, String queryParam) throws WxErrorException, IOException { - if (queryParam != null) { - if (uri.indexOf('?') == -1) { - uri += '?'; - } - uri += uri.endsWith("?") ? queryParam : '&' + queryParam; - } - - HttpRequest request = HttpRequest.post(uri); - if (httpProxy != null) { - provider.useProxy(httpProxy); - } - request.withConnectionProvider(provider); - HttpResponse response = request.send(); - String contentType = response.header("Content-Type"); - if (contentType != null && contentType.startsWith("application/json")) { - // application/json; encoding=utf-8 下载媒体文件出错 - throw new WxErrorException(WxError.fromJson(response.bodyText())); - } - - String fileName = getFileName(response); - if (StringUtils.isBlank(fileName)) { - return null; - } - - InputStream inputStream = new ByteArrayInputStream(response.bodyBytes()); - String[] nameAndExt = fileName.split("\\."); - return FileUtils.createTmpFile(inputStream, nameAndExt[0], nameAndExt[1], this.tmpDirFile); - } - - private String getFileName(HttpResponse response) throws WxErrorException { - String content = response.header("Content-disposition"); - if (content == null || content.length() == 0) { - throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); - } - - Pattern p = Pattern.compile(".*filename=\"(.*)\""); - Matcher m = p.matcher(content); - if (m.matches()) { - return m.group(1); - } - throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); - } - -} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/MediaUploadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/MediaUploadRequestExecutor.java deleted file mode 100644 index 7d3b3eb9..00000000 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/MediaUploadRequestExecutor.java +++ /dev/null @@ -1,39 +0,0 @@ -package me.chanjar.weixin.common.util.http.jodd; - -import jodd.http.HttpConnectionProvider; -import jodd.http.HttpRequest; -import jodd.http.HttpResponse; -import jodd.http.ProxyInfo; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestExecutor; - -import java.io.File; -import java.io.IOException; - -/** - * 上传媒体文件请求执行器,请求的参数是File, 返回的结果是String - * - * @author Daniel Qian - */ -public class MediaUploadRequestExecutor implements RequestExecutor { - - @Override - public WxMediaUploadResult execute(HttpConnectionProvider provider, ProxyInfo httpProxy, String uri, File file) throws WxErrorException, IOException { - HttpRequest request = HttpRequest.post(uri); - if (httpProxy != null) { - provider.useProxy(httpProxy); - } - request.withConnectionProvider(provider); - request.form("media", file); - HttpResponse response = request.send(); - String responseContent =response.bodyText(); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } - return WxMediaUploadResult.fromJson(responseContent); - } - -} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimpleGetRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimpleGetRequestExecutor.java deleted file mode 100644 index 221e3b1e..00000000 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimpleGetRequestExecutor.java +++ /dev/null @@ -1,43 +0,0 @@ -package me.chanjar.weixin.common.util.http.jodd; - -import jodd.http.HttpConnectionProvider; -import jodd.http.HttpRequest; -import jodd.http.HttpResponse; -import jodd.http.ProxyInfo; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestExecutor; - -import java.io.IOException; - -/** - * 简单的GET请求执行器,请求的参数是String, 返回的结果也是String - * - * @author Daniel Qian - */ -public class SimpleGetRequestExecutor implements RequestExecutor { - - @Override - public String execute(HttpConnectionProvider provider, ProxyInfo httpProxy, String uri, String queryParam) throws WxErrorException, IOException { - if (queryParam != null) { - if (uri.indexOf('?') == -1) { - uri += '?'; - } - uri += uri.endsWith("?") ? queryParam : '&' + queryParam; - } - - HttpRequest request = HttpRequest.get(uri); - if (httpProxy != null) { - provider.useProxy(httpProxy); - } - request.withConnectionProvider(provider); - HttpResponse response = request.send(); - String responseContent = response.bodyText(); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } - return responseContent; - } - -} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimplePostRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimplePostRequestExecutor.java deleted file mode 100644 index 057abf8e..00000000 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/SimplePostRequestExecutor.java +++ /dev/null @@ -1,51 +0,0 @@ -package me.chanjar.weixin.common.util.http.jodd; - -import jodd.http.HttpConnectionProvider; -import jodd.http.HttpRequest; -import jodd.http.HttpResponse; -import jodd.http.ProxyInfo; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestExecutor; - -import java.io.IOException; - -/** - * 简单的POST请求执行器,请求的参数是String, 返回的结果也是String - * - * @author Daniel Qian - */ -public class SimplePostRequestExecutor implements RequestExecutor { - - @Override - public String execute(HttpConnectionProvider provider, ProxyInfo httpProxy, String uri, String postEntity) throws WxErrorException, IOException { - HttpRequest request = HttpRequest.post(uri); - if (httpProxy != null) { - provider.useProxy(httpProxy); - } - request.withConnectionProvider(provider); - if (postEntity != null) { - request.bodyText(postEntity); - } - HttpResponse response = request.send(); - - String responseContent = response.bodyText(); - if (responseContent.isEmpty()) { - throw new WxErrorException( - WxError.newBuilder().setErrorCode(9999).setErrorMsg("无响应内容") - .build()); - } - - if (responseContent.startsWith("")) { - //xml格式输出直接返回 - return responseContent; - } - - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } - return responseContent; - } - -} From 9ac1aad0e4c439ad798252bd0e3e44500764fcca Mon Sep 17 00:00:00 2001 From: ecoolper Date: Sat, 22 Apr 2017 15:06:12 +0800 Subject: [PATCH 09/27] =?UTF-8?q?=E8=A3=85=E9=A5=B0=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../http/MediaDownloadRequestExecutor.java | 12 +- .../util/http/MediaUploadRequestExecutor.java | 12 +- .../weixin/common/util/http/RequestHttp.java | 4 +- .../util/http/SimpleGetRequestExecutor.java | 12 +- .../util/http/SimplePostRequestExecutor.java | 12 +- .../me/chanjar/weixin/cp/api/WxCpService.java | 9 +- .../cp/api/impl/apache/WxCpServiceImpl.java | 23 +- .../cp/api/impl/apache/WxCpBusyRetryTest.java | 4 +- .../weixin/mp/api/WxMpCardService.java | 2 +- .../me/chanjar/weixin/mp/api/WxMpService.java | 31 +-- .../{apache => }/WxMpCardServiceImpl.java | 8 +- .../impl/{jodd => }/WxMpKefuServiceImpl.java | 8 +- .../{jodd => }/WxMpMaterialServiceImpl.java | 12 +- .../{jodd => }/WxMpQrcodeServiceImpl.java | 8 +- .../WxMpUserBlacklistServiceImpl.java | 8 +- .../api/impl/apache/WxMpKefuServiceImpl.java | 183 ------------- .../impl/apache/WxMpMaterialServiceImpl.java | 168 ------------ .../impl/apache/WxMpQrcodeServiceImpl.java | 120 --------- .../mp/api/impl/apache/WxMpServiceImpl.java | 40 +-- .../apache/WxMpUserBlacklistServiceImpl.java | 52 ---- .../mp/api/impl/jodd/WxMpCardServiceImpl.java | 251 ------------------ .../mp/api/impl/jodd/WxMpServiceImpl.java | 40 +-- .../http/MaterialDeleteRequestExecutor.java | 93 +++++++ .../http/MaterialNewsInfoRequestExecutor.java | 93 +++++++ .../http/MaterialUploadRequestExecutor.java | 121 +++++++++ .../MaterialVideoInfoRequestExecutor.java | 92 +++++++ ...lVoiceAndImageDownloadRequestExecutor.java | 117 ++++++++ .../http/MediaImgUploadRequestExecutor.java | 103 +++++++ .../mp/util/http/QrCodeRequestExecutor.java | 116 ++++++++ .../apache/MaterialDeleteRequestExecutor.java | 50 ---- .../MaterialNewsInfoRequestExecutor.java | 52 ---- .../apache/MaterialUploadRequestExecutor.java | 68 ----- .../MaterialVideoInfoRequestExecutor.java | 50 ---- ...lVoiceAndImageDownloadRequestExecutor.java | 66 ----- .../apache/MediaImgUploadRequestExecutor.java | 55 ---- .../http/apache/QrCodeRequestExecutor.java | 66 ----- .../jodd/MaterialDeleteRequestExecutor.java | 39 --- .../jodd/MaterialNewsInfoRequestExecutor.java | 41 --- .../jodd/MaterialUploadRequestExecutor.java | 53 ---- .../MaterialVideoInfoRequestExecutor.java | 39 --- ...lVoiceAndImageDownloadRequestExecutor.java | 57 ---- .../jodd/MediaImgUploadRequestExecutor.java | 42 --- .../util/http/jodd/QrCodeRequestExecutor.java | 60 ----- .../weixin/mp/api/WxMpBusyRetryTest.java | 4 +- 44 files changed, 860 insertions(+), 1636 deletions(-) rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/{apache => }/WxMpCardServiceImpl.java (97%) rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/{jodd => }/WxMpKefuServiceImpl.java (96%) rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/{jodd => }/WxMpMaterialServiceImpl.java (94%) rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/{jodd => }/WxMpQrcodeServiceImpl.java (94%) rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/{jodd => }/WxMpUserBlacklistServiceImpl.java (87%) delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpKefuServiceImpl.java delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpMaterialServiceImpl.java delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpQrcodeServiceImpl.java delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpUserBlacklistServiceImpl.java delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpCardServiceImpl.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialDeleteRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialNewsInfoRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialUploadRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVideoInfoRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVoiceAndImageDownloadRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MediaImgUploadRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/QrCodeRequestExecutor.java delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialDeleteRequestExecutor.java delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialNewsInfoRequestExecutor.java delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialUploadRequestExecutor.java delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialVideoInfoRequestExecutor.java delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialVoiceAndImageDownloadRequestExecutor.java delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MediaImgUploadRequestExecutor.java delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/QrCodeRequestExecutor.java delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialDeleteRequestExecutor.java delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialNewsInfoRequestExecutor.java delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialUploadRequestExecutor.java delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialVideoInfoRequestExecutor.java delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialVoiceAndImageDownloadRequestExecutor.java delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MediaImgUploadRequestExecutor.java delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/QrCodeRequestExecutor.java diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java index cfe382e1..a61c54a7 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java @@ -41,14 +41,14 @@ public class MediaDownloadRequestExecutor implements RequestExecutor @Override public String execute(RequestHttp requestHttp, String uri, String queryParam) throws WxErrorException, IOException { - if (requestHttp.getHttpClient() instanceof CloseableHttpClient) { - CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getHttpClient(); - HttpHost httpProxy = (HttpHost) requestHttp.getHttpProxy(); + if (requestHttp.getRequestHttpClient() instanceof CloseableHttpClient) { + CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getRequestHttpClient(); + HttpHost httpProxy = (HttpHost) requestHttp.getRequestHttpProxy(); return executeApache(httpClient, httpProxy, uri, queryParam); } - if (requestHttp.getHttpClient() instanceof HttpConnectionProvider) { - HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getHttpClient(); - ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getHttpProxy(); + if (requestHttp.getRequestHttpClient() instanceof HttpConnectionProvider) { + HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getRequestHttpClient(); + ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getRequestHttpProxy(); return executeJodd(provider, proxyInfo, uri, queryParam); } else { //这里需要抛出异常,需要优化 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 39cb90d6..f35385de 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 @@ -27,14 +27,14 @@ public class SimplePostRequestExecutor implements RequestExecutor { +public interface WxCpService { /** *
@@ -469,7 +470,7 @@ public interface WxCpService {
    * 
    * Service没有实现某个API的时候,可以用这个,
    * 比{@link #get}和{@link #post}方法更灵活,可以自己构造RequestExecutor用来处理不同的参数和不同的返回类型。
-   * 可以参考,{@link me.chanjar.weixin.common.util.http.jodd.MediaUploadRequestExecutor}的实现方法
+   * 可以参考,{@link MediaUploadRequestExecutor}的实现方法
    * 
* * @param executor 执行器 @@ -478,9 +479,7 @@ public interface WxCpService { * @param 请求值类型 * @param 返回值类型 */ - T execute(RequestExecutor executor, String uri, E data) throws WxErrorException; - - T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException; + T execute(RequestExecutor executor, String uri, E data) throws WxErrorException; /** * 注入 {@link WxCpConfigStorage} 的实现 diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java index 522c449f..4369868f 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java @@ -14,9 +14,9 @@ import me.chanjar.weixin.common.session.WxSessionManager; import me.chanjar.weixin.common.util.RandomUtils; import me.chanjar.weixin.common.util.crypto.SHA1; import me.chanjar.weixin.common.util.fs.FileUtils; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.http.URIUtil; -import me.chanjar.weixin.common.util.http.apache.*; +import me.chanjar.weixin.common.util.http.*; +import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; import me.chanjar.weixin.common.util.json.GsonHelper; import me.chanjar.weixin.cp.api.WxCpConfigStorage; import me.chanjar.weixin.cp.api.WxCpService; @@ -41,7 +41,7 @@ import java.io.InputStream; import java.util.List; import java.util.UUID; -public class WxCpServiceImpl implements WxCpService { +public class WxCpServiceImpl implements WxCpService, RequestHttp { protected final Logger log = LoggerFactory.getLogger(WxCpServiceImpl.class); @@ -538,7 +538,7 @@ public class WxCpServiceImpl implements WxCpService T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { + public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { int retryTimes = 0; do { try { @@ -574,7 +574,7 @@ public class WxCpServiceImpl implements WxCpService T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { + public synchronized T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { if (uri.contains("access_token=")) { throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); } @@ -584,7 +584,7 @@ public class WxCpServiceImpl implements WxCpService { * 得到WxMpService * @return */ - WxMpService getWxMpService(); + WxMpService getWxMpService(); /** * 获得卡券api_ticket,不强制刷新卡券api_ticket diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java index edaa72c1..0b968594 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java @@ -2,15 +2,15 @@ package me.chanjar.weixin.mp.api; import me.chanjar.weixin.common.bean.WxJsapiSignature; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.http.apache.MediaUploadRequestExecutor; import me.chanjar.weixin.mp.bean.*; import me.chanjar.weixin.mp.bean.result.*; /** * 微信API的Service */ -public interface WxMpService { +public interface WxMpService { /** *
@@ -133,7 +133,6 @@ public interface WxMpService {
    * 长链接转短链接接口
    * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=长链接转短链接接口
    * 
- * */ String shortUrl(String long_url) throws WxErrorException; @@ -153,8 +152,8 @@ public interface WxMpService { *
* * @param redirectURI 用户授权完成后的重定向链接,无需urlencode, 方法内会进行encode - * @param scope 应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即可 - * @param state 非必填,用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验 + * @param scope 应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即可 + * @param state 非必填,用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验 * @return url */ String buildQrConnectUrl(String redirectURI, String scope, String state); @@ -190,7 +189,7 @@ public interface WxMpService { * 用oauth2获取用户信息, 当前面引导授权时的scope是snsapi_userinfo的时候才可以 *
* - * @param lang zh_CN, zh_TW, en + * @param lang zh_CN, zh_TW, en */ WxMpUser oauth2getUserInfo(WxMpOAuth2AccessToken oAuth2AccessToken, String lang) throws WxErrorException; @@ -198,7 +197,6 @@ public interface WxMpService { *
    * 验证oauth2的access token是否有效
    * 
- * */ boolean oauth2validateAccessToken(WxMpOAuth2AccessToken oAuth2AccessToken); @@ -227,15 +225,12 @@ public interface WxMpService { * 可以参考,{@link MediaUploadRequestExecutor}的实现方法 *
*/ - T execute(RequestExecutor executor, String uri, E data) throws WxErrorException; - - T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException; - + T execute(RequestExecutor executor, String uri, E data) throws WxErrorException; - /** - * 获取代理对象 - */ - //HttpHost getHttpProxy(); + /** + * 获取代理对象 + */ + //HttpHost getRequestHttpProxy(); /** * 注入 {@link WxMpConfigStorage} 的实现 @@ -350,15 +345,13 @@ public interface WxMpService { WxMpDeviceService getDeviceService(); /** - * * @return */ - H getHttpclient(); + //Object getHttpclient(); /** - * * @return */ - P getHttpProxy(); + //Object getHttpProxy(); } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpCardServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpCardServiceImpl.java similarity index 97% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpCardServiceImpl.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpCardServiceImpl.java index e9d9c789..9e64d043 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpCardServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpCardServiceImpl.java @@ -1,4 +1,4 @@ -package me.chanjar.weixin.mp.api.impl.apache; +package me.chanjar.weixin.mp.api.impl; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -10,7 +10,7 @@ import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.RandomUtils; import me.chanjar.weixin.common.util.crypto.SHA1; -import me.chanjar.weixin.common.util.http.apache.SimpleGetRequestExecutor; +import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; import me.chanjar.weixin.mp.api.WxMpCardService; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.bean.result.WxMpCardResult; @@ -30,7 +30,7 @@ public class WxMpCardServiceImpl implements WxMpCardService wxMpService; + private WxMpService wxMpService; public WxMpCardServiceImpl(WxMpService wxMpService) { this.wxMpService = wxMpService; @@ -41,7 +41,7 @@ public class WxMpCardServiceImpl implements WxMpCardService getWxMpService(){ + public WxMpService getWxMpService(){ return this.wxMpService; } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpKefuServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java similarity index 96% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpKefuServiceImpl.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java index 9e7685b5..4667f327 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpKefuServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java @@ -1,12 +1,10 @@ -package me.chanjar.weixin.mp.api.impl.jodd; +package me.chanjar.weixin.mp.api.impl; import com.google.gson.JsonObject; -import jodd.http.HttpConnectionProvider; -import jodd.http.ProxyInfo; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.jodd.MediaUploadRequestExecutor; +import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; import me.chanjar.weixin.mp.api.WxMpKefuService; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage; @@ -29,7 +27,7 @@ public class WxMpKefuServiceImpl implements WxMpKefuService { .getLogger(WxMpKefuServiceImpl.class); private static final String API_URL_PREFIX = "https://api.weixin.qq.com/customservice"; private static final String API_URL_PREFIX_WITH_CGI_BIN = "https://api.weixin.qq.com/cgi-bin/customservice"; - private WxMpService wxMpService; + private WxMpService wxMpService; public WxMpKefuServiceImpl(WxMpService wxMpService) { this.wxMpService = wxMpService; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpMaterialServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java similarity index 94% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpMaterialServiceImpl.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java index f6c48f9a..4242063b 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpMaterialServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java @@ -1,19 +1,17 @@ -package me.chanjar.weixin.mp.api.impl.jodd; +package me.chanjar.weixin.mp.api.impl; -import jodd.http.HttpConnectionProvider; -import jodd.http.ProxyInfo; import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.fs.FileUtils; -import me.chanjar.weixin.common.util.http.jodd.MediaDownloadRequestExecutor; -import me.chanjar.weixin.common.util.http.jodd.MediaUploadRequestExecutor; +import me.chanjar.weixin.common.util.http.MediaDownloadRequestExecutor; +import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; import me.chanjar.weixin.common.util.json.WxGsonBuilder; import me.chanjar.weixin.mp.api.WxMpMaterialService; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.bean.material.*; -import me.chanjar.weixin.mp.util.http.jodd.*; +import me.chanjar.weixin.mp.util.http.*; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; import java.io.File; @@ -29,7 +27,7 @@ import java.util.UUID; public class WxMpMaterialServiceImpl implements WxMpMaterialService { private static final String MEDIA_API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/media"; private static final String MATERIAL_API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/material"; - private WxMpService wxMpService; + private WxMpService wxMpService; public WxMpMaterialServiceImpl(WxMpService wxMpService) { this.wxMpService = wxMpService; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpQrcodeServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpQrcodeServiceImpl.java similarity index 94% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpQrcodeServiceImpl.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpQrcodeServiceImpl.java index fba822b3..8659f2af 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpQrcodeServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpQrcodeServiceImpl.java @@ -1,14 +1,12 @@ -package me.chanjar.weixin.mp.api.impl.jodd; +package me.chanjar.weixin.mp.api.impl; import com.google.gson.JsonObject; -import jodd.http.HttpConnectionProvider; -import jodd.http.ProxyInfo; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.mp.api.WxMpQrcodeService; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; -import me.chanjar.weixin.mp.util.http.jodd.QrCodeRequestExecutor; +import me.chanjar.weixin.mp.util.http.QrCodeRequestExecutor; import java.io.File; import java.io.UnsupportedEncodingException; @@ -20,7 +18,7 @@ import java.nio.charset.StandardCharsets; */ public class WxMpQrcodeServiceImpl implements WxMpQrcodeService { private static final String API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/qrcode"; - private WxMpService wxMpService; + private WxMpService wxMpService; public WxMpQrcodeServiceImpl(WxMpService wxMpService) { this.wxMpService = wxMpService; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpUserBlacklistServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpUserBlacklistServiceImpl.java similarity index 87% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpUserBlacklistServiceImpl.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpUserBlacklistServiceImpl.java index f310b3d4..b0b35343 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpUserBlacklistServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpUserBlacklistServiceImpl.java @@ -1,11 +1,9 @@ -package me.chanjar.weixin.mp.api.impl.jodd; +package me.chanjar.weixin.mp.api.impl; import com.google.gson.Gson; import com.google.gson.JsonObject; -import jodd.http.HttpConnectionProvider; -import jodd.http.ProxyInfo; import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.jodd.SimplePostRequestExecutor; +import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpUserBlacklistService; import me.chanjar.weixin.mp.bean.result.WxMpUserBlacklistGetResult; @@ -19,7 +17,7 @@ import java.util.Map; */ public class WxMpUserBlacklistServiceImpl implements WxMpUserBlacklistService { private static final String API_BLACKLIST_PREFIX = "https://api.weixin.qq.com/cgi-bin/tags/members"; - private WxMpService wxMpService; + private WxMpService wxMpService; public WxMpUserBlacklistServiceImpl(WxMpService wxMpService) { this.wxMpService = wxMpService; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpKefuServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpKefuServiceImpl.java deleted file mode 100644 index 0dc921f1..00000000 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpKefuServiceImpl.java +++ /dev/null @@ -1,183 +0,0 @@ -package me.chanjar.weixin.mp.api.impl.apache; - -import com.google.gson.JsonObject; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.apache.MediaUploadRequestExecutor; -import me.chanjar.weixin.mp.api.WxMpKefuService; -import me.chanjar.weixin.mp.api.WxMpService; -import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage; -import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; -import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfSessionRequest; -import me.chanjar.weixin.mp.bean.kefu.result.*; -import org.apache.http.HttpHost; -import org.apache.http.impl.client.CloseableHttpClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.util.Date; - -/** - * - * @author Binary Wang - * - */ -public class WxMpKefuServiceImpl implements WxMpKefuService { - protected final Logger log = LoggerFactory - .getLogger(WxMpKefuServiceImpl.class); - private static final String API_URL_PREFIX = "https://api.weixin.qq.com/customservice"; - private static final String API_URL_PREFIX_WITH_CGI_BIN = "https://api.weixin.qq.com/cgi-bin/customservice"; - private WxMpService wxMpService; - - public WxMpKefuServiceImpl(WxMpService wxMpService) { - this.wxMpService = wxMpService; - } - - @Override - public boolean sendKefuMessage(WxMpKefuMessage message) - throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send"; - String responseContent = this.wxMpService.post(url, message.toJson()); - return responseContent != null; - } - - @Override - public WxMpKfList kfList() throws WxErrorException { - String url = API_URL_PREFIX_WITH_CGI_BIN + "/getkflist"; - String responseContent = this.wxMpService.get(url, null); - return WxMpKfList.fromJson(responseContent); - } - - @Override - public WxMpKfOnlineList kfOnlineList() throws WxErrorException { - String url = API_URL_PREFIX_WITH_CGI_BIN + "/getonlinekflist"; - String responseContent = this.wxMpService.get(url, null); - return WxMpKfOnlineList.fromJson(responseContent); - } - - @Override - public boolean kfAccountAdd(WxMpKfAccountRequest request) - throws WxErrorException { - String url = API_URL_PREFIX + "/kfaccount/add"; - String responseContent = this.wxMpService.post(url, request.toJson()); - return responseContent != null; - } - - @Override - public boolean kfAccountUpdate(WxMpKfAccountRequest request) - throws WxErrorException { - String url = API_URL_PREFIX + "/kfaccount/update"; - String responseContent = this.wxMpService.post(url, request.toJson()); - return responseContent != null; - } - - @Override - public boolean kfAccountInviteWorker(WxMpKfAccountRequest request) throws WxErrorException { - String url = API_URL_PREFIX + "/kfaccount/inviteworker"; - String responseContent = this.wxMpService.post(url, request.toJson()); - return responseContent != null; - } - - @Override - public boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) - throws WxErrorException { - String url = API_URL_PREFIX + "/kfaccount/uploadheadimg?kf_account=" + kfAccount; - WxMediaUploadResult responseContent = this.wxMpService - .execute(new MediaUploadRequestExecutor(), url, imgFile); - return responseContent != null; - } - - @Override - public boolean kfAccountDel(String kfAccount) throws WxErrorException { - String url = API_URL_PREFIX + "/kfaccount/del?kf_account=" + kfAccount; - String responseContent = this.wxMpService.get(url, null); - return responseContent != null; - } - - @Override - public boolean kfSessionCreate(String openid, String kfAccount) - throws WxErrorException { - WxMpKfSessionRequest request = new WxMpKfSessionRequest(kfAccount, openid); - String url = API_URL_PREFIX + "/kfsession/create"; - String responseContent = this.wxMpService.post(url, request.toJson()); - return responseContent != null; - } - - @Override - public boolean kfSessionClose(String openid, String kfAccount) - throws WxErrorException { - WxMpKfSessionRequest request = new WxMpKfSessionRequest(kfAccount, openid); - String url = API_URL_PREFIX + "/kfsession/close"; - String responseContent = this.wxMpService.post(url, request.toJson()); - return responseContent != null; - } - - @Override - public WxMpKfSessionGetResult kfSessionGet(String openid) - throws WxErrorException { - String url = API_URL_PREFIX + "/kfsession/getsession?openid=" + openid; - String responseContent = this.wxMpService.get(url, null); - return WxMpKfSessionGetResult.fromJson(responseContent); - } - - @Override - public WxMpKfSessionList kfSessionList(String kfAccount) - throws WxErrorException { - String url = API_URL_PREFIX + "/kfsession/getsessionlist?kf_account=" + kfAccount; - String responseContent = this.wxMpService.get(url, null); - return WxMpKfSessionList.fromJson(responseContent); - } - - @Override - public WxMpKfSessionWaitCaseList kfSessionGetWaitCase() - throws WxErrorException { - String url = API_URL_PREFIX + "/kfsession/getwaitcase"; - String responseContent = this.wxMpService.get(url, null); - return WxMpKfSessionWaitCaseList.fromJson(responseContent); - } - - @Override - public WxMpKfMsgList kfMsgList(Date startTime, Date endTime, Long msgId, Integer number) throws WxErrorException { - if(number > 10000){ - throw new WxErrorException(WxError.newBuilder().setErrorMsg("非法参数请求,每次最多查询10000条记录!").build()); - } - - if(startTime.after(endTime)){ - throw new WxErrorException(WxError.newBuilder().setErrorMsg("起始时间不能晚于结束时间!").build()); - } - - String url = API_URL_PREFIX + "/msgrecord/getmsglist"; - - JsonObject param = new JsonObject(); - param.addProperty("starttime", startTime.getTime() / 1000); //starttime 起始时间,unix时间戳 - param.addProperty("endtime", endTime.getTime() / 1000); //endtime 结束时间,unix时间戳,每次查询时段不能超过24小时 - param.addProperty("msgid", msgId); //msgid 消息id顺序从小到大,从1开始 - param.addProperty("number", number); //number 每次获取条数,最多10000条 - - String responseContent = this.wxMpService.post(url, param.toString()); - - return WxMpKfMsgList.fromJson(responseContent); - } - - @Override - public WxMpKfMsgList kfMsgList(Date startTime, Date endTime) throws WxErrorException { - int number = 10000; - WxMpKfMsgList result = this.kfMsgList(startTime,endTime, 1L, number); - - if(result != null && result.getNumber() == number){ - Long msgId = result.getMsgId(); - WxMpKfMsgList followingResult = this.kfMsgList(startTime,endTime, msgId, number); - while(followingResult != null && followingResult.getRecords().size() > 0){ - result.getRecords().addAll(followingResult.getRecords()); - result.setNumber(result.getNumber() + followingResult.getNumber()); - result.setMsgId(followingResult.getMsgId()); - followingResult = this.kfMsgList(startTime,endTime, followingResult.getMsgId(), number); - } - } - - return result; - } - -} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpMaterialServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpMaterialServiceImpl.java deleted file mode 100644 index 13d5a754..00000000 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpMaterialServiceImpl.java +++ /dev/null @@ -1,168 +0,0 @@ -package me.chanjar.weixin.mp.api.impl.apache; - -import me.chanjar.weixin.common.api.WxConsts; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.fs.FileUtils; -import me.chanjar.weixin.common.util.http.apache.MediaDownloadRequestExecutor; -import me.chanjar.weixin.common.util.http.apache.MediaUploadRequestExecutor; -import me.chanjar.weixin.common.util.json.WxGsonBuilder; -import me.chanjar.weixin.mp.api.WxMpMaterialService; -import me.chanjar.weixin.mp.api.WxMpService; -import me.chanjar.weixin.mp.bean.material.WxMpMaterial; -import me.chanjar.weixin.mp.bean.material.WxMpMaterialArticleUpdate; -import me.chanjar.weixin.mp.bean.material.WxMpMaterialNews; -import me.chanjar.weixin.mp.bean.material.*; -import me.chanjar.weixin.mp.util.http.apache.*; -import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; -import org.apache.http.HttpHost; -import org.apache.http.impl.client.CloseableHttpClient; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -/** - * Created by Binary Wang on 2016/7/21. - */ -public class WxMpMaterialServiceImpl implements WxMpMaterialService { - private static final String MEDIA_API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/media"; - private static final String MATERIAL_API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/material"; - private WxMpService wxMpService; - - public WxMpMaterialServiceImpl(WxMpService wxMpService) { - this.wxMpService = wxMpService; - } - - @Override - public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) throws WxErrorException { - try { - return this.mediaUpload(mediaType, FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType)); - } catch (IOException e) { - e.printStackTrace(); - throw new WxErrorException(WxError.newBuilder().setErrorMsg(e.getMessage()).build()); - } - } - - @Override - public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException { - String url = MEDIA_API_URL_PREFIX + "/upload?type=" + mediaType; - return this.wxMpService.execute(new MediaUploadRequestExecutor(), url, file); - } - - @Override - public File mediaDownload(String media_id) throws WxErrorException { - String url = MEDIA_API_URL_PREFIX + "/get"; - return this.wxMpService.execute( - new MediaDownloadRequestExecutor(this.wxMpService.getWxMpConfigStorage().getTmpDirFile()), - url, - "media_id=" + media_id); - } - - @Override - public WxMediaImgUploadResult mediaImgUpload(File file) throws WxErrorException { - String url = MEDIA_API_URL_PREFIX + "/uploadimg"; - return this.wxMpService.execute(new MediaImgUploadRequestExecutor(), url, file); - } - - @Override - public WxMpMaterialUploadResult materialFileUpload(String mediaType, WxMpMaterial material) throws WxErrorException { - String url = MATERIAL_API_URL_PREFIX + "/add_material?type=" + mediaType; - return this.wxMpService.execute(new MaterialUploadRequestExecutor(), url, material); - } - - @Override - public WxMpMaterialUploadResult materialNewsUpload(WxMpMaterialNews news) throws WxErrorException { - if (news == null || news.isEmpty()) { - throw new IllegalArgumentException("news is empty!"); - } - String url = MATERIAL_API_URL_PREFIX + "/add_news"; - String responseContent = this.wxMpService.post(url, news.toJson()); - return WxMpMaterialUploadResult.fromJson(responseContent); - } - - @Override - public InputStream materialImageOrVoiceDownload(String media_id) throws WxErrorException { - String url = MATERIAL_API_URL_PREFIX + "/get_material"; - return this.wxMpService.execute(new MaterialVoiceAndImageDownloadRequestExecutor(this.wxMpService.getWxMpConfigStorage().getTmpDirFile()), url, media_id); - } - - @Override - public WxMpMaterialVideoInfoResult materialVideoInfo(String media_id) throws WxErrorException { - String url = MATERIAL_API_URL_PREFIX + "/get_material"; - return this.wxMpService.execute(new MaterialVideoInfoRequestExecutor(), url, media_id); - } - - @Override - public WxMpMaterialNews materialNewsInfo(String media_id) throws WxErrorException { - String url = MATERIAL_API_URL_PREFIX + "/get_material"; - return this.wxMpService.execute(new MaterialNewsInfoRequestExecutor(), url, media_id); - } - - @Override - public boolean materialNewsUpdate(WxMpMaterialArticleUpdate wxMpMaterialArticleUpdate) throws WxErrorException { - String url = MATERIAL_API_URL_PREFIX + "/update_news"; - String responseText = this.wxMpService.post(url, wxMpMaterialArticleUpdate.toJson()); - WxError wxError = WxError.fromJson(responseText); - if (wxError.getErrorCode() == 0) { - return true; - } else { - throw new WxErrorException(wxError); - } - } - - @Override - public boolean materialDelete(String media_id) throws WxErrorException { - String url = MATERIAL_API_URL_PREFIX + "/del_material"; - return this.wxMpService.execute(new MaterialDeleteRequestExecutor(), url, media_id); - } - - @Override - public WxMpMaterialCountResult materialCount() throws WxErrorException { - String url = MATERIAL_API_URL_PREFIX + "/get_materialcount"; - String responseText = this.wxMpService.get(url, null); - WxError wxError = WxError.fromJson(responseText); - if (wxError.getErrorCode() == 0) { - return WxMpGsonBuilder.create().fromJson(responseText, WxMpMaterialCountResult.class); - } else { - throw new WxErrorException(wxError); - } - } - - @Override - public WxMpMaterialNewsBatchGetResult materialNewsBatchGet(int offset, int count) throws WxErrorException { - String url = MATERIAL_API_URL_PREFIX + "/batchget_material"; - Map params = new HashMap<>(); - params.put("type", WxConsts.MATERIAL_NEWS); - params.put("offset", offset); - params.put("count", count); - String responseText = this.wxMpService.post(url, WxGsonBuilder.create().toJson(params)); - WxError wxError = WxError.fromJson(responseText); - if (wxError.getErrorCode() == 0) { - return WxMpGsonBuilder.create().fromJson(responseText, WxMpMaterialNewsBatchGetResult.class); - } else { - throw new WxErrorException(wxError); - } - } - - @Override - public WxMpMaterialFileBatchGetResult materialFileBatchGet(String type, int offset, int count) throws WxErrorException { - String url = MATERIAL_API_URL_PREFIX + "/batchget_material"; - Map params = new HashMap<>(); - params.put("type", type); - params.put("offset", offset); - params.put("count", count); - String responseText = this.wxMpService.post(url, WxGsonBuilder.create().toJson(params)); - WxError wxError = WxError.fromJson(responseText); - if (wxError.getErrorCode() == 0) { - return WxMpGsonBuilder.create().fromJson(responseText, WxMpMaterialFileBatchGetResult.class); - } else { - throw new WxErrorException(wxError); - } - } - -} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpQrcodeServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpQrcodeServiceImpl.java deleted file mode 100644 index 5db81fe1..00000000 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpQrcodeServiceImpl.java +++ /dev/null @@ -1,120 +0,0 @@ -package me.chanjar.weixin.mp.api.impl.apache; - -import com.google.gson.JsonObject; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.mp.api.WxMpQrcodeService; -import me.chanjar.weixin.mp.api.WxMpService; -import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; -import me.chanjar.weixin.mp.util.http.apache.QrCodeRequestExecutor; -import org.apache.http.HttpHost; -import org.apache.http.impl.client.CloseableHttpClient; - -import java.io.File; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; - -/** - * Created by Binary Wang on 2016/7/21. - */ -public class WxMpQrcodeServiceImpl implements WxMpQrcodeService { - private static final String API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/qrcode"; - private WxMpService wxMpService; - - public WxMpQrcodeServiceImpl(WxMpService wxMpService) { - this.wxMpService = wxMpService; - } - - @Override - public WxMpQrCodeTicket qrCodeCreateTmpTicket(int sceneId, Integer expireSeconds) throws WxErrorException { - if (sceneId == 0) { - throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("临时二维码场景值不能为0!").build()); - } - - //expireSeconds 该二维码有效时间,以秒为单位。 最大不超过2592000(即30天),此字段如果不填,则默认有效期为30秒。 - if (expireSeconds != null && expireSeconds > 2592000) { - throw new WxErrorException(WxError.newBuilder().setErrorCode(-1) - .setErrorMsg("临时二维码有效时间最大不能超过2592000(即30天)!").build()); - } - - if (expireSeconds == null) { - expireSeconds = 30; - } - - String url = API_URL_PREFIX + "/create"; - JsonObject json = new JsonObject(); - json.addProperty("action_name", "QR_SCENE"); - json.addProperty("expire_seconds", expireSeconds); - - JsonObject actionInfo = new JsonObject(); - JsonObject scene = new JsonObject(); - scene.addProperty("scene_id", sceneId); - actionInfo.add("scene", scene); - json.add("action_info", actionInfo); - String responseContent = this.wxMpService.post(url, json.toString()); - return WxMpQrCodeTicket.fromJson(responseContent); - } - - @Override - public WxMpQrCodeTicket qrCodeCreateLastTicket(int sceneId) throws WxErrorException { - if (sceneId < 1 || sceneId > 100000) { - throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("永久二维码的场景值目前只支持1--100000!").build()); - } - - String url = API_URL_PREFIX + "/create"; - JsonObject json = new JsonObject(); - json.addProperty("action_name", "QR_LIMIT_SCENE"); - JsonObject actionInfo = new JsonObject(); - JsonObject scene = new JsonObject(); - scene.addProperty("scene_id", sceneId); - actionInfo.add("scene", scene); - json.add("action_info", actionInfo); - String responseContent = this.wxMpService.post(url, json.toString()); - return WxMpQrCodeTicket.fromJson(responseContent); - } - - @Override - public WxMpQrCodeTicket qrCodeCreateLastTicket(String sceneStr) throws WxErrorException { - String url = API_URL_PREFIX + "/create"; - JsonObject json = new JsonObject(); - json.addProperty("action_name", "QR_LIMIT_STR_SCENE"); - JsonObject actionInfo = new JsonObject(); - JsonObject scene = new JsonObject(); - scene.addProperty("scene_str", sceneStr); - actionInfo.add("scene", scene); - json.add("action_info", actionInfo); - String responseContent = this.wxMpService.post(url, json.toString()); - return WxMpQrCodeTicket.fromJson(responseContent); - } - - @Override - public File qrCodePicture(WxMpQrCodeTicket ticket) throws WxErrorException { - String url = "https://mp.weixin.qq.com/cgi-bin/showqrcode"; - return this.wxMpService.execute(new QrCodeRequestExecutor(), url, ticket); - } - - @Override - public String qrCodePictureUrl(String ticket, boolean needShortUrl) throws WxErrorException { - String url = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=%s"; - try { - String resultUrl = String.format(url, - URLEncoder.encode(ticket, StandardCharsets.UTF_8.name())); - if (needShortUrl) { - return this.wxMpService.shortUrl(resultUrl); - } - - return resultUrl; - } catch (UnsupportedEncodingException e) { - WxError error = WxError.newBuilder().setErrorCode(-1) - .setErrorMsg(e.getMessage()).build(); - throw new WxErrorException(error); - } - } - - @Override - public String qrCodePictureUrl(String ticket) throws WxErrorException { - return qrCodePictureUrl(ticket, false); - } - -} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpServiceImpl.java index 75a6bd96..5e6f863a 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpServiceImpl.java @@ -12,12 +12,9 @@ import me.chanjar.weixin.common.session.StandardSessionManager; import me.chanjar.weixin.common.session.WxSessionManager; import me.chanjar.weixin.common.util.RandomUtils; import me.chanjar.weixin.common.util.crypto.SHA1; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.http.URIUtil; +import me.chanjar.weixin.common.util.http.*; import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; -import me.chanjar.weixin.common.util.http.apache.SimpleGetRequestExecutor; -import me.chanjar.weixin.common.util.http.apache.SimplePostRequestExecutor; import me.chanjar.weixin.mp.api.*; import me.chanjar.weixin.mp.api.impl.*; import me.chanjar.weixin.mp.bean.*; @@ -34,7 +31,7 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.concurrent.locks.Lock; -public class WxMpServiceImpl implements WxMpService { +public class WxMpServiceImpl implements WxMpService,RequestHttp { private static final JsonParser JSON_PARSER = new JsonParser(); @@ -248,8 +245,8 @@ public class WxMpServiceImpl implements WxMpService executor = new SimpleGetRequestExecutor(); - String responseText = executor.execute(this.getHttpclient(), this.httpProxy, url.toString(), null); + RequestExecutor executor = new SimpleGetRequestExecutor(); + String responseText = executor.execute(this, url.toString(), null); return WxMpOAuth2AccessToken.fromJson(responseText); } catch (IOException e) { throw new RuntimeException(e); @@ -292,8 +289,8 @@ public class WxMpServiceImpl implements WxMpService executor = new SimpleGetRequestExecutor(); - String responseText = executor.execute(getHttpclient(), this.httpProxy, url.toString(), null); + RequestExecutor executor = new SimpleGetRequestExecutor(); + String responseText = executor.execute(this, url.toString(), null); return WxMpUser.fromJson(responseText); } catch (IOException e) { throw new RuntimeException(e); @@ -308,8 +305,8 @@ public class WxMpServiceImpl implements WxMpService T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { + public synchronized T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { if (uri.indexOf("access_token=") != -1) { throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); } @@ -390,7 +386,7 @@ public class WxMpServiceImpl implements WxMpService wxMpService; - - public WxMpUserBlacklistServiceImpl(WxMpService wxMpService) { - this.wxMpService = wxMpService; - } - - @Override - public WxMpUserBlacklistGetResult getBlacklist(String nextOpenid) throws WxErrorException { - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("begin_openid", nextOpenid); - String url = API_BLACKLIST_PREFIX + "/getblacklist"; - String responseContent = this.wxMpService.execute(new SimplePostRequestExecutor(), url, jsonObject.toString()); - return WxMpUserBlacklistGetResult.fromJson(responseContent); - } - - @Override - public void pushToBlacklist(List openidList) throws WxErrorException { - Map map = new HashMap<>(); - map.put("openid_list", openidList); - String url = API_BLACKLIST_PREFIX + "/batchblacklist"; - this.wxMpService.execute(new SimplePostRequestExecutor(), url, new Gson().toJson(map)); - } - - @Override - public void pullFromBlacklist(List openidList) throws WxErrorException { - Map map = new HashMap<>(); - map.put("openid_list", openidList); - String url = API_BLACKLIST_PREFIX + "/batchunblacklist"; - this.wxMpService.execute(new SimplePostRequestExecutor(), url, new Gson().toJson(map)); - } -} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpCardServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpCardServiceImpl.java deleted file mode 100644 index 0789b7ea..00000000 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpCardServiceImpl.java +++ /dev/null @@ -1,251 +0,0 @@ -package me.chanjar.weixin.mp.api.impl.jodd; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.JsonPrimitive; -import com.google.gson.reflect.TypeToken; -import jodd.http.HttpConnectionProvider; -import jodd.http.ProxyInfo; -import me.chanjar.weixin.common.bean.WxCardApiSignature; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.RandomUtils; -import me.chanjar.weixin.common.util.crypto.SHA1; -import me.chanjar.weixin.common.util.http.jodd.SimpleGetRequestExecutor; -import me.chanjar.weixin.mp.api.WxMpCardService; -import me.chanjar.weixin.mp.api.WxMpService; -import me.chanjar.weixin.mp.bean.result.WxMpCardResult; -import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Arrays; -import java.util.concurrent.locks.Lock; - -/** - * Created by Binary Wang on 2016/7/27. - */ -public class WxMpCardServiceImpl implements WxMpCardService { - - private final Logger log = LoggerFactory.getLogger(WxMpCardServiceImpl.class); - - private WxMpService wxMpService; - - public WxMpCardServiceImpl(WxMpService wxMpService) { - this.wxMpService = wxMpService; - } - - /** - * 得到WxMpService - * @return - */ - @Override - public WxMpService getWxMpService(){ - return this.wxMpService; - } - - /** - * 获得卡券api_ticket,不强制刷新卡券api_ticket - * - * @return 卡券api_ticket - * @see #getCardApiTicket(boolean) - */ - @Override - public String getCardApiTicket() throws WxErrorException { - return getCardApiTicket(false); - } - - /** - *
-   * 获得卡券api_ticket
-   * 获得时会检查卡券apiToken是否过期,如果过期了,那么就刷新一下,否则就什么都不干
-   *
-   * 详情请见:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD
-   * .954-.E5.8D.A1.E5.88.B8.E6.89.A9.E5.B1.95.E5.AD.97.E6.AE.B5.E5.8F.8A.E7.AD.BE.E5.90.8D.E7.94
-   * .9F.E6.88.90.E7.AE.97.E6.B3.95
-   * 
- * - * @param forceRefresh 强制刷新 - * @return 卡券api_ticket - */ - @Override - public String getCardApiTicket(boolean forceRefresh) throws WxErrorException { - Lock lock = getWxMpService().getWxMpConfigStorage().getCardApiTicketLock(); - try { - lock.lock(); - - if (forceRefresh) { - this.getWxMpService().getWxMpConfigStorage().expireCardApiTicket(); - } - - if (this.getWxMpService().getWxMpConfigStorage().isCardApiTicketExpired()) { - String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=wx_card"; - String responseContent = this.wxMpService.execute(new SimpleGetRequestExecutor(), url, null); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); - String cardApiTicket = tmpJsonObject.get("ticket").getAsString(); - int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); - this.getWxMpService().getWxMpConfigStorage().updateCardApiTicket(cardApiTicket, expiresInSeconds); - } - } finally { - lock.unlock(); - } - return this.getWxMpService().getWxMpConfigStorage().getCardApiTicket(); - } - - /** - *
-   * 创建调用卡券api时所需要的签名
-   *
-   * 详情请见:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD
-   * .954-.E5.8D.A1.E5.88.B8.E6.89.A9.E5.B1.95.E5.AD.97.E6.AE.B5.E5.8F.8A.E7.AD.BE.E5.90.8D.E7.94
-   * .9F.E6.88.90.E7.AE.97.E6.B3.95
-   * 
- * - * @param optionalSignParam 参与签名的参数数组。 - * 可以为下列字段:app_id, card_id, card_type, code, openid, location_id - *
注意:当做wx.chooseCard调用时,必须传入app_id参与签名,否则会造成签名失败导致拉取卡券列表为空 - * @return 卡券Api签名对象 - */ - @Override - public WxCardApiSignature createCardApiSignature(String... optionalSignParam) throws - WxErrorException { - long timestamp = System.currentTimeMillis() / 1000; - String nonceStr = RandomUtils.getRandomStr(); - String cardApiTicket = getCardApiTicket(false); - - String[] signParam = Arrays.copyOf(optionalSignParam, optionalSignParam.length + 3); - signParam[optionalSignParam.length] = String.valueOf(timestamp); - signParam[optionalSignParam.length + 1] = nonceStr; - signParam[optionalSignParam.length + 2] = cardApiTicket; - String signature = SHA1.gen(signParam); - WxCardApiSignature cardApiSignature = new WxCardApiSignature(); - cardApiSignature.setTimestamp(timestamp); - cardApiSignature.setNonceStr(nonceStr); - cardApiSignature.setSignature(signature); - return cardApiSignature; - } - - /** - * 卡券Code解码 - * - * @param encryptCode 加密Code,通过JSSDK的chooseCard接口获得 - * @return 解密后的Code - */ - @Override - public String decryptCardCode(String encryptCode) throws WxErrorException { - String url = "https://api.weixin.qq.com/card/code/decrypt"; - JsonObject param = new JsonObject(); - param.addProperty("encrypt_code", encryptCode); - String responseContent = this.wxMpService.post(url, param.toString()); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); - JsonPrimitive jsonPrimitive = tmpJsonObject.getAsJsonPrimitive("code"); - return jsonPrimitive.getAsString(); - } - - /** - * 卡券Code查询 - * - * @param cardId 卡券ID代表一类卡券 - * @param code 单张卡券的唯一标准 - * @param checkConsume 是否校验code核销状态,填入true和false时的code异常状态返回数据不同 - * @return WxMpCardResult对象 - */ - @Override - public WxMpCardResult queryCardCode(String cardId, String code, boolean checkConsume) throws WxErrorException { - String url = "https://api.weixin.qq.com/card/code/get"; - JsonObject param = new JsonObject(); - param.addProperty("card_id", cardId); - param.addProperty("code", code); - param.addProperty("check_consume", checkConsume); - String responseContent = this.wxMpService.post(url, param.toString()); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement, - new TypeToken() { - }.getType()); - } - - /** - * 卡券Code核销。核销失败会抛出异常 - * - * @param code 单张卡券的唯一标准 - * @return 调用返回的JSON字符串。 - *
可用 com.google.gson.JsonParser#parse 等方法直接取JSON串中的errcode等信息。 - */ - @Override - public String consumeCardCode(String code) throws WxErrorException { - return consumeCardCode(code, null); - } - - /** - * 卡券Code核销。核销失败会抛出异常 - * - * @param code 单张卡券的唯一标准 - * @param cardId 当自定义Code卡券时需要传入card_id - * @return 调用返回的JSON字符串。 - *
可用 com.google.gson.JsonParser#parse 等方法直接取JSON串中的errcode等信息。 - */ - @Override - public String consumeCardCode(String code, String cardId) throws WxErrorException { - String url = "https://api.weixin.qq.com/card/code/consume"; - JsonObject param = new JsonObject(); - param.addProperty("code", code); - - if (cardId != null && !"".equals(cardId)) { - param.addProperty("card_id", cardId); - } - - return this.wxMpService.post(url, param.toString()); - } - - /** - * 卡券Mark接口。 - * 开发者在帮助消费者核销卡券之前,必须帮助先将此code(卡券串码)与一个openid绑定(即mark住), - * 才能进一步调用核销接口,否则报错。 - * - * @param code 卡券的code码 - * @param cardId 卡券的ID - * @param openId 用券用户的openid - * @param isMark 是否要mark(占用)这个code,填写true或者false,表示占用或解除占用 - */ - @Override - public void markCardCode(String code, String cardId, String openId, boolean isMark) throws - WxErrorException { - String url = "https://api.weixin.qq.com/card/code/mark"; - JsonObject param = new JsonObject(); - param.addProperty("code", code); - param.addProperty("card_id", cardId); - param.addProperty("openid", openId); - param.addProperty("is_mark", isMark); - String responseContent = this.getWxMpService().post(url, param.toString()); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - WxMpCardResult cardResult = WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement, - new TypeToken() { }.getType()); - if (!cardResult.getErrorCode().equals("0")) { - this.log.warn("朋友的券mark失败:{}", cardResult.getErrorMsg()); - } - } - - @Override - public String getCardDetail(String cardId) throws WxErrorException { - String url = "https://api.weixin.qq.com/card/get"; - JsonObject param = new JsonObject(); - param.addProperty("card_id", cardId); - String responseContent = this.wxMpService.post(url, param.toString()); - - // 判断返回值 - JsonObject json = (new JsonParser()).parse(responseContent).getAsJsonObject(); - String errcode = json.get("errcode").getAsString(); - if (!"0".equals(errcode)) { - String errmsg = json.get("errmsg").getAsString(); - WxError error = new WxError(); - error.setErrorCode(Integer.valueOf(errcode)); - error.setErrorMsg(errmsg); - throw new WxErrorException(error); - } - - return responseContent; - } -} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpServiceImpl.java index 1480270c..fa342f66 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpServiceImpl.java @@ -14,10 +14,7 @@ import me.chanjar.weixin.common.session.StandardSessionManager; import me.chanjar.weixin.common.session.WxSessionManager; import me.chanjar.weixin.common.util.RandomUtils; import me.chanjar.weixin.common.util.crypto.SHA1; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.http.URIUtil; -import me.chanjar.weixin.common.util.http.jodd.SimpleGetRequestExecutor; -import me.chanjar.weixin.common.util.http.jodd.SimplePostRequestExecutor; +import me.chanjar.weixin.common.util.http.*; import me.chanjar.weixin.mp.api.*; import me.chanjar.weixin.mp.api.impl.*; import me.chanjar.weixin.mp.bean.*; @@ -28,7 +25,7 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.concurrent.locks.Lock; -public class WxMpServiceImpl implements WxMpService { +public class WxMpServiceImpl implements WxMpService,RequestHttp { private static final JsonParser JSON_PARSER = new JsonParser(); @@ -248,8 +245,8 @@ public class WxMpServiceImpl implements WxMpService executor = new SimpleGetRequestExecutor(); - String responseText = executor.execute(getHttpclient(), getHttpProxy(), url.toString(), null); + RequestExecutor executor = new SimpleGetRequestExecutor(); + String responseText = executor.execute(this, url.toString(), null); return WxMpOAuth2AccessToken.fromJson(responseText); } catch (IOException e) { throw new RuntimeException(e); @@ -292,8 +289,8 @@ public class WxMpServiceImpl implements WxMpService executor = new SimpleGetRequestExecutor(); - String responseText = executor.execute(getHttpclient(), getHttpProxy(), url.toString(), null); + RequestExecutor executor = new SimpleGetRequestExecutor(); + String responseText = executor.execute(this, url.toString(), null); return WxMpUser.fromJson(responseText); } catch (IOException e) { throw new RuntimeException(e); @@ -308,8 +305,8 @@ public class WxMpServiceImpl implements WxMpService T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { + public synchronized T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { if (uri.indexOf("access_token=") != -1) { throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); } @@ -394,7 +395,7 @@ public class WxMpServiceImpl implements WxMpService params = new HashMap<>(); + params.put("media_id", materialId); + httpPost.setEntity(new StringEntity(WxGsonBuilder.create().toJson(params))); + try (CloseableHttpResponse response = httpclient.execute(httpPost)) { + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } else { + return true; + } + } finally { + httpPost.releaseConnection(); + } + } + + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialNewsInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialNewsInfoRequestExecutor.java new file mode 100644 index 00000000..87180067 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialNewsInfoRequestExecutor.java @@ -0,0 +1,93 @@ +package me.chanjar.weixin.mp.util.http; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.apache.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.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.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class MaterialNewsInfoRequestExecutor implements RequestExecutor { + + public MaterialNewsInfoRequestExecutor() { + super(); + } + + @Override + public WxMpMaterialNews execute(RequestHttp requestHttp, String uri, + String materialId) throws WxErrorException, IOException { + if (requestHttp.getRequestHttpClient() instanceof CloseableHttpClient) { + CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getRequestHttpClient(); + HttpHost httpProxy = (HttpHost) requestHttp.getRequestHttpProxy(); + return executeApache(httpClient, httpProxy, uri, materialId); + } + if (requestHttp.getRequestHttpClient() instanceof HttpConnectionProvider) { + HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getRequestHttpClient(); + ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getRequestHttpProxy(); + return executeJodd(provider, proxyInfo, uri, materialId); + } else { + //这里需要抛出异常,需要优化 + return null; + } + } + + public WxMpMaterialNews executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String materialId) throws WxErrorException, IOException { + HttpPost httpPost = new HttpPost(uri); + if (httpProxy != null) { + RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); + httpPost.setConfig(config); + } + + Map params = new HashMap<>(); + params.put("media_id", materialId); + httpPost.setEntity(new StringEntity(WxGsonBuilder.create().toJson(params))); + try (CloseableHttpResponse response = httpclient.execute(httpPost)) { + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } else { + return WxMpGsonBuilder.create().fromJson(responseContent, WxMpMaterialNews.class); + } + } finally { + httpPost.releaseConnection(); + } + } + + + public WxMpMaterialNews executeJodd(HttpConnectionProvider httpclient, ProxyInfo httpProxy, String uri, String materialId) throws WxErrorException, IOException { + HttpRequest request = HttpRequest.post(uri); + if (httpProxy != null) { + httpclient.useProxy(httpProxy); + } + request.withConnectionProvider(httpclient); + + request.query("media_id", materialId); + HttpResponse response = request.send(); + + String responseContent = request.bodyText(); + WxError error = WxError.fromJson(responseContent); + 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/http/MaterialUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialUploadRequestExecutor.java new file mode 100644 index 00000000..a1e1a91b --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialUploadRequestExecutor.java @@ -0,0 +1,121 @@ +package me.chanjar.weixin.mp.util.http; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.apache.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.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.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.impl.client.CloseableHttpClient; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Map; + +public class MaterialUploadRequestExecutor implements RequestExecutor { + + @Override + public WxMpMaterialUploadResult execute(RequestHttp requestHttp, String uri, WxMpMaterial material) throws WxErrorException, IOException { + if (requestHttp.getRequestHttpClient() instanceof CloseableHttpClient) { + CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getRequestHttpClient(); + HttpHost httpProxy = (HttpHost) requestHttp.getRequestHttpProxy(); + return executeApache(httpClient, httpProxy, uri, material); + } + if (requestHttp.getRequestHttpClient() instanceof HttpConnectionProvider) { + HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getRequestHttpClient(); + ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getRequestHttpProxy(); + return executeJodd(provider, proxyInfo, uri, material); + } else { + //这里需要抛出异常,需要优化 + return null; + } + } + + private WxMpMaterialUploadResult executeJodd(HttpConnectionProvider provider, ProxyInfo httpProxy, String uri, WxMpMaterial material) throws WxErrorException, IOException { + HttpRequest request = HttpRequest.post(uri); + if (httpProxy != null) { + provider.useProxy(httpProxy); + } + request.withConnectionProvider(provider); + + if (material == null) { + throw new WxErrorException(WxError.newBuilder().setErrorMsg("非法请求,material参数为空").build()); + } + + File file = material.getFile(); + if (file == null || !file.exists()) { + throw new FileNotFoundException(); + } + request.form("media", file); + Map form = material.getForm(); + if (material.getForm() != null) { + request.form("description", WxGsonBuilder.create().toJson(form)); + } + + HttpResponse response = request.send(); + String responseContent = response.bodyText(); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } else { + return WxMpMaterialUploadResult.fromJson(responseContent); + } + } + + private WxMpMaterialUploadResult executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, + WxMpMaterial material) throws WxErrorException, IOException { + HttpPost httpPost = new HttpPost(uri); + if (httpProxy != null) { + RequestConfig response = RequestConfig.custom().setProxy(httpProxy).build(); + httpPost.setConfig(response); + } + + if (material == null) { + throw new WxErrorException(WxError.newBuilder().setErrorMsg("非法请求,material参数为空").build()); + } + + File file = material.getFile(); + if (file == null || !file.exists()) { + throw new FileNotFoundException(); + } + + MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create(); + multipartEntityBuilder + .addBinaryBody("media", file) + .setMode(HttpMultipartMode.RFC6532); + Map form = material.getForm(); + if (material.getForm() != null) { + multipartEntityBuilder.addTextBody("description", WxGsonBuilder.create().toJson(form)); + } + + httpPost.setEntity(multipartEntityBuilder.build()); + httpPost.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.toString()); + + try (CloseableHttpResponse response = httpclient.execute(httpPost)) { + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } else { + return WxMpMaterialUploadResult.fromJson(responseContent); + } + } finally { + httpPost.releaseConnection(); + } + } + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVideoInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVideoInfoRequestExecutor.java new file mode 100644 index 00000000..fb581892 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVideoInfoRequestExecutor.java @@ -0,0 +1,92 @@ +package me.chanjar.weixin.mp.util.http; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import me.chanjar.weixin.mp.bean.material.WxMpMaterialVideoInfoResult; +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.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class MaterialVideoInfoRequestExecutor implements RequestExecutor { + + public MaterialVideoInfoRequestExecutor() { + super(); + } + + @Override + public WxMpMaterialVideoInfoResult execute(RequestHttp requestHttp, String uri, String materialId) throws WxErrorException, IOException { + if (requestHttp.getRequestHttpClient() instanceof CloseableHttpClient) { + CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getRequestHttpClient(); + HttpHost httpProxy = (HttpHost) requestHttp.getRequestHttpProxy(); + return executeApache(httpClient, httpProxy, uri, materialId); + } + if (requestHttp.getRequestHttpClient() instanceof HttpConnectionProvider) { + HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getRequestHttpClient(); + ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getRequestHttpProxy(); + return executeJodd(provider, proxyInfo, uri, materialId); + } else { + //这里需要抛出异常,需要优化 + return null; + } + } + + + private WxMpMaterialVideoInfoResult executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, String materialId) throws WxErrorException, IOException { + HttpRequest request = HttpRequest.post(uri); + if (proxyInfo != null) { + provider.useProxy(proxyInfo); + } + request.withConnectionProvider(provider); + + request.query("media_id", materialId); + HttpResponse response = request.send(); + String responseContent = response.bodyText(); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } else { + return WxMpMaterialVideoInfoResult.fromJson(responseContent); + } + } + + private WxMpMaterialVideoInfoResult executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, + String materialId) throws WxErrorException, IOException { + HttpPost httpPost = new HttpPost(uri); + if (httpProxy != null) { + RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); + httpPost.setConfig(config); + } + + Map params = new HashMap<>(); + params.put("media_id", materialId); + httpPost.setEntity(new StringEntity(WxGsonBuilder.create().toJson(params))); + try (CloseableHttpResponse response = httpclient.execute(httpPost)) { + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } else { + return WxMpMaterialVideoInfoResult.fromJson(responseContent); + } + } finally { + httpPost.releaseConnection(); + } + } + + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVoiceAndImageDownloadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVoiceAndImageDownloadRequestExecutor.java new file mode 100644 index 00000000..913ca086 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVoiceAndImageDownloadRequestExecutor.java @@ -0,0 +1,117 @@ +package me.chanjar.weixin.mp.util.http; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.apache.InputStreamResponseHandler; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import org.apache.commons.io.IOUtils; +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.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +public class MaterialVoiceAndImageDownloadRequestExecutor implements RequestExecutor { + + + public MaterialVoiceAndImageDownloadRequestExecutor() { + super(); + } + + public MaterialVoiceAndImageDownloadRequestExecutor(File tmpDirFile) { + super(); + } + + @Override + public InputStream execute(RequestHttp requestHttp, String uri, String materialId) throws WxErrorException, IOException { + if (requestHttp.getRequestHttpClient() instanceof CloseableHttpClient) { + CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getRequestHttpClient(); + HttpHost httpProxy = (HttpHost) requestHttp.getRequestHttpProxy(); + return executeApache(httpClient, httpProxy, uri, materialId); + } + if (requestHttp.getRequestHttpClient() instanceof HttpConnectionProvider) { + HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getRequestHttpClient(); + ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getRequestHttpProxy(); + return executeJodd(provider, proxyInfo, uri, materialId); + } else { + //这里需要抛出异常,需要优化 + return null; + } + } + + private InputStream executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, String materialId) throws WxErrorException, IOException { + HttpRequest request = HttpRequest.post(uri); + if (proxyInfo != null) { + provider.useProxy(proxyInfo); + } + request.withConnectionProvider(provider); + + request.query("media_id", materialId); + HttpResponse response = request.send(); + try (InputStream inputStream = new ByteArrayInputStream(response.bodyBytes())) { + // 下载媒体文件出错 + byte[] responseContent = IOUtils.toByteArray(inputStream); + String responseContentString = new String(responseContent, "UTF-8"); + if (responseContentString.length() < 100) { + 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); + } + + } + + private InputStream executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, + String materialId) throws WxErrorException, IOException { + HttpPost httpPost = new HttpPost(uri); + if (httpProxy != null) { + RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); + httpPost.setConfig(config); + } + + Map params = new HashMap<>(); + params.put("media_id", materialId); + httpPost.setEntity(new StringEntity(WxGsonBuilder.create().toJson(params))); + try (CloseableHttpResponse response = httpclient.execute(httpPost); + InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response);) { + // 下载媒体文件出错 + byte[] responseContent = IOUtils.toByteArray(inputStream); + String responseContentString = new String(responseContent, "UTF-8"); + if (responseContentString.length() < 100) { + 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); + } finally { + httpPost.releaseConnection(); + } + } + + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MediaImgUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MediaImgUploadRequestExecutor.java new file mode 100644 index 00000000..c22bc310 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MediaImgUploadRequestExecutor.java @@ -0,0 +1,103 @@ +package me.chanjar.weixin.mp.util.http; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult; +import org.apache.http.HttpEntity; +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.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.impl.client.CloseableHttpClient; + +import java.io.File; +import java.io.IOException; + +/** + * @author miller + */ +public class MediaImgUploadRequestExecutor implements RequestExecutor { + + @Override + public WxMediaImgUploadResult execute(RequestHttp requestHttp, String uri, File data) throws WxErrorException, IOException { + if (requestHttp.getRequestHttpClient() instanceof CloseableHttpClient) { + CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getRequestHttpClient(); + HttpHost httpProxy = (HttpHost) requestHttp.getRequestHttpProxy(); + return executeApache(httpClient, httpProxy, uri, data); + } + if (requestHttp.getRequestHttpClient() instanceof HttpConnectionProvider) { + HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getRequestHttpClient(); + ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getRequestHttpProxy(); + return executeJodd(provider, proxyInfo, uri, data); + } else { + //这里需要抛出异常,需要优化 + return null; + } + + } + + + private WxMediaImgUploadResult executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, File data) throws WxErrorException, IOException { + if (data == null) { + throw new WxErrorException(WxError.newBuilder().setErrorMsg("文件对象为空").build()); + } + + HttpRequest request = HttpRequest.post(uri); + if (proxyInfo != null) { + provider.useProxy(proxyInfo); + } + request.withConnectionProvider(provider); + + request.form("media", data); + HttpResponse response = request.send(); + String responseContent = response.bodyText(); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + + return WxMediaImgUploadResult.fromJson(responseContent); + } + + private WxMediaImgUploadResult executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, + File data) throws WxErrorException, IOException { + if (data == null) { + throw new WxErrorException(WxError.newBuilder().setErrorMsg("文件对象为空").build()); + } + + HttpPost httpPost = new HttpPost(uri); + if (httpProxy != null) { + RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); + httpPost.setConfig(config); + } + + HttpEntity entity = MultipartEntityBuilder + .create() + .addBinaryBody("media", data) + .setMode(HttpMultipartMode.RFC6532) + .build(); + httpPost.setEntity(entity); + httpPost.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.toString()); + + try (CloseableHttpResponse response = httpclient.execute(httpPost)) { + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + WxError error = WxError.fromJson(responseContent); + 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/http/QrCodeRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/QrCodeRequestExecutor.java new file mode 100644 index 00000000..c9ae525c --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/QrCodeRequestExecutor.java @@ -0,0 +1,116 @@ +package me.chanjar.weixin.mp.util.http; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import jodd.util.MimeTypes; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.fs.FileUtils; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.apache.InputStreamResponseHandler; +import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; +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.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URLEncoder; +import java.util.UUID; + +/** + * 获得QrCode图片 请求执行器 + * + * @author chanjarster + */ +public class QrCodeRequestExecutor implements RequestExecutor { + + @Override + public File execute(RequestHttp requestHttp, String uri, + WxMpQrCodeTicket ticket) throws WxErrorException, IOException { + if (requestHttp.getRequestHttpClient() instanceof CloseableHttpClient) { + CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getRequestHttpClient(); + HttpHost httpProxy = (HttpHost) requestHttp.getRequestHttpProxy(); + return executeApache(httpClient, httpProxy, uri, ticket); + } + if (requestHttp.getRequestHttpClient() instanceof HttpConnectionProvider) { + HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getRequestHttpClient(); + ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getRequestHttpProxy(); + return executeJodd(provider, proxyInfo, uri, ticket); + } else { + //这里需要抛出异常,需要优化 + return null; + } + } + + private File executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, WxMpQrCodeTicket ticket) 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"); + } + + HttpRequest request = HttpRequest.get(uri); + if (proxyInfo != null) { + provider.useProxy(proxyInfo); + } + request.withConnectionProvider(provider); + + HttpResponse response = request.send(); + String contentTypeHeader = response.header("Content-Type"); + if (MimeTypes.MIME_TEXT_PLAIN.equals(contentTypeHeader)) { + String responseContent = response.bodyText(); + throw new WxErrorException(WxError.fromJson(responseContent)); + } + try (InputStream inputStream = new ByteArrayInputStream(response.bodyBytes())) { + return FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), "jpg"); + } + } + + private File executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, + WxMpQrCodeTicket ticket) 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 (httpProxy != null) { + RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); + httpGet.setConfig(config); + } + + try (CloseableHttpResponse response = httpclient.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(contentTypeHeader[0].getValue())) { + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + throw new WxErrorException(WxError.fromJson(responseContent)); + } + } + return FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), "jpg"); + } finally { + httpGet.releaseConnection(); + } + } + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialDeleteRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialDeleteRequestExecutor.java deleted file mode 100644 index b25d668d..00000000 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialDeleteRequestExecutor.java +++ /dev/null @@ -1,50 +0,0 @@ -package me.chanjar.weixin.mp.util.http.apache; - -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; -import me.chanjar.weixin.common.util.json.WxGsonBuilder; -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.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -public class MaterialDeleteRequestExecutor implements RequestExecutor { - - - public MaterialDeleteRequestExecutor() { - super(); - } - - @Override - public Boolean execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String materialId) throws WxErrorException, IOException { - HttpPost httpPost = new HttpPost(uri); - if (httpProxy != null) { - RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); - httpPost.setConfig(config); - } - - Map params = new HashMap<>(); - params.put("media_id", materialId); - httpPost.setEntity(new StringEntity(WxGsonBuilder.create().toJson(params))); - try(CloseableHttpResponse response = httpclient.execute(httpPost)){ - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } else { - return true; - } - }finally { - httpPost.releaseConnection(); - } - } - -} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialNewsInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialNewsInfoRequestExecutor.java deleted file mode 100644 index f29de11f..00000000 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialNewsInfoRequestExecutor.java +++ /dev/null @@ -1,52 +0,0 @@ -package me.chanjar.weixin.mp.util.http.apache; - -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.http.apache.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.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.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -public class MaterialNewsInfoRequestExecutor implements RequestExecutor { - - public MaterialNewsInfoRequestExecutor() { - super(); - } - - @Override - public WxMpMaterialNews execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String materialId) throws WxErrorException, IOException { - HttpPost httpPost = new HttpPost(uri); - if (httpProxy != null) { - RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); - httpPost.setConfig(config); - } - - Map params = new HashMap<>(); - params.put("media_id", materialId); - httpPost.setEntity(new StringEntity(WxGsonBuilder.create().toJson(params))); - try(CloseableHttpResponse response = httpclient.execute(httpPost)){ - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } else { - return WxMpGsonBuilder.create().fromJson(responseContent, WxMpMaterialNews.class); - } - }finally { - httpPost.releaseConnection(); - } - - } - -} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialUploadRequestExecutor.java deleted file mode 100644 index d0c16f2d..00000000 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialUploadRequestExecutor.java +++ /dev/null @@ -1,68 +0,0 @@ -package me.chanjar.weixin.mp.util.http.apache; - -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.http.apache.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.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.mime.HttpMultipartMode; -import org.apache.http.entity.mime.MultipartEntityBuilder; -import org.apache.http.impl.client.CloseableHttpClient; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.Map; - -public class MaterialUploadRequestExecutor implements RequestExecutor { - - @Override - public WxMpMaterialUploadResult execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, WxMpMaterial material) throws WxErrorException, IOException { - HttpPost httpPost = new HttpPost(uri); - if (httpProxy != null) { - RequestConfig response = RequestConfig.custom().setProxy(httpProxy).build(); - httpPost.setConfig(response); - } - - if (material == null) { - throw new WxErrorException(WxError.newBuilder().setErrorMsg("非法请求,material参数为空").build()); - } - - File file = material.getFile(); - if (file == null || !file.exists()) { - throw new FileNotFoundException(); - } - - MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create(); - multipartEntityBuilder - .addBinaryBody("media", file) - .setMode(HttpMultipartMode.RFC6532); - Map form = material.getForm(); - if (material.getForm() != null) { - multipartEntityBuilder.addTextBody("description", WxGsonBuilder.create().toJson(form)); - } - - httpPost.setEntity(multipartEntityBuilder.build()); - httpPost.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.toString()); - - try (CloseableHttpResponse response = httpclient.execute(httpPost)) { - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } else { - return WxMpMaterialUploadResult.fromJson(responseContent); - } - } finally { - httpPost.releaseConnection(); - } - } - -} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialVideoInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialVideoInfoRequestExecutor.java deleted file mode 100644 index 16176755..00000000 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialVideoInfoRequestExecutor.java +++ /dev/null @@ -1,50 +0,0 @@ -package me.chanjar.weixin.mp.util.http.apache; - -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; -import me.chanjar.weixin.common.util.json.WxGsonBuilder; -import me.chanjar.weixin.mp.bean.material.WxMpMaterialVideoInfoResult; -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.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -public class MaterialVideoInfoRequestExecutor implements RequestExecutor { - - public MaterialVideoInfoRequestExecutor() { - super(); - } - - @Override - public WxMpMaterialVideoInfoResult execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String materialId) throws WxErrorException, IOException { - HttpPost httpPost = new HttpPost(uri); - if (httpProxy != null) { - RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); - httpPost.setConfig(config); - } - - Map params = new HashMap<>(); - params.put("media_id", materialId); - httpPost.setEntity(new StringEntity(WxGsonBuilder.create().toJson(params))); - try(CloseableHttpResponse response = httpclient.execute(httpPost)){ - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } else { - return WxMpMaterialVideoInfoResult.fromJson(responseContent); - } - }finally { - httpPost.releaseConnection(); - } - } - -} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialVoiceAndImageDownloadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialVoiceAndImageDownloadRequestExecutor.java deleted file mode 100644 index 3a29ccfa..00000000 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MaterialVoiceAndImageDownloadRequestExecutor.java +++ /dev/null @@ -1,66 +0,0 @@ -package me.chanjar.weixin.mp.util.http.apache; - -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.http.apache.InputStreamResponseHandler; -import me.chanjar.weixin.common.util.json.WxGsonBuilder; -import org.apache.commons.io.IOUtils; -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.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; - -public class MaterialVoiceAndImageDownloadRequestExecutor implements RequestExecutor { - - - public MaterialVoiceAndImageDownloadRequestExecutor() { - super(); - } - - public MaterialVoiceAndImageDownloadRequestExecutor(File tmpDirFile) { - super(); - } - - @Override - public InputStream execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String materialId) throws WxErrorException, IOException { - HttpPost httpPost = new HttpPost(uri); - if (httpProxy != null) { - RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); - httpPost.setConfig(config); - } - - Map params = new HashMap<>(); - params.put("media_id", materialId); - httpPost.setEntity(new StringEntity(WxGsonBuilder.create().toJson(params))); - try (CloseableHttpResponse response = httpclient.execute(httpPost); - InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response);){ - // 下载媒体文件出错 - byte[] responseContent = IOUtils.toByteArray(inputStream); - String responseContentString = new String(responseContent, "UTF-8"); - if (responseContentString.length() < 100) { - 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); - }finally { - httpPost.releaseConnection(); - } - } - -} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MediaImgUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MediaImgUploadRequestExecutor.java deleted file mode 100644 index e253f4ee..00000000 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/MediaImgUploadRequestExecutor.java +++ /dev/null @@ -1,55 +0,0 @@ -package me.chanjar.weixin.mp.util.http.apache; - -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; -import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult; -import org.apache.http.HttpEntity; -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.mime.HttpMultipartMode; -import org.apache.http.entity.mime.MultipartEntityBuilder; -import org.apache.http.impl.client.CloseableHttpClient; - -import java.io.File; -import java.io.IOException; - -/** - * @author miller - */ -public class MediaImgUploadRequestExecutor implements RequestExecutor { - @Override - public WxMediaImgUploadResult execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, File data) throws WxErrorException, IOException { - if (data == null) { - throw new WxErrorException(WxError.newBuilder().setErrorMsg("文件对象为空").build()); - } - - HttpPost httpPost = new HttpPost(uri); - if (httpProxy != null) { - RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); - httpPost.setConfig(config); - } - - HttpEntity entity = MultipartEntityBuilder - .create() - .addBinaryBody("media", data) - .setMode(HttpMultipartMode.RFC6532) - .build(); - httpPost.setEntity(entity); - httpPost.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.toString()); - - try (CloseableHttpResponse response = httpclient.execute(httpPost)) { - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - WxError error = WxError.fromJson(responseContent); - 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/http/apache/QrCodeRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/QrCodeRequestExecutor.java deleted file mode 100644 index b0823365..00000000 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/QrCodeRequestExecutor.java +++ /dev/null @@ -1,66 +0,0 @@ -package me.chanjar.weixin.mp.util.http.apache; - -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.fs.FileUtils; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.http.apache.InputStreamResponseHandler; -import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; -import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; -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; -import java.net.URLEncoder; -import java.util.UUID; - -/** - * 获得QrCode图片 请求执行器 - * @author chanjarster - * - */ -public class QrCodeRequestExecutor implements RequestExecutor { - - @Override - public File execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, - WxMpQrCodeTicket ticket) 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 (httpProxy != null) { - RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); - httpGet.setConfig(config); - } - - try (CloseableHttpResponse response = httpclient.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(contentTypeHeader[0].getValue())) { - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - throw new WxErrorException(WxError.fromJson(responseContent)); - } - } - return FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), "jpg"); - } finally { - httpGet.releaseConnection(); - } - - } - -} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialDeleteRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialDeleteRequestExecutor.java deleted file mode 100644 index 26485742..00000000 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialDeleteRequestExecutor.java +++ /dev/null @@ -1,39 +0,0 @@ -package me.chanjar.weixin.mp.util.http.jodd; - -import jodd.http.HttpConnectionProvider; -import jodd.http.HttpRequest; -import jodd.http.HttpResponse; -import jodd.http.ProxyInfo; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestExecutor; - -import java.io.IOException; - -public class MaterialDeleteRequestExecutor implements RequestExecutor { - - - public MaterialDeleteRequestExecutor() { - super(); - } - - @Override - public Boolean execute(HttpConnectionProvider httpclient, ProxyInfo httpProxy, String uri, String materialId) throws WxErrorException, IOException { - HttpRequest request = HttpRequest.post(uri); - if (httpProxy != null) { - httpclient.useProxy(httpProxy); - } - request.withConnectionProvider(httpclient); - - request.query("media_id", materialId); - HttpResponse response = request.send(); - String responseContent = response.bodyText(); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } else { - return true; - } - } - -} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialNewsInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialNewsInfoRequestExecutor.java deleted file mode 100644 index 93b3a735..00000000 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialNewsInfoRequestExecutor.java +++ /dev/null @@ -1,41 +0,0 @@ -package me.chanjar.weixin.mp.util.http.jodd; - -import jodd.http.HttpConnectionProvider; -import jodd.http.HttpRequest; -import jodd.http.HttpResponse; -import jodd.http.ProxyInfo; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.mp.bean.material.WxMpMaterialNews; -import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; - -import java.io.IOException; - -public class MaterialNewsInfoRequestExecutor implements RequestExecutor { - - public MaterialNewsInfoRequestExecutor() { - super(); - } - - @Override - public WxMpMaterialNews execute(HttpConnectionProvider httpclient, ProxyInfo httpProxy, String uri, String materialId) throws WxErrorException, IOException { - HttpRequest request = HttpRequest.post(uri); - if (httpProxy != null) { - httpclient.useProxy(httpProxy); - } - request.withConnectionProvider(httpclient); - - request.query("media_id", materialId); - HttpResponse response = request.send(); - - String responseContent = request.bodyText(); - WxError error = WxError.fromJson(responseContent); - 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/http/jodd/MaterialUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialUploadRequestExecutor.java deleted file mode 100644 index 85b6665e..00000000 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialUploadRequestExecutor.java +++ /dev/null @@ -1,53 +0,0 @@ -package me.chanjar.weixin.mp.util.http.jodd; - -import jodd.http.HttpConnectionProvider; -import jodd.http.HttpRequest; -import jodd.http.HttpResponse; -import jodd.http.ProxyInfo; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestExecutor; -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 java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.Map; - -public class MaterialUploadRequestExecutor implements RequestExecutor { - - @Override - public WxMpMaterialUploadResult execute(HttpConnectionProvider provider, ProxyInfo httpProxy, String uri, WxMpMaterial material) throws WxErrorException, IOException { - HttpRequest request = HttpRequest.post(uri); - if (httpProxy != null) { - provider.useProxy(httpProxy); - } - request.withConnectionProvider(provider); - - if (material == null) { - throw new WxErrorException(WxError.newBuilder().setErrorMsg("非法请求,material参数为空").build()); - } - - File file = material.getFile(); - if (file == null || !file.exists()) { - throw new FileNotFoundException(); - } - request.form("media", file); - Map form = material.getForm(); - if (material.getForm() != null) { - request.form("description", WxGsonBuilder.create().toJson(form)); - } - - HttpResponse response = request.send(); - String responseContent = response.bodyText(); - WxError error = WxError.fromJson(responseContent); - 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/http/jodd/MaterialVideoInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialVideoInfoRequestExecutor.java deleted file mode 100644 index 7b7272b7..00000000 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialVideoInfoRequestExecutor.java +++ /dev/null @@ -1,39 +0,0 @@ -package me.chanjar.weixin.mp.util.http.jodd; - -import jodd.http.HttpConnectionProvider; -import jodd.http.HttpRequest; -import jodd.http.HttpResponse; -import jodd.http.ProxyInfo; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.mp.bean.material.WxMpMaterialVideoInfoResult; - -import java.io.IOException; - -public class MaterialVideoInfoRequestExecutor implements RequestExecutor { - - public MaterialVideoInfoRequestExecutor() { - super(); - } - - @Override - public WxMpMaterialVideoInfoResult execute(HttpConnectionProvider provider, ProxyInfo httpProxy, String uri, String materialId) throws WxErrorException, IOException { - HttpRequest request = HttpRequest.post(uri); - if (httpProxy != null) { - provider.useProxy(httpProxy); - } - request.withConnectionProvider(provider); - - request.query("media_id", materialId); - HttpResponse response =request.send(); - String responseContent = response.bodyText(); - WxError error = WxError.fromJson(responseContent); - 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/http/jodd/MaterialVoiceAndImageDownloadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialVoiceAndImageDownloadRequestExecutor.java deleted file mode 100644 index 4d988bad..00000000 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MaterialVoiceAndImageDownloadRequestExecutor.java +++ /dev/null @@ -1,57 +0,0 @@ -package me.chanjar.weixin.mp.util.http.jodd; - -import jodd.http.HttpConnectionProvider; -import jodd.http.HttpRequest; -import jodd.http.HttpResponse; -import jodd.http.ProxyInfo; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.json.WxGsonBuilder; -import org.apache.commons.io.IOUtils; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; - -public class MaterialVoiceAndImageDownloadRequestExecutor implements RequestExecutor { - - - public MaterialVoiceAndImageDownloadRequestExecutor() { - super(); - } - - public MaterialVoiceAndImageDownloadRequestExecutor(File tmpDirFile) { - super(); - } - - @Override - public InputStream execute(HttpConnectionProvider provider, ProxyInfo httpProxy, String uri, String materialId) throws WxErrorException, IOException { - HttpRequest request = HttpRequest.post(uri); - if (httpProxy != null) { - provider.useProxy(httpProxy); - } - request.withConnectionProvider(provider); - - request.query("media_id", materialId); - HttpResponse response = request.send(); - - InputStream inputStream = new ByteArrayInputStream(response.bodyBytes()); - // 下载媒体文件出错 - byte[] responseContent = IOUtils.toByteArray(inputStream); - String responseContentString = new String(responseContent, "UTF-8"); - if (responseContentString.length() < 100) { - 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); - } - -} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MediaImgUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MediaImgUploadRequestExecutor.java deleted file mode 100644 index 7c4b13f9..00000000 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/MediaImgUploadRequestExecutor.java +++ /dev/null @@ -1,42 +0,0 @@ -package me.chanjar.weixin.mp.util.http.jodd; - -import jodd.http.HttpConnectionProvider; -import jodd.http.HttpRequest; -import jodd.http.HttpResponse; -import jodd.http.ProxyInfo; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult; - -import java.io.File; -import java.io.IOException; - -/** - * @author miller - */ -public class MediaImgUploadRequestExecutor implements RequestExecutor { - @Override - public WxMediaImgUploadResult execute(HttpConnectionProvider provider, ProxyInfo httpProxy, String uri, File data) throws WxErrorException, IOException { - if (data == null) { - throw new WxErrorException(WxError.newBuilder().setErrorMsg("文件对象为空").build()); - } - - HttpRequest request = HttpRequest.post(uri); - if (httpProxy != null) { - provider.useProxy(httpProxy); - } - request.withConnectionProvider(provider); - - request.form("media", data); - HttpResponse response =request.send(); - - String responseContent =response.bodyText(); - WxError error = WxError.fromJson(responseContent); - 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/http/jodd/QrCodeRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/QrCodeRequestExecutor.java deleted file mode 100644 index d1b6f2c5..00000000 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/QrCodeRequestExecutor.java +++ /dev/null @@ -1,60 +0,0 @@ -package me.chanjar.weixin.mp.util.http.jodd; - -import jodd.http.HttpConnectionProvider; -import jodd.http.HttpRequest; -import jodd.http.HttpResponse; -import jodd.http.ProxyInfo; -import jodd.util.MimeTypes; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.fs.FileUtils; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.URLEncoder; -import java.util.UUID; - -/** - * 获得QrCode图片 请求执行器 - * - * @author chanjarster - */ -public class QrCodeRequestExecutor implements RequestExecutor { - - @Override - public File execute(HttpConnectionProvider provider, ProxyInfo httpProxy, String uri, - WxMpQrCodeTicket ticket) 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"); - } - - - HttpRequest request = HttpRequest.get(uri); - if (httpProxy != null) { - provider.useProxy(httpProxy); - } - request.withConnectionProvider(provider); - - HttpResponse response = request.send(); - try ( - InputStream inputStream = new ByteArrayInputStream(response.bodyBytes());) { - String contentTypeHeader = response.header("Content-Type"); - // 出错 - if (MimeTypes.MIME_TEXT_PLAIN.equals(contentTypeHeader)) { - String responseContent = response.bodyText(); - throw new WxErrorException(WxError.fromJson(responseContent)); - } - return FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), "jpg"); - } - } - -} diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBusyRetryTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBusyRetryTest.java index 25dedbaa..74777cae 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBusyRetryTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBusyRetryTest.java @@ -4,8 +4,6 @@ import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.http.RequestExecutor; import me.chanjar.weixin.mp.api.impl.apache.WxMpServiceImpl; -import org.apache.http.HttpHost; -import org.apache.http.impl.client.CloseableHttpClient; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -23,7 +21,7 @@ public class WxMpBusyRetryTest { @Override public synchronized T executeInternal( - RequestExecutor executor, String uri, E data) + RequestExecutor executor, String uri, E data) throws WxErrorException { this.log.info("Executed"); WxError error = new WxError(); From b03cb4b783bb7ea5fce3f9f1610bd26de596f4a2 Mon Sep 17 00:00:00 2001 From: ecoolper Date: Sat, 22 Apr 2017 20:11:57 +0800 Subject: [PATCH 10/27] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=E6=B3=A8?= =?UTF-8?q?=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- weixin-java-common/pom.xml | 5 +++++ .../http/MediaDownloadRequestExecutor.java | 22 ++++++++++++++++++- .../util/http/MediaUploadRequestExecutor.java | 20 +++++++++++++++++ .../weixin/common/util/http/RequestHttp.java | 4 ++-- .../util/http/SimpleGetRequestExecutor.java | 20 +++++++++++++++++ .../util/http/SimplePostRequestExecutor.java | 20 +++++++++++++++++ 6 files changed, 88 insertions(+), 3 deletions(-) diff --git a/weixin-java-common/pom.xml b/weixin-java-common/pom.xml index 946c65c2..29c2ec4c 100644 --- a/weixin-java-common/pom.xml +++ b/weixin-java-common/pom.xml @@ -39,6 +39,11 @@ jetty-servlet test + + org.jodd + jodd-http + 3.7 + diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java index a61c54a7..b69438fa 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java @@ -85,6 +85,16 @@ public class MediaDownloadRequestExecutor implements RequestExecutor } + /** + * apache-http实现方式 + * @param httpclient + * @param httpProxy + * @param uri + * @param queryParam + * @return + * @throws WxErrorException + * @throws IOException + */ private String executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String queryParam) throws WxErrorException, IOException { if (queryParam != null) { if (uri.indexOf('?') == -1) { @@ -66,6 +76,16 @@ public class SimpleGetRequestExecutor implements RequestExecutor } + /** + * jodd-http实现方式 + * @param provider + * @param proxyInfo + * @param uri + * @param queryParam + * @return + * @throws WxErrorException + * @throws IOException + */ private String executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, String queryParam) throws WxErrorException, IOException { if (queryParam != null) { if (uri.indexOf('?') == -1) { 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 f35385de..f6873289 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 @@ -42,6 +42,16 @@ public class SimplePostRequestExecutor implements RequestExecutor Date: Sat, 22 Apr 2017 20:28:04 +0800 Subject: [PATCH 11/27] =?UTF-8?q?=E5=B0=91=E6=8F=90=E4=BA=A4=E4=B8=80?= =?UTF-8?q?=E4=B8=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cp/api/impl/jodd/WxCpServiceImpl.java | 686 ++++++++++++++++++ 1 file changed, 686 insertions(+) create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/jodd/WxCpServiceImpl.java diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/jodd/WxCpServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/jodd/WxCpServiceImpl.java new file mode 100644 index 00000000..8c41f042 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/jodd/WxCpServiceImpl.java @@ -0,0 +1,686 @@ +package me.chanjar.weixin.cp.api.impl.jodd; + +import com.google.gson.*; +import com.google.gson.reflect.TypeToken; +import jodd.http.*; +import me.chanjar.weixin.common.bean.WxAccessToken; +import me.chanjar.weixin.common.bean.WxJsapiSignature; +import me.chanjar.weixin.common.bean.menu.WxMenu; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.session.StandardSessionManager; +import me.chanjar.weixin.common.session.WxSession; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.common.util.RandomUtils; +import me.chanjar.weixin.common.util.crypto.SHA1; +import me.chanjar.weixin.common.util.fs.FileUtils; +import me.chanjar.weixin.common.util.http.*; +import me.chanjar.weixin.common.util.json.GsonHelper; +import me.chanjar.weixin.cp.api.WxCpConfigStorage; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.WxCpDepart; +import me.chanjar.weixin.cp.bean.WxCpMessage; +import me.chanjar.weixin.cp.bean.WxCpTag; +import me.chanjar.weixin.cp.bean.WxCpUser; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.UUID; + +public class WxCpServiceImpl implements WxCpService, RequestHttp { + + protected final Logger log = LoggerFactory.getLogger(WxCpServiceImpl.class); + + /** + * 全局的是否正在刷新access token的锁 + */ + protected final Object globalAccessTokenRefreshLock = new Object(); + + /** + * 全局的是否正在刷新jsapi_ticket的锁 + */ + protected final Object globalJsapiTicketRefreshLock = new Object(); + + protected WxCpConfigStorage configStorage; + + protected HttpConnectionProvider httpClient; + + protected ProxyInfo httpProxy; + protected WxSessionManager sessionManager = new StandardSessionManager(); + /** + * 临时文件目录 + */ + protected File tmpDirFile; + private int retrySleepMillis = 1000; + private int maxRetryTimes = 5; + + @Override + public boolean checkSignature(String msgSignature, String timestamp, String nonce, String data) { + try { + return SHA1.gen(this.configStorage.getToken(), timestamp, nonce, data) + .equals(msgSignature); + } catch (Exception e) { + return false; + } + } + + @Override + public void userAuthenticated(String userId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/authsucc?userid=" + userId; + get(url, null); + } + + @Override + public String getAccessToken() throws WxErrorException { + return getAccessToken(false); + } + + @Override + public String getAccessToken(boolean forceRefresh) throws WxErrorException { + if (forceRefresh) { + this.configStorage.expireAccessToken(); + } + if (this.configStorage.isAccessTokenExpired()) { + synchronized (this.globalAccessTokenRefreshLock) { + if (this.configStorage.isAccessTokenExpired()) { + String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?" + + "&corpid=" + this.configStorage.getCorpId() + + "&corpsecret=" + this.configStorage.getCorpSecret(); + + HttpRequest request = HttpRequest.get(url); + if (this.httpProxy != null) { + httpClient.useProxy(this.httpProxy); + } + request.withConnectionProvider(httpClient); + HttpResponse response = request.send(); + + String resultContent = response.bodyText(); + WxError error = WxError.fromJson(resultContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + WxAccessToken accessToken = WxAccessToken.fromJson(resultContent); + this.configStorage.updateAccessToken( + accessToken.getAccessToken(), accessToken.getExpiresIn()); + } + } + } + return this.configStorage.getAccessToken(); + } + + @Override + public String getJsapiTicket() throws WxErrorException { + return getJsapiTicket(false); + } + + @Override + public String getJsapiTicket(boolean forceRefresh) throws WxErrorException { + if (forceRefresh) { + this.configStorage.expireJsapiTicket(); + } + if (this.configStorage.isJsapiTicketExpired()) { + synchronized (this.globalJsapiTicketRefreshLock) { + if (this.configStorage.isJsapiTicketExpired()) { + String url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket"; + String responseContent = execute(new SimpleGetRequestExecutor(), url, null); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); + String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); + int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); + this.configStorage.updateJsapiTicket(jsapiTicket, + expiresInSeconds); + } + } + } + return this.configStorage.getJsapiTicket(); + } + + @Override + public WxJsapiSignature createJsapiSignature(String url) throws WxErrorException { + long timestamp = System.currentTimeMillis() / 1000; + String noncestr = RandomUtils.getRandomStr(); + String jsapiTicket = getJsapiTicket(false); + String signature = SHA1.genWithAmple( + "jsapi_ticket=" + jsapiTicket, + "noncestr=" + noncestr, + "timestamp=" + timestamp, + "url=" + url + ); + WxJsapiSignature jsapiSignature = new WxJsapiSignature(); + jsapiSignature.setTimestamp(timestamp); + jsapiSignature.setNonceStr(noncestr); + jsapiSignature.setUrl(url); + jsapiSignature.setSignature(signature); + + // Fixed bug + jsapiSignature.setAppId(this.configStorage.getCorpId()); + + return jsapiSignature; + } + + @Override + public void messageSend(WxCpMessage message) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/message/send"; + post(url, message.toJson()); + } + + @Override + public void menuCreate(WxMenu menu) throws WxErrorException { + menuCreate(this.configStorage.getAgentId(), menu); + } + + @Override + public void menuCreate(Integer agentId, WxMenu menu) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/create?agentid=" + + this.configStorage.getAgentId(); + post(url, menu.toJson()); + } + + @Override + public void menuDelete() throws WxErrorException { + menuDelete(this.configStorage.getAgentId()); + } + + @Override + public void menuDelete(Integer agentId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/delete?agentid=" + agentId; + get(url, null); + } + + @Override + public WxMenu menuGet() throws WxErrorException { + return menuGet(this.configStorage.getAgentId()); + } + + @Override + public WxMenu menuGet(Integer agentId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/get?agentid=" + agentId; + try { + String resultContent = get(url, null); + return WxMenu.fromJson(resultContent); + } catch (WxErrorException e) { + // 46003 不存在的菜单数据 + if (e.getError().getErrorCode() == 46003) { + return null; + } + throw e; + } + } + + @Override + public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) + throws WxErrorException, IOException { + return mediaUpload(mediaType, FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType)); + } + + @Override + public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?type=" + mediaType; + return execute(new MediaUploadRequestExecutor(), url, file); + } + + @Override + public File mediaDownload(String mediaId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/media/get"; + return execute( + new MediaDownloadRequestExecutor( + this.configStorage.getTmpDirFile()), + url, "media_id=" + mediaId); + } + + + @Override + public Integer departCreate(WxCpDepart depart) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/department/create"; + String responseContent = execute( + new SimplePostRequestExecutor(), + url, + depart.toJson()); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + return GsonHelper.getAsInteger(tmpJsonElement.getAsJsonObject().get("id")); + } + + @Override + public void departUpdate(WxCpDepart group) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/department/update"; + post(url, group.toJson()); + } + + @Override + public void departDelete(Integer departId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/department/delete?id=" + departId; + get(url, null); + } + + @Override + public List departGet() throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/department/list"; + String responseContent = get(url, null); + /* + * 操蛋的微信API,创建时返回的是 { group : { id : ..., name : ...} } + * 查询时返回的是 { groups : [ { id : ..., name : ..., count : ... }, ... ] } + */ + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + return WxCpGsonBuilder.INSTANCE.create() + .fromJson( + tmpJsonElement.getAsJsonObject().get("department"), + new TypeToken>() { + }.getType() + ); + } + + @Override + public void userCreate(WxCpUser user) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/create"; + post(url, user.toJson()); + } + + @Override + public void userUpdate(WxCpUser user) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/update"; + post(url, user.toJson()); + } + + @Override + public void userDelete(String userid) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/delete?userid=" + userid; + get(url, null); + } + + @Override + public void userDelete(String[] userids) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/batchdelete"; + JsonObject jsonObject = new JsonObject(); + JsonArray jsonArray = new JsonArray(); + for (String userid : userids) { + jsonArray.add(new JsonPrimitive(userid)); + } + jsonObject.add("useridlist", jsonArray); + post(url, jsonObject.toString()); + } + + @Override + public WxCpUser userGet(String userid) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/get?userid=" + userid; + String responseContent = get(url, null); + return WxCpUser.fromJson(responseContent); + } + + @Override + public List userList(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/list?department_id=" + departId; + String params = ""; + if (fetchChild != null) { + params += "&fetch_child=" + (fetchChild ? "1" : "0"); + } + if (status != null) { + params += "&status=" + status; + } else { + params += "&status=0"; + } + + String responseContent = get(url, params); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + return WxCpGsonBuilder.INSTANCE.create() + .fromJson( + tmpJsonElement.getAsJsonObject().get("userlist"), + new TypeToken>() { + }.getType() + ); + } + + @Override + public List departGetUsers(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?department_id=" + departId; + String params = ""; + if (fetchChild != null) { + params += "&fetch_child=" + (fetchChild ? "1" : "0"); + } + if (status != null) { + params += "&status=" + status; + } else { + params += "&status=0"; + } + + String responseContent = get(url, params); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + return WxCpGsonBuilder.INSTANCE.create() + .fromJson( + tmpJsonElement.getAsJsonObject().get("userlist"), + new TypeToken>() { + }.getType() + ); + } + + @Override + public String tagCreate(String tagName) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/create"; + JsonObject o = new JsonObject(); + o.addProperty("tagname", tagName); + String responseContent = post(url, o.toString()); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + return tmpJsonElement.getAsJsonObject().get("tagid").getAsString(); + } + + @Override + public void tagUpdate(String tagId, String tagName) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/update"; + JsonObject o = new JsonObject(); + o.addProperty("tagid", tagId); + o.addProperty("tagname", tagName); + post(url, o.toString()); + } + + @Override + public void tagDelete(String tagId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/delete?tagid=" + tagId; + get(url, null); + } + + @Override + public List tagGet() throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/list"; + String responseContent = get(url, null); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + return WxCpGsonBuilder.INSTANCE.create() + .fromJson( + tmpJsonElement.getAsJsonObject().get("taglist"), + new TypeToken>() { + }.getType() + ); + } + + @Override + public List tagGetUsers(String tagId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/get?tagid=" + tagId; + String responseContent = get(url, null); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + return WxCpGsonBuilder.INSTANCE.create() + .fromJson( + tmpJsonElement.getAsJsonObject().get("userlist"), + new TypeToken>() { + }.getType() + ); + } + + @Override + public void tagAddUsers(String tagId, List userIds, List partyIds) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/addtagusers"; + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("tagid", tagId); + if (userIds != null) { + JsonArray jsonArray = new JsonArray(); + for (String userId : userIds) { + jsonArray.add(new JsonPrimitive(userId)); + } + jsonObject.add("userlist", jsonArray); + } + if (partyIds != null) { + JsonArray jsonArray = new JsonArray(); + for (String userId : partyIds) { + jsonArray.add(new JsonPrimitive(userId)); + } + jsonObject.add("partylist", jsonArray); + } + post(url, jsonObject.toString()); + } + + @Override + public void tagRemoveUsers(String tagId, List userIds) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/deltagusers"; + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("tagid", tagId); + JsonArray jsonArray = new JsonArray(); + for (String userId : userIds) { + jsonArray.add(new JsonPrimitive(userId)); + } + jsonObject.add("userlist", jsonArray); + post(url, jsonObject.toString()); + } + + @Override + public String oauth2buildAuthorizationUrl(String state) { + return this.oauth2buildAuthorizationUrl( + this.configStorage.getOauth2redirectUri(), + state + ); + } + + @Override + public String oauth2buildAuthorizationUrl(String redirectUri, String state) { + String url = "https://open.weixin.qq.com/connect/oauth2/authorize?"; + url += "appid=" + this.configStorage.getCorpId(); + url += "&redirect_uri=" + URIUtil.encodeURIComponent(redirectUri); + url += "&response_type=code"; + url += "&scope=snsapi_base"; + if (state != null) { + url += "&state=" + state; + } + url += "#wechat_redirect"; + return url; + } + + @Override + public String[] oauth2getUserInfo(String code) throws WxErrorException { + return oauth2getUserInfo(this.configStorage.getAgentId(), code); + } + + @Override + public String[] oauth2getUserInfo(Integer agentId, String code) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?" + + "code=" + code + + "&agentid=" + agentId; + String responseText = get(url, null); + JsonElement je = new JsonParser().parse(responseText); + JsonObject jo = je.getAsJsonObject(); + return new String[]{GsonHelper.getString(jo, "UserId"), GsonHelper.getString(jo, "DeviceId"), GsonHelper.getString(jo, "OpenId")}; + } + + @Override + public int invite(String userId, String inviteTips) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/invite/send"; + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("userid", userId); + if (StringUtils.isNotEmpty(inviteTips)) { + jsonObject.addProperty("invite_tips", inviteTips); + } + String responseContent = post(url, jsonObject.toString()); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + return tmpJsonElement.getAsJsonObject().get("type").getAsInt(); + } + + @Override + public String[] getCallbackIp() throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/getcallbackip"; + String responseContent = get(url, null); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + JsonArray jsonArray = tmpJsonElement.getAsJsonObject().get("ip_list").getAsJsonArray(); + String[] ips = new String[jsonArray.size()]; + for (int i = 0; i < jsonArray.size(); i++) { + ips[i] = jsonArray.get(i).getAsString(); + } + return ips; + } + + @Override + public String get(String url, String queryParam) throws WxErrorException { + return execute(new SimpleGetRequestExecutor(), url, queryParam); + } + + @Override + public String post(String url, String postData) throws WxErrorException { + return execute(new SimplePostRequestExecutor(), url, postData); + } + + /** + * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 + */ + @Override + public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { + int retryTimes = 0; + do { + try { + T result = this.executeInternal(executor, uri, data); + this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", uri, data, result); + return result; + } catch (WxErrorException e) { + if (retryTimes + 1 > this.maxRetryTimes) { + this.log.warn("重试达到最大次数【{}】", this.maxRetryTimes); + //最后一次重试失败后,直接抛出异常,不再等待 + throw new RuntimeException("微信服务端异常,超出重试次数"); + } + + WxError error = e.getError(); + /* + * -1 系统繁忙, 1000ms后重试 + */ + if (error.getErrorCode() == -1) { + int sleepMillis = this.retrySleepMillis * (1 << retryTimes); + try { + this.log.debug("微信系统繁忙,{} ms 后重试(第{}次)", sleepMillis, retryTimes + 1); + Thread.sleep(sleepMillis); + } catch (InterruptedException e1) { + throw new RuntimeException(e1); + } + } else { + throw e; + } + } + } while (retryTimes++ < this.maxRetryTimes); + + this.log.warn("重试达到最大次数【{}】", this.maxRetryTimes); + throw new RuntimeException("微信服务端异常,超出重试次数"); + } + + + public synchronized T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { + if (uri.contains("access_token=")) { + throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); + } + String accessToken = getAccessToken(false); + + String uriWithAccessToken = uri; + uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken; + + try { + return executor.execute(this, uriWithAccessToken, data); + } catch (WxErrorException e) { + WxError error = e.getError(); + /* + * 发生以下情况时尝试刷新access_token + * 40001 获取access_token时AppSecret错误,或者access_token无效 + * 42001 access_token超时 + */ + if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) { + // 强制设置wxCpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token + this.configStorage.expireAccessToken(); + return execute(executor, uri, data); + } + + if (error.getErrorCode() != 0) { + this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", uri, data, error); + throw new WxErrorException(error); + } + return null; + } catch (IOException e) { + this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[EXCEPTION]: {}", uri, data, e.getMessage()); + throw new RuntimeException(e); + } + } + + protected HttpConnectionProvider getHttpclient() { + return this.httpClient; + } + + @Override + public void setWxCpConfigStorage(WxCpConfigStorage wxConfigProvider) { + this.configStorage = wxConfigProvider; + + if (this.configStorage.getHttpProxyHost() != null && this.configStorage.getHttpProxyPort() > 0) { + httpProxy = new ProxyInfo(ProxyInfo.ProxyType.HTTP, configStorage.getHttpProxyHost(), configStorage.getHttpProxyPort(), configStorage.getHttpProxyUsername(), configStorage.getHttpProxyPassword()); + } + + httpClient = JoddHttp.httpConnectionProvider; + } + + @Override + public void setRetrySleepMillis(int retrySleepMillis) { + this.retrySleepMillis = retrySleepMillis; + } + + + @Override + public void setMaxRetryTimes(int maxRetryTimes) { + this.maxRetryTimes = maxRetryTimes; + } + + @Override + public WxSession getSession(String id) { + if (this.sessionManager == null) { + return null; + } + return this.sessionManager.getSession(id); + } + + @Override + public WxSession getSession(String id, boolean create) { + if (this.sessionManager == null) { + return null; + } + return this.sessionManager.getSession(id, create); + } + + + @Override + public void setSessionManager(WxSessionManager sessionManager) { + this.sessionManager = sessionManager; + } + + @Override + public String replaceParty(String mediaId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/replaceparty"; + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("media_id", mediaId); + return post(url, jsonObject.toString()); + } + + @Override + public String replaceUser(String mediaId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/replaceuser"; + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("media_id", mediaId); + return post(url, jsonObject.toString()); + } + + @Override + public String getTaskResult(String joinId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/getresult?jobid=" + joinId; + return get(url, null); + } + + public File getTmpDirFile() { + return this.tmpDirFile; + } + + public void setTmpDirFile(File tmpDirFile) { + this.tmpDirFile = tmpDirFile; + } + + + @Override + public Object getRequestHttpClient() { + return this.httpClient; + } + + @Override + public Object getRequestHttpProxy() { + return this.httpProxy; + } +} From 2019115b677a1288c55a94d244214ff5c3e44342 Mon Sep 17 00:00:00 2001 From: ecoolper Date: Sat, 22 Apr 2017 20:29:21 +0800 Subject: [PATCH 12/27] =?UTF-8?q?gradle=E9=85=8D=E7=BD=AE=E4=BF=A1?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- settings.gradle | 4 +++- weixin-java-pay/build.gradle | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 weixin-java-pay/build.gradle diff --git a/settings.gradle b/settings.gradle index 1c0e0214..0ff1d35b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,7 +2,9 @@ rootProject.name = 'weixin-java-parent' include ':weixin-java-common' include ':weixin-java-cp' include ':weixin-java-mp' +include ':weixin-java-pay' project(':weixin-java-common').projectDir = "$rootDir/weixin-java-common" as File project(':weixin-java-cp').projectDir = "$rootDir/weixin-java-cp" as File -project(':weixin-java-mp').projectDir = "$rootDir/weixin-java-mp" as File \ No newline at end of file +project(':weixin-java-mp').projectDir = "$rootDir/weixin-java-mp" as File +project(':weixin-java-pay').projectDir = "$rootDir/weixin-java-pay" as File diff --git a/weixin-java-pay/build.gradle b/weixin-java-pay/build.gradle new file mode 100644 index 00000000..2f0c7e9a --- /dev/null +++ b/weixin-java-pay/build.gradle @@ -0,0 +1,12 @@ +description = 'WeiXin Java Tools - PAY' +dependencies { + compile project(':weixin-java-common') + testCompile group: 'junit', name: 'junit', version: '4.11' + testCompile group: 'org.testng', name: 'testng', version: '6.8.7' + testCompile group: 'org.mockito', name: 'mockito-all', version: '1.9.5' + testCompile group: 'com.google.inject', name: 'guice', version: '3.0' + testCompile group: 'org.eclipse.jetty', name: 'jetty-server', version: '9.3.0.RC0' + testCompile group: 'org.eclipse.jetty', name: 'jetty-servlet', version: '9.3.0.RC0' + testCompile group: 'joda-time', name: 'joda-time', version: '2.9.4' +} +test.useTestNG() From dbf0a1505bc304db231a9e4466870d6d8dd97aef Mon Sep 17 00:00:00 2001 From: ecoolper Date: Mon, 24 Apr 2017 23:18:08 +0800 Subject: [PATCH 13/27] =?UTF-8?q?weixin-java-parent=20pom.xml=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0jodd-http?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pom.xml b/pom.xml index 2447fd71..c185f037 100644 --- a/pom.xml +++ b/pom.xml @@ -110,6 +110,17 @@ + + org.jodd + jodd-http + 3.7 + + + + com.squareup.okhttp3 + okhttp + 3.7.0 + org.slf4j slf4j-api From 49f9787e98d5c551811fa6308952b2fb8d0113cd Mon Sep 17 00:00:00 2001 From: ecoolper Date: Thu, 27 Apr 2017 18:27:01 +0800 Subject: [PATCH 14/27] =?UTF-8?q?1=E3=80=81=E6=8F=90=E5=8F=96=E4=BA=86?= =?UTF-8?q?=E5=85=AC=E5=85=B1=E4=BB=A3=E7=A0=81=EF=BC=8C=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?AbstractWxMPService=E3=80=81AbstractWxCPService=E7=B1=BB=202?= =?UTF-8?q?=E3=80=81=E5=AE=9E=E7=8E=B0=E4=BA=86okhttp=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=203=E3=80=81RequestExecute=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0executeApache=E3=80=81executeJodd=E3=80=81exe?= =?UTF-8?q?cuteOkhttp=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- weixin-java-common/pom.xml | 5 - .../util/http/AbstractRequestExecutor.java | 43 +++++++ .../http/MediaDownloadRequestExecutor.java | 116 +++++++++++++---- .../util/http/MediaUploadRequestExecutor.java | 76 ++++++++---- .../common/util/http/RequestExecutor.java | 44 +++++++ .../weixin/common/util/http/RequestHttp.java | 6 +- .../util/http/SimpleGetRequestExecutor.java | 81 ++++++++---- .../util/http/SimplePostRequestExecutor.java | 74 ++++++++--- .../util/http/okhttp/OkhttpProxyInfo.java | 117 ++++++++++++++++++ 9 files changed, 464 insertions(+), 98 deletions(-) create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/AbstractRequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkhttpProxyInfo.java diff --git a/weixin-java-common/pom.xml b/weixin-java-common/pom.xml index 29c2ec4c..946c65c2 100644 --- a/weixin-java-common/pom.xml +++ b/weixin-java-common/pom.xml @@ -39,11 +39,6 @@ jetty-servlet test - - org.jodd - jodd-http - 3.7 - diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/AbstractRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/AbstractRequestExecutor.java new file mode 100644 index 00000000..23881e66 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/AbstractRequestExecutor.java @@ -0,0 +1,43 @@ +package me.chanjar.weixin.common.util.http; + +import java.io.IOException; + +import org.apache.http.HttpHost; +import org.apache.http.impl.client.CloseableHttpClient; + +import jodd.http.HttpConnectionProvider; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; +import okhttp3.ConnectionPool; + +/** + * Created by ecoolper on 2017/4/27. + */ +public abstract class AbstractRequestExecutor implements RequestExecutor { + + @Override + public T execute(RequestHttp requestHttp, String uri, E data) throws WxErrorException, IOException{ + if (requestHttp.getRequestHttpClient() instanceof CloseableHttpClient) { + //apache-http请求 + CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getRequestHttpClient(); + HttpHost httpProxy = (HttpHost) requestHttp.getRequestHttpProxy(); + return executeApache(httpClient, httpProxy, uri, data); + } + if (requestHttp.getRequestHttpClient() instanceof HttpConnectionProvider) { + //jodd-http请求 + HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getRequestHttpClient(); + ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getRequestHttpProxy(); + return executeJodd(provider, proxyInfo, uri, data); + } else if (requestHttp.getRequestHttpClient() instanceof ConnectionPool) { + //okhttp请求 + ConnectionPool pool = (ConnectionPool) requestHttp.getRequestHttpClient(); + OkhttpProxyInfo proxyInfo = (OkhttpProxyInfo) requestHttp.getRequestHttpProxy(); + return executeOkhttp(pool, proxyInfo, uri, data); + } else { + //TODO 这里需要抛出异常,需要优化 + return null; + } + } + +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java index b69438fa..e95f02de 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java @@ -5,10 +5,14 @@ import jodd.http.HttpRequest; import jodd.http.HttpResponse; import jodd.http.ProxyInfo; import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.fs.FileUtils; import me.chanjar.weixin.common.util.http.apache.InputStreamResponseHandler; import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; +import okhttp3.*; + import org.apache.commons.lang3.StringUtils; import org.apache.http.Header; import org.apache.http.HttpHost; @@ -22,6 +26,8 @@ import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.net.InetSocketAddress; +import java.net.Proxy; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -31,7 +37,7 @@ import java.util.regex.Pattern; * * @author Daniel Qian */ -public class MediaDownloadRequestExecutor implements RequestExecutor { +public class MediaDownloadRequestExecutor extends AbstractRequestExecutor { private File tmpDirFile; @@ -39,24 +45,7 @@ public class MediaDownloadRequestExecutor implements RequestExecutor 0) { if (contentTypeHeader[0].getValue().startsWith(ContentType.APPLICATION_JSON.getMimeType())) { @@ -122,7 +111,7 @@ public class MediaDownloadRequestExecutor implements RequestExecutor { - - @Override - public WxMediaUploadResult execute(RequestHttp requestHttp, String uri, File file) throws WxErrorException, IOException { - if (requestHttp.getRequestHttpClient() instanceof CloseableHttpClient) { - CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getRequestHttpClient(); - HttpHost httpProxy = (HttpHost) requestHttp.getRequestHttpProxy(); - return executeApache(httpClient, httpProxy, uri, file); - } - if (requestHttp.getRequestHttpClient() instanceof HttpConnectionProvider) { - HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getRequestHttpClient(); - ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getRequestHttpProxy(); - return executeJodd(provider, proxyInfo, uri, file); - } else { - //这里需要抛出异常,需要优化 - return null; - } - - - } +public class MediaUploadRequestExecutor extends AbstractRequestExecutor { /** * apache-http实现方式 + * * @param httpclient * @param httpProxy * @param uri @@ -57,7 +44,7 @@ public class MediaUploadRequestExecutor implements RequestExecutor { */ T execute(RequestHttp requestHttp, String uri, E data) throws WxErrorException, IOException; + /** + * apache-http实现方式 + * @param httpclient + * @param httpProxy + * @param uri + * @param data + * @return + * @throws WxErrorException + * @throws IOException + */ + T executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, E data) throws WxErrorException, IOException; + + /** + * jodd-http实现方式 + * @param provider + * @param proxyInfo + * @param uri + * @param data + * @return + * @throws WxErrorException + * @throws IOException + */ + T executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, E data) throws WxErrorException, IOException; + + + /** okhttp实现方式 + * @param pool + * @param proxyInfo + * @param uri + * @param data + * @return + * @throws WxErrorException + * @throws IOException + */ + T executeOkhttp(ConnectionPool pool, final OkhttpProxyInfo proxyInfo, String uri, E data) throws WxErrorException, IOException; + + } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestHttp.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestHttp.java index 02225d46..5af68e07 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestHttp.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestHttp.java @@ -3,18 +3,18 @@ package me.chanjar.weixin.common.util.http; /** * Created by ecoolper on 2017/4/22. */ -public interface RequestHttp { +public interface RequestHttp { /** * 返回httpClient * @return */ - Object getRequestHttpClient(); + H getRequestHttpClient(); /** * 返回httpProxy * @return */ - Object getRequestHttpProxy(); + P getRequestHttpProxy(); } 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 cb414d2b..50beb29f 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 @@ -7,6 +7,9 @@ import jodd.http.ProxyInfo; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; +import okhttp3.*; + import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; @@ -14,34 +17,20 @@ import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.util.concurrent.TimeUnit; /** * 简单的GET请求执行器,请求的参数是String, 返回的结果也是String * * @author Daniel Qian */ -public class SimpleGetRequestExecutor implements RequestExecutor { - - @Override - public String execute(RequestHttp requestHttp, String uri, String queryParam) throws WxErrorException, IOException { - if (requestHttp.getRequestHttpClient() instanceof CloseableHttpClient) { - CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getRequestHttpClient(); - HttpHost httpProxy = (HttpHost) requestHttp.getRequestHttpProxy(); - return executeApache(httpClient, httpProxy, uri, queryParam); - } - if (requestHttp.getRequestHttpClient() instanceof HttpConnectionProvider) { - HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getRequestHttpClient(); - ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getRequestHttpProxy(); - return executeJodd(provider, proxyInfo, uri, queryParam); - } else { - //这里需要抛出异常,需要优化 - return null; - } - } - +public class SimpleGetRequestExecutor extends AbstractRequestExecutor { /** * apache-http实现方式 + * * @param httpclient * @param httpProxy * @param uri @@ -50,7 +39,7 @@ public class SimpleGetRequestExecutor implements RequestExecutor * @throws WxErrorException * @throws IOException */ - private String executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String queryParam) throws WxErrorException, IOException { + public String executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String queryParam) throws WxErrorException, IOException { if (queryParam != null) { if (uri.indexOf('?') == -1) { uri += '?'; @@ -78,6 +67,7 @@ public class SimpleGetRequestExecutor implements RequestExecutor /** * jodd-http实现方式 + * * @param provider * @param proxyInfo * @param uri @@ -86,7 +76,7 @@ public class SimpleGetRequestExecutor implements RequestExecutor * @throws WxErrorException * @throws IOException */ - private String executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, String queryParam) throws WxErrorException, IOException { + public String executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, String queryParam) throws WxErrorException, IOException { if (queryParam != null) { if (uri.indexOf('?') == -1) { uri += '?'; @@ -108,4 +98,53 @@ public class SimpleGetRequestExecutor implements RequestExecutor return responseContent; } + /** + * okHttp实现方式 + * + * @param pool + * @param proxyInfo + * @param uri + * @param queryParam + * @return + * @throws WxErrorException + * @throws IOException + */ + public String executeOkhttp(ConnectionPool pool, final OkhttpProxyInfo proxyInfo, String uri, String queryParam) throws WxErrorException, IOException { + if (queryParam != null) { + if (uri.indexOf('?') == -1) { + uri += '?'; + } + uri += uri.endsWith("?") ? queryParam : '&' + queryParam; + } + + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(pool); + //设置代理 + if (proxyInfo != null) { + clientBuilder.proxy(proxyInfo.getProxy()); + } + //设置授权 + clientBuilder.authenticator(new Authenticator() { + @Override + public Request authenticate(Route route, Response response) throws IOException { + String credential = Credentials.basic(proxyInfo.getProxyUsername(), proxyInfo.getProxyPassword()); + return response.request().newBuilder() + .header("Authorization", credential) + .build(); + } + }); + //得到httpClient + OkHttpClient client =clientBuilder.build(); + + Request request = new Request.Builder().url(uri).build(); + + Response response = client.newCall(request).execute(); + String responseContent = response.body().toString(); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return responseContent; + } + + } 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 f6873289..28ca7cb7 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 @@ -7,6 +7,9 @@ import jodd.http.ProxyInfo; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; +import okhttp3.*; + import org.apache.http.Consts; import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; @@ -23,27 +26,11 @@ import java.io.IOException; * * @author Daniel Qian */ -public class SimplePostRequestExecutor implements RequestExecutor { - - @Override - public String execute(RequestHttp requestHttp, String uri, String postEntity) throws WxErrorException, IOException { - if (requestHttp.getRequestHttpClient() instanceof CloseableHttpClient) { - CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getRequestHttpClient(); - HttpHost httpProxy = (HttpHost) requestHttp.getRequestHttpProxy(); - return executeApache(httpClient, httpProxy, uri, postEntity); - } - if (requestHttp.getRequestHttpClient() instanceof HttpConnectionProvider) { - HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getRequestHttpClient(); - ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getRequestHttpProxy(); - return executeJodd(provider, proxyInfo, uri, postEntity); - } else { - //这里需要抛出异常,需要优化 - return null; - } - } +public class SimplePostRequestExecutor extends AbstractRequestExecutor { /** * apache-http实现方式 + * * @param httpclient * @param httpProxy * @param uri @@ -52,7 +39,7 @@ public class SimplePostRequestExecutor implements RequestExecutornull if + * no authentication required. + */ + public String getProxyUsername() { + return proxyUsername; + } + + /** + * Returns proxy password or null. + */ + public String getProxyPassword() { + return proxyPassword; + } + + /** + * 返回 java.net.Proxy + * @return + */ + public Proxy getProxy() { + Proxy proxy = null; + if (getProxyType().equals(ProxyType.SOCKS5)) { + proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(getProxyAddress(), getProxyPort())); + } else if (getProxyType().equals(ProxyType.SOCKS4)) { + proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(getProxyAddress(), getProxyPort())); + } else if (getProxyType().equals(ProxyType.HTTP)) { + proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(getProxyAddress(), getProxyPort())); + } else if (getProxyType().equals(ProxyType.NONE)) { + proxy = new Proxy(Proxy.Type.DIRECT, new InetSocketAddress(getProxyAddress(), getProxyPort())); + } + return proxy; + } +} From ffa3544579b7cd471aac6bab4b98b60630946efc Mon Sep 17 00:00:00 2001 From: ecoolper Date: Thu, 27 Apr 2017 18:38:14 +0800 Subject: [PATCH 15/27] =?UTF-8?q?1=E3=80=81=E6=8F=90=E5=8F=96=E4=BA=86?= =?UTF-8?q?=E5=85=AC=E5=85=B1=E4=BB=A3=E7=A0=81=EF=BC=8C=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?AbstractWxMPService=E3=80=81AbstractWxCPService=E7=B1=BB=202?= =?UTF-8?q?=E3=80=81=E5=AE=9E=E7=8E=B0=E4=BA=86okhttp=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=203=E3=80=81RequestExecute=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0executeApache=E3=80=81executeJodd=E3=80=81exe?= =?UTF-8?q?cuteOkhttp=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 5 +- .../me/chanjar/weixin/cp/api/WxCpService.java | 5 + .../cp/api/impl/AbstractWxCpService.java | 632 +++++++++++++++++ .../cp/api/impl/apache/WxCpServiceImpl.java | 636 +----------------- .../cp/api/impl/jodd/WxCpServiceImpl.java | 635 +---------------- .../cp/api/impl/okhttp/WxCpServiceImpl.java | 90 +++ .../me/chanjar/weixin/mp/api/WxMpService.java | 8 +- .../mp/api/impl/AbstractWxMpService.java | 445 ++++++++++++ .../mp/api/impl/apache/WxMpServiceImpl.java | 518 ++------------ .../mp/api/impl/jodd/WxMpServiceImpl.java | 474 +------------ .../mp/api/impl/okhttp/WxMpServiceImpl.java | 96 +++ .../http/MaterialDeleteRequestExecutor.java | 89 ++- .../http/MaterialNewsInfoRequestExecutor.java | 60 +- .../http/MaterialUploadRequestExecutor.java | 76 ++- .../MaterialVideoInfoRequestExecutor.java | 63 +- ...lVoiceAndImageDownloadRequestExecutor.java | 74 +- .../http/MediaImgUploadRequestExecutor.java | 72 +- .../mp/util/http/QrCodeRequestExecutor.java | 66 +- .../weixin/mp/api/WxMpBusyRetryTest.java | 4 +- .../weixin/mp/api/test/ApiTestModule.java | 3 +- .../weixin/mp/demo/WxMpDemoServer.java | 4 +- weixin-java-pay/pom.xml | 7 - 22 files changed, 1693 insertions(+), 2369 deletions(-) create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/AbstractWxCpService.java create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/okhttp/WxCpServiceImpl.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/AbstractWxMpService.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/okhttp/WxMpServiceImpl.java diff --git a/pom.xml b/pom.xml index c185f037..b93c50ec 100644 --- a/pom.xml +++ b/pom.xml @@ -107,14 +107,15 @@ 1.10 9.3.0.RC0 2.9.0 + + 3.7 org.jodd jodd-http - 3.7 - + ${jodd-http.version} com.squareup.okhttp3 diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java index faa01d09..4b15fdb1 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java @@ -551,4 +551,9 @@ public interface WxCpService { * 获取异步任务结果 */ String getTaskResult(String joinId) throws WxErrorException; + + /** + * 初始化http请求对象 + */ + void initHttp(); } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/AbstractWxCpService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/AbstractWxCpService.java new file mode 100644 index 00000000..82fcdef9 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/AbstractWxCpService.java @@ -0,0 +1,632 @@ +package me.chanjar.weixin.cp.api.impl; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.UUID; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.*; +import com.google.gson.reflect.TypeToken; + +import me.chanjar.weixin.common.bean.WxJsapiSignature; +import me.chanjar.weixin.common.bean.menu.WxMenu; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.session.StandardSessionManager; +import me.chanjar.weixin.common.session.WxSession; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.common.util.RandomUtils; +import me.chanjar.weixin.common.util.crypto.SHA1; +import me.chanjar.weixin.common.util.fs.FileUtils; +import me.chanjar.weixin.common.util.http.*; +import me.chanjar.weixin.common.util.json.GsonHelper; +import me.chanjar.weixin.cp.api.WxCpConfigStorage; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.WxCpDepart; +import me.chanjar.weixin.cp.bean.WxCpMessage; +import me.chanjar.weixin.cp.bean.WxCpTag; +import me.chanjar.weixin.cp.bean.WxCpUser; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +public abstract class AbstractWxCpService implements WxCpService, RequestHttp { + + protected final Logger log = LoggerFactory.getLogger(AbstractWxCpService.class); + + /** + * 全局的是否正在刷新access token的锁 + */ + protected final Object globalAccessTokenRefreshLock = new Object(); + + /** + * 全局的是否正在刷新jsapi_ticket的锁 + */ + protected final Object globalJsapiTicketRefreshLock = new Object(); + + protected WxCpConfigStorage configStorage; + + + protected WxSessionManager sessionManager = new StandardSessionManager(); + /** + * 临时文件目录 + */ + protected File tmpDirFile; + private int retrySleepMillis = 1000; + private int maxRetryTimes = 5; + + @Override + public boolean checkSignature(String msgSignature, String timestamp, String nonce, String data) { + try { + return SHA1.gen(this.configStorage.getToken(), timestamp, nonce, data) + .equals(msgSignature); + } catch (Exception e) { + return false; + } + } + + @Override + public void userAuthenticated(String userId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/authsucc?userid=" + userId; + get(url, null); + } + + @Override + public String getAccessToken() throws WxErrorException { + return getAccessToken(false); + } + + + @Override + public String getJsapiTicket() throws WxErrorException { + return getJsapiTicket(false); + } + + @Override + public String getJsapiTicket(boolean forceRefresh) throws WxErrorException { + if (forceRefresh) { + this.configStorage.expireJsapiTicket(); + } + if (this.configStorage.isJsapiTicketExpired()) { + synchronized (this.globalJsapiTicketRefreshLock) { + if (this.configStorage.isJsapiTicketExpired()) { + String url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket"; + String responseContent = execute(new SimpleGetRequestExecutor(), url, null); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); + String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); + int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); + this.configStorage.updateJsapiTicket(jsapiTicket, + expiresInSeconds); + } + } + } + return this.configStorage.getJsapiTicket(); + } + + @Override + public WxJsapiSignature createJsapiSignature(String url) throws WxErrorException { + long timestamp = System.currentTimeMillis() / 1000; + String noncestr = RandomUtils.getRandomStr(); + String jsapiTicket = getJsapiTicket(false); + String signature = SHA1.genWithAmple( + "jsapi_ticket=" + jsapiTicket, + "noncestr=" + noncestr, + "timestamp=" + timestamp, + "url=" + url + ); + WxJsapiSignature jsapiSignature = new WxJsapiSignature(); + jsapiSignature.setTimestamp(timestamp); + jsapiSignature.setNonceStr(noncestr); + jsapiSignature.setUrl(url); + jsapiSignature.setSignature(signature); + + // Fixed bug + jsapiSignature.setAppId(this.configStorage.getCorpId()); + + return jsapiSignature; + } + + @Override + public void messageSend(WxCpMessage message) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/message/send"; + post(url, message.toJson()); + } + + @Override + public void menuCreate(WxMenu menu) throws WxErrorException { + menuCreate(this.configStorage.getAgentId(), menu); + } + + @Override + public void menuCreate(Integer agentId, WxMenu menu) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/create?agentid=" + + this.configStorage.getAgentId(); + post(url, menu.toJson()); + } + + @Override + public void menuDelete() throws WxErrorException { + menuDelete(this.configStorage.getAgentId()); + } + + @Override + public void menuDelete(Integer agentId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/delete?agentid=" + agentId; + get(url, null); + } + + @Override + public WxMenu menuGet() throws WxErrorException { + return menuGet(this.configStorage.getAgentId()); + } + + @Override + public WxMenu menuGet(Integer agentId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/get?agentid=" + agentId; + try { + String resultContent = get(url, null); + return WxMenu.fromJson(resultContent); + } catch (WxErrorException e) { + // 46003 不存在的菜单数据 + if (e.getError().getErrorCode() == 46003) { + return null; + } + throw e; + } + } + + @Override + public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) + throws WxErrorException, IOException { + return mediaUpload(mediaType, FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType)); + } + + @Override + public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?type=" + mediaType; + return execute(new MediaUploadRequestExecutor(), url, file); + } + + @Override + public File mediaDownload(String mediaId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/media/get"; + return execute( + new MediaDownloadRequestExecutor( + this.configStorage.getTmpDirFile()), + url, "media_id=" + mediaId); + } + + + @Override + public Integer departCreate(WxCpDepart depart) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/department/create"; + String responseContent = execute( + new SimplePostRequestExecutor(), + url, + depart.toJson()); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + return GsonHelper.getAsInteger(tmpJsonElement.getAsJsonObject().get("id")); + } + + @Override + public void departUpdate(WxCpDepart group) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/department/update"; + post(url, group.toJson()); + } + + @Override + public void departDelete(Integer departId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/department/delete?id=" + departId; + get(url, null); + } + + @Override + public List departGet() throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/department/list"; + String responseContent = get(url, null); + /* + * 操蛋的微信API,创建时返回的是 { group : { id : ..., name : ...} } + * 查询时返回的是 { groups : [ { id : ..., name : ..., count : ... }, ... ] } + */ + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + return WxCpGsonBuilder.INSTANCE.create() + .fromJson( + tmpJsonElement.getAsJsonObject().get("department"), + new TypeToken>() { + }.getType() + ); + } + + @Override + public void userCreate(WxCpUser user) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/create"; + post(url, user.toJson()); + } + + @Override + public void userUpdate(WxCpUser user) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/update"; + post(url, user.toJson()); + } + + @Override + public void userDelete(String userid) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/delete?userid=" + userid; + get(url, null); + } + + @Override + public void userDelete(String[] userids) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/batchdelete"; + JsonObject jsonObject = new JsonObject(); + JsonArray jsonArray = new JsonArray(); + for (String userid : userids) { + jsonArray.add(new JsonPrimitive(userid)); + } + jsonObject.add("useridlist", jsonArray); + post(url, jsonObject.toString()); + } + + @Override + public WxCpUser userGet(String userid) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/get?userid=" + userid; + String responseContent = get(url, null); + return WxCpUser.fromJson(responseContent); + } + + @Override + public List userList(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/list?department_id=" + departId; + String params = ""; + if (fetchChild != null) { + params += "&fetch_child=" + (fetchChild ? "1" : "0"); + } + if (status != null) { + params += "&status=" + status; + } else { + params += "&status=0"; + } + + String responseContent = get(url, params); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + return WxCpGsonBuilder.INSTANCE.create() + .fromJson( + tmpJsonElement.getAsJsonObject().get("userlist"), + new TypeToken>() { + }.getType() + ); + } + + @Override + public List departGetUsers(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?department_id=" + departId; + String params = ""; + if (fetchChild != null) { + params += "&fetch_child=" + (fetchChild ? "1" : "0"); + } + if (status != null) { + params += "&status=" + status; + } else { + params += "&status=0"; + } + + String responseContent = get(url, params); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + return WxCpGsonBuilder.INSTANCE.create() + .fromJson( + tmpJsonElement.getAsJsonObject().get("userlist"), + new TypeToken>() { + }.getType() + ); + } + + @Override + public String tagCreate(String tagName) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/create"; + JsonObject o = new JsonObject(); + o.addProperty("tagname", tagName); + String responseContent = post(url, o.toString()); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + return tmpJsonElement.getAsJsonObject().get("tagid").getAsString(); + } + + @Override + public void tagUpdate(String tagId, String tagName) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/update"; + JsonObject o = new JsonObject(); + o.addProperty("tagid", tagId); + o.addProperty("tagname", tagName); + post(url, o.toString()); + } + + @Override + public void tagDelete(String tagId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/delete?tagid=" + tagId; + get(url, null); + } + + @Override + public List tagGet() throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/list"; + String responseContent = get(url, null); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + return WxCpGsonBuilder.INSTANCE.create() + .fromJson( + tmpJsonElement.getAsJsonObject().get("taglist"), + new TypeToken>() { + }.getType() + ); + } + + @Override + public List tagGetUsers(String tagId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/get?tagid=" + tagId; + String responseContent = get(url, null); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + return WxCpGsonBuilder.INSTANCE.create() + .fromJson( + tmpJsonElement.getAsJsonObject().get("userlist"), + new TypeToken>() { + }.getType() + ); + } + + @Override + public void tagAddUsers(String tagId, List userIds, List partyIds) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/addtagusers"; + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("tagid", tagId); + if (userIds != null) { + JsonArray jsonArray = new JsonArray(); + for (String userId : userIds) { + jsonArray.add(new JsonPrimitive(userId)); + } + jsonObject.add("userlist", jsonArray); + } + if (partyIds != null) { + JsonArray jsonArray = new JsonArray(); + for (String userId : partyIds) { + jsonArray.add(new JsonPrimitive(userId)); + } + jsonObject.add("partylist", jsonArray); + } + post(url, jsonObject.toString()); + } + + @Override + public void tagRemoveUsers(String tagId, List userIds) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/deltagusers"; + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("tagid", tagId); + JsonArray jsonArray = new JsonArray(); + for (String userId : userIds) { + jsonArray.add(new JsonPrimitive(userId)); + } + jsonObject.add("userlist", jsonArray); + post(url, jsonObject.toString()); + } + + @Override + public String oauth2buildAuthorizationUrl(String state) { + return this.oauth2buildAuthorizationUrl( + this.configStorage.getOauth2redirectUri(), + state + ); + } + + @Override + public String oauth2buildAuthorizationUrl(String redirectUri, String state) { + String url = "https://open.weixin.qq.com/connect/oauth2/authorize?"; + url += "appid=" + this.configStorage.getCorpId(); + url += "&redirect_uri=" + URIUtil.encodeURIComponent(redirectUri); + url += "&response_type=code"; + url += "&scope=snsapi_base"; + if (state != null) { + url += "&state=" + state; + } + url += "#wechat_redirect"; + return url; + } + + @Override + public String[] oauth2getUserInfo(String code) throws WxErrorException { + return oauth2getUserInfo(this.configStorage.getAgentId(), code); + } + + @Override + public String[] oauth2getUserInfo(Integer agentId, String code) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?" + + "code=" + code + + "&agentid=" + agentId; + String responseText = get(url, null); + JsonElement je = new JsonParser().parse(responseText); + JsonObject jo = je.getAsJsonObject(); + return new String[]{GsonHelper.getString(jo, "UserId"), GsonHelper.getString(jo, "DeviceId"), GsonHelper.getString(jo, "OpenId")}; + } + + @Override + public int invite(String userId, String inviteTips) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/invite/send"; + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("userid", userId); + if (StringUtils.isNotEmpty(inviteTips)) { + jsonObject.addProperty("invite_tips", inviteTips); + } + String responseContent = post(url, jsonObject.toString()); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + return tmpJsonElement.getAsJsonObject().get("type").getAsInt(); + } + + @Override + public String[] getCallbackIp() throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/getcallbackip"; + String responseContent = get(url, null); + JsonElement tmpJsonElement = new JsonParser().parse(responseContent); + JsonArray jsonArray = tmpJsonElement.getAsJsonObject().get("ip_list").getAsJsonArray(); + String[] ips = new String[jsonArray.size()]; + for (int i = 0; i < jsonArray.size(); i++) { + ips[i] = jsonArray.get(i).getAsString(); + } + return ips; + } + + @Override + public String get(String url, String queryParam) throws WxErrorException { + return execute(new SimpleGetRequestExecutor(), url, queryParam); + } + + @Override + public String post(String url, String postData) throws WxErrorException { + return execute(new SimplePostRequestExecutor(), url, postData); + } + + /** + * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 + */ + @Override + public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { + int retryTimes = 0; + do { + try { + T result = this.executeInternal(executor, uri, data); + this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}",uri, data, result); + return result; + } catch (WxErrorException e) { + if (retryTimes + 1 > this.maxRetryTimes) { + this.log.warn("重试达到最大次数【{}】", this.maxRetryTimes); + //最后一次重试失败后,直接抛出异常,不再等待 + throw new RuntimeException("微信服务端异常,超出重试次数"); + } + + WxError error = e.getError(); + /* + * -1 系统繁忙, 1000ms后重试 + */ + if (error.getErrorCode() == -1) { + int sleepMillis = this.retrySleepMillis * (1 << retryTimes); + try { + this.log.debug("微信系统繁忙,{} ms 后重试(第{}次)", sleepMillis, retryTimes + 1); + Thread.sleep(sleepMillis); + } catch (InterruptedException e1) { + throw new RuntimeException(e1); + } + } else { + throw e; + } + } + } while (retryTimes++ < this.maxRetryTimes); + + this.log.warn("重试达到最大次数【{}】", this.maxRetryTimes); + throw new RuntimeException("微信服务端异常,超出重试次数"); + } + + public synchronized T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { + if (uri.contains("access_token=")) { + throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); + } + String accessToken = getAccessToken(false); + + String uriWithAccessToken = uri; + uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken; + + try { + return executor.execute(this, uriWithAccessToken, data); + } catch (WxErrorException e) { + WxError error = e.getError(); + /* + * 发生以下情况时尝试刷新access_token + * 40001 获取access_token时AppSecret错误,或者access_token无效 + * 42001 access_token超时 + */ + if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) { + // 强制设置wxCpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token + this.configStorage.expireAccessToken(); + return execute(executor, uri, data); + } + + if (error.getErrorCode() != 0) { + this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", uri, data, error); + throw new WxErrorException(error); + } + return null; + } catch (IOException e) { + this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[EXCEPTION]: {}", uri, data, e.getMessage()); + throw new RuntimeException(e); + } + } + + @Override + public void setWxCpConfigStorage(WxCpConfigStorage wxConfigProvider) { + this.configStorage = wxConfigProvider; + this.initHttp(); + } + + @Override + public void setRetrySleepMillis(int retrySleepMillis) { + this.retrySleepMillis = retrySleepMillis; + } + + + @Override + public void setMaxRetryTimes(int maxRetryTimes) { + this.maxRetryTimes = maxRetryTimes; + } + + @Override + public WxSession getSession(String id) { + if (this.sessionManager == null) { + return null; + } + return this.sessionManager.getSession(id); + } + + @Override + public WxSession getSession(String id, boolean create) { + if (this.sessionManager == null) { + return null; + } + return this.sessionManager.getSession(id, create); + } + + + @Override + public void setSessionManager(WxSessionManager sessionManager) { + this.sessionManager = sessionManager; + } + + @Override + public String replaceParty(String mediaId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/replaceparty"; + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("media_id", mediaId); + return post(url, jsonObject.toString()); + } + + @Override + public String replaceUser(String mediaId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/replaceuser"; + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("media_id", mediaId); + return post(url, jsonObject.toString()); + } + + @Override + public String getTaskResult(String joinId) throws WxErrorException { + String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/getresult?jobid=" + joinId; + return get(url, null); + } + + public File getTmpDirFile() { + return this.tmpDirFile; + } + + public void setTmpDirFile(File tmpDirFile) { + this.tmpDirFile = tmpDirFile; + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java index 4369868f..8e4d57e3 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java @@ -1,92 +1,34 @@ package me.chanjar.weixin.cp.api.impl.apache; -import com.google.gson.*; -import com.google.gson.reflect.TypeToken; + import me.chanjar.weixin.common.bean.WxAccessToken; -import me.chanjar.weixin.common.bean.WxJsapiSignature; -import me.chanjar.weixin.common.bean.menu.WxMenu; import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.session.StandardSessionManager; -import me.chanjar.weixin.common.session.WxSession; -import me.chanjar.weixin.common.session.WxSessionManager; -import me.chanjar.weixin.common.util.RandomUtils; -import me.chanjar.weixin.common.util.crypto.SHA1; -import me.chanjar.weixin.common.util.fs.FileUtils; -import me.chanjar.weixin.common.util.http.*; import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; -import me.chanjar.weixin.common.util.json.GsonHelper; -import me.chanjar.weixin.cp.api.WxCpConfigStorage; -import me.chanjar.weixin.cp.api.WxCpService; -import me.chanjar.weixin.cp.bean.WxCpDepart; -import me.chanjar.weixin.cp.bean.WxCpMessage; -import me.chanjar.weixin.cp.bean.WxCpTag; -import me.chanjar.weixin.cp.bean.WxCpUser; -import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; -import org.apache.commons.lang3.StringUtils; +import me.chanjar.weixin.cp.api.impl.AbstractWxCpService; + 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.impl.client.BasicResponseHandler; import org.apache.http.impl.client.CloseableHttpClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.util.List; -import java.util.UUID; - -public class WxCpServiceImpl implements WxCpService, RequestHttp { - - protected final Logger log = LoggerFactory.getLogger(WxCpServiceImpl.class); - - /** - * 全局的是否正在刷新access token的锁 - */ - protected final Object globalAccessTokenRefreshLock = new Object(); - - /** - * 全局的是否正在刷新jsapi_ticket的锁 - */ - protected final Object globalJsapiTicketRefreshLock = new Object(); - - protected WxCpConfigStorage configStorage; +public class WxCpServiceImpl extends AbstractWxCpService { protected CloseableHttpClient httpClient; - protected HttpHost httpProxy; - protected WxSessionManager sessionManager = new StandardSessionManager(); - /** - * 临时文件目录 - */ - protected File tmpDirFile; - private int retrySleepMillis = 1000; - private int maxRetryTimes = 5; @Override - public boolean checkSignature(String msgSignature, String timestamp, String nonce, String data) { - try { - return SHA1.gen(this.configStorage.getToken(), timestamp, nonce, data) - .equals(msgSignature); - } catch (Exception e) { - return false; - } + public CloseableHttpClient getRequestHttpClient() { + return httpClient; } @Override - public void userAuthenticated(String userId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/authsucc?userid=" + userId; - get(url, null); - } - - @Override - public String getAccessToken() throws WxErrorException { - return getAccessToken(false); + public HttpHost getRequestHttpProxy() { + return httpProxy; } @Override @@ -108,7 +50,7 @@ public class WxCpServiceImpl implements WxCpService, RequestHttp { httpGet.setConfig(config); } String resultContent = null; - try (CloseableHttpClient httpclient = getHttpclient(); + try (CloseableHttpClient httpclient = getRequestHttpClient(); CloseableHttpResponse response = httpclient.execute(httpGet)) { resultContent = new BasicResponseHandler().handleResponse(response); } finally { @@ -131,491 +73,7 @@ public class WxCpServiceImpl implements WxCpService, RequestHttp { } @Override - public String getJsapiTicket() throws WxErrorException { - return getJsapiTicket(false); - } - - @Override - public String getJsapiTicket(boolean forceRefresh) throws WxErrorException { - if (forceRefresh) { - this.configStorage.expireJsapiTicket(); - } - if (this.configStorage.isJsapiTicketExpired()) { - synchronized (this.globalJsapiTicketRefreshLock) { - if (this.configStorage.isJsapiTicketExpired()) { - String url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket"; - String responseContent = execute(new SimpleGetRequestExecutor(), url, null); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); - String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); - int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); - this.configStorage.updateJsapiTicket(jsapiTicket, - expiresInSeconds); - } - } - } - return this.configStorage.getJsapiTicket(); - } - - @Override - public WxJsapiSignature createJsapiSignature(String url) throws WxErrorException { - long timestamp = System.currentTimeMillis() / 1000; - String noncestr = RandomUtils.getRandomStr(); - String jsapiTicket = getJsapiTicket(false); - String signature = SHA1.genWithAmple( - "jsapi_ticket=" + jsapiTicket, - "noncestr=" + noncestr, - "timestamp=" + timestamp, - "url=" + url - ); - WxJsapiSignature jsapiSignature = new WxJsapiSignature(); - jsapiSignature.setTimestamp(timestamp); - jsapiSignature.setNonceStr(noncestr); - jsapiSignature.setUrl(url); - jsapiSignature.setSignature(signature); - - // Fixed bug - jsapiSignature.setAppId(this.configStorage.getCorpId()); - - return jsapiSignature; - } - - @Override - public void messageSend(WxCpMessage message) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/message/send"; - post(url, message.toJson()); - } - - @Override - public void menuCreate(WxMenu menu) throws WxErrorException { - menuCreate(this.configStorage.getAgentId(), menu); - } - - @Override - public void menuCreate(Integer agentId, WxMenu menu) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/create?agentid=" - + this.configStorage.getAgentId(); - post(url, menu.toJson()); - } - - @Override - public void menuDelete() throws WxErrorException { - menuDelete(this.configStorage.getAgentId()); - } - - @Override - public void menuDelete(Integer agentId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/delete?agentid=" + agentId; - get(url, null); - } - - @Override - public WxMenu menuGet() throws WxErrorException { - return menuGet(this.configStorage.getAgentId()); - } - - @Override - public WxMenu menuGet(Integer agentId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/get?agentid=" + agentId; - try { - String resultContent = get(url, null); - return WxMenu.fromJson(resultContent); - } catch (WxErrorException e) { - // 46003 不存在的菜单数据 - if (e.getError().getErrorCode() == 46003) { - return null; - } - throw e; - } - } - - @Override - public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) - throws WxErrorException, IOException { - return mediaUpload(mediaType, FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType)); - } - - @Override - public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?type=" + mediaType; - return execute(new MediaUploadRequestExecutor(), url, file); - } - - @Override - public File mediaDownload(String mediaId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/media/get"; - return execute( - new MediaDownloadRequestExecutor( - this.configStorage.getTmpDirFile()), - url, "media_id=" + mediaId); - } - - - @Override - public Integer departCreate(WxCpDepart depart) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/department/create"; - String responseContent = execute( - new SimplePostRequestExecutor(), - url, - depart.toJson()); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return GsonHelper.getAsInteger(tmpJsonElement.getAsJsonObject().get("id")); - } - - @Override - public void departUpdate(WxCpDepart group) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/department/update"; - post(url, group.toJson()); - } - - @Override - public void departDelete(Integer departId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/department/delete?id=" + departId; - get(url, null); - } - - @Override - public List departGet() throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/department/list"; - String responseContent = get(url, null); - /* - * 操蛋的微信API,创建时返回的是 { group : { id : ..., name : ...} } - * 查询时返回的是 { groups : [ { id : ..., name : ..., count : ... }, ... ] } - */ - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return WxCpGsonBuilder.INSTANCE.create() - .fromJson( - tmpJsonElement.getAsJsonObject().get("department"), - new TypeToken>() { - }.getType() - ); - } - - @Override - public void userCreate(WxCpUser user) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/create"; - post(url, user.toJson()); - } - - @Override - public void userUpdate(WxCpUser user) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/update"; - post(url, user.toJson()); - } - - @Override - public void userDelete(String userid) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/delete?userid=" + userid; - get(url, null); - } - - @Override - public void userDelete(String[] userids) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/batchdelete"; - JsonObject jsonObject = new JsonObject(); - JsonArray jsonArray = new JsonArray(); - for (String userid : userids) { - jsonArray.add(new JsonPrimitive(userid)); - } - jsonObject.add("useridlist", jsonArray); - post(url, jsonObject.toString()); - } - - @Override - public WxCpUser userGet(String userid) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/get?userid=" + userid; - String responseContent = get(url, null); - return WxCpUser.fromJson(responseContent); - } - - @Override - public List userList(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/list?department_id=" + departId; - String params = ""; - if (fetchChild != null) { - params += "&fetch_child=" + (fetchChild ? "1" : "0"); - } - if (status != null) { - params += "&status=" + status; - } else { - params += "&status=0"; - } - - String responseContent = get(url, params); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return WxCpGsonBuilder.INSTANCE.create() - .fromJson( - tmpJsonElement.getAsJsonObject().get("userlist"), - new TypeToken>() { - }.getType() - ); - } - - @Override - public List departGetUsers(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?department_id=" + departId; - String params = ""; - if (fetchChild != null) { - params += "&fetch_child=" + (fetchChild ? "1" : "0"); - } - if (status != null) { - params += "&status=" + status; - } else { - params += "&status=0"; - } - - String responseContent = get(url, params); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return WxCpGsonBuilder.INSTANCE.create() - .fromJson( - tmpJsonElement.getAsJsonObject().get("userlist"), - new TypeToken>() { - }.getType() - ); - } - - @Override - public String tagCreate(String tagName) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/create"; - JsonObject o = new JsonObject(); - o.addProperty("tagname", tagName); - String responseContent = post(url, o.toString()); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return tmpJsonElement.getAsJsonObject().get("tagid").getAsString(); - } - - @Override - public void tagUpdate(String tagId, String tagName) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/update"; - JsonObject o = new JsonObject(); - o.addProperty("tagid", tagId); - o.addProperty("tagname", tagName); - post(url, o.toString()); - } - - @Override - public void tagDelete(String tagId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/delete?tagid=" + tagId; - get(url, null); - } - - @Override - public List tagGet() throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/list"; - String responseContent = get(url, null); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return WxCpGsonBuilder.INSTANCE.create() - .fromJson( - tmpJsonElement.getAsJsonObject().get("taglist"), - new TypeToken>() { - }.getType() - ); - } - - @Override - public List tagGetUsers(String tagId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/get?tagid=" + tagId; - String responseContent = get(url, null); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return WxCpGsonBuilder.INSTANCE.create() - .fromJson( - tmpJsonElement.getAsJsonObject().get("userlist"), - new TypeToken>() { - }.getType() - ); - } - - @Override - public void tagAddUsers(String tagId, List userIds, List partyIds) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/addtagusers"; - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("tagid", tagId); - if (userIds != null) { - JsonArray jsonArray = new JsonArray(); - for (String userId : userIds) { - jsonArray.add(new JsonPrimitive(userId)); - } - jsonObject.add("userlist", jsonArray); - } - if (partyIds != null) { - JsonArray jsonArray = new JsonArray(); - for (String userId : partyIds) { - jsonArray.add(new JsonPrimitive(userId)); - } - jsonObject.add("partylist", jsonArray); - } - post(url, jsonObject.toString()); - } - - @Override - public void tagRemoveUsers(String tagId, List userIds) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/deltagusers"; - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("tagid", tagId); - JsonArray jsonArray = new JsonArray(); - for (String userId : userIds) { - jsonArray.add(new JsonPrimitive(userId)); - } - jsonObject.add("userlist", jsonArray); - post(url, jsonObject.toString()); - } - - @Override - public String oauth2buildAuthorizationUrl(String state) { - return this.oauth2buildAuthorizationUrl( - this.configStorage.getOauth2redirectUri(), - state - ); - } - - @Override - public String oauth2buildAuthorizationUrl(String redirectUri, String state) { - String url = "https://open.weixin.qq.com/connect/oauth2/authorize?"; - url += "appid=" + this.configStorage.getCorpId(); - url += "&redirect_uri=" + URIUtil.encodeURIComponent(redirectUri); - url += "&response_type=code"; - url += "&scope=snsapi_base"; - if (state != null) { - url += "&state=" + state; - } - url += "#wechat_redirect"; - return url; - } - - @Override - public String[] oauth2getUserInfo(String code) throws WxErrorException { - return oauth2getUserInfo(this.configStorage.getAgentId(), code); - } - - @Override - public String[] oauth2getUserInfo(Integer agentId, String code) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?" - + "code=" + code - + "&agentid=" + agentId; - String responseText = get(url, null); - JsonElement je = new JsonParser().parse(responseText); - JsonObject jo = je.getAsJsonObject(); - return new String[]{GsonHelper.getString(jo, "UserId"), GsonHelper.getString(jo, "DeviceId"), GsonHelper.getString(jo, "OpenId")}; - } - - @Override - public int invite(String userId, String inviteTips) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/invite/send"; - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("userid", userId); - if (StringUtils.isNotEmpty(inviteTips)) { - jsonObject.addProperty("invite_tips", inviteTips); - } - String responseContent = post(url, jsonObject.toString()); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return tmpJsonElement.getAsJsonObject().get("type").getAsInt(); - } - - @Override - public String[] getCallbackIp() throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/getcallbackip"; - String responseContent = get(url, null); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - JsonArray jsonArray = tmpJsonElement.getAsJsonObject().get("ip_list").getAsJsonArray(); - String[] ips = new String[jsonArray.size()]; - for (int i = 0; i < jsonArray.size(); i++) { - ips[i] = jsonArray.get(i).getAsString(); - } - return ips; - } - - @Override - public String get(String url, String queryParam) throws WxErrorException { - return execute(new SimpleGetRequestExecutor(), url, queryParam); - } - - @Override - public String post(String url, String postData) throws WxErrorException { - return execute(new SimplePostRequestExecutor(), url, postData); - } - - /** - * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 - */ - @Override - public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { - int retryTimes = 0; - do { - try { - T result = this.executeInternal(executor, uri, data); - this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}",uri, data, result); - return result; - } catch (WxErrorException e) { - if (retryTimes + 1 > this.maxRetryTimes) { - this.log.warn("重试达到最大次数【{}】", this.maxRetryTimes); - //最后一次重试失败后,直接抛出异常,不再等待 - throw new RuntimeException("微信服务端异常,超出重试次数"); - } - - WxError error = e.getError(); - /* - * -1 系统繁忙, 1000ms后重试 - */ - if (error.getErrorCode() == -1) { - int sleepMillis = this.retrySleepMillis * (1 << retryTimes); - try { - this.log.debug("微信系统繁忙,{} ms 后重试(第{}次)", sleepMillis, retryTimes + 1); - Thread.sleep(sleepMillis); - } catch (InterruptedException e1) { - throw new RuntimeException(e1); - } - } else { - throw e; - } - } - } while (retryTimes++ < this.maxRetryTimes); - - this.log.warn("重试达到最大次数【{}】", this.maxRetryTimes); - throw new RuntimeException("微信服务端异常,超出重试次数"); - } - - public synchronized T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { - if (uri.contains("access_token=")) { - throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); - } - String accessToken = getAccessToken(false); - - String uriWithAccessToken = uri; - uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken; - - try { - return executor.execute(this, uriWithAccessToken, data); - } catch (WxErrorException e) { - WxError error = e.getError(); - /* - * 发生以下情况时尝试刷新access_token - * 40001 获取access_token时AppSecret错误,或者access_token无效 - * 42001 access_token超时 - */ - if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) { - // 强制设置wxCpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token - this.configStorage.expireAccessToken(); - return execute(executor, uri, data); - } - - if (error.getErrorCode() != 0) { - this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", uri, data, error); - throw new WxErrorException(error); - } - return null; - } catch (IOException e) { - this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[EXCEPTION]: {}", uri, data, e.getMessage()); - throw new RuntimeException(e); - } - } - - protected CloseableHttpClient getHttpclient() { - return this.httpClient; - } - - @Override - public void setWxCpConfigStorage(WxCpConfigStorage wxConfigProvider) { - this.configStorage = wxConfigProvider; + public void initHttp() { ApacheHttpClientBuilder apacheHttpClientBuilder = this.configStorage .getApacheHttpClientBuilder(); if (null == apacheHttpClientBuilder) { @@ -633,78 +91,4 @@ public class WxCpServiceImpl implements WxCpService, RequestHttp { this.httpClient = apacheHttpClientBuilder.build(); } - - @Override - public void setRetrySleepMillis(int retrySleepMillis) { - this.retrySleepMillis = retrySleepMillis; - } - - - @Override - public void setMaxRetryTimes(int maxRetryTimes) { - this.maxRetryTimes = maxRetryTimes; - } - - @Override - public WxSession getSession(String id) { - if (this.sessionManager == null) { - return null; - } - return this.sessionManager.getSession(id); - } - - @Override - public WxSession getSession(String id, boolean create) { - if (this.sessionManager == null) { - return null; - } - return this.sessionManager.getSession(id, create); - } - - - @Override - public void setSessionManager(WxSessionManager sessionManager) { - this.sessionManager = sessionManager; - } - - @Override - public String replaceParty(String mediaId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/replaceparty"; - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("media_id", mediaId); - return post(url, jsonObject.toString()); - } - - @Override - public String replaceUser(String mediaId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/replaceuser"; - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("media_id", mediaId); - return post(url, jsonObject.toString()); - } - - @Override - public String getTaskResult(String joinId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/getresult?jobid=" + joinId; - return get(url, null); - } - - public File getTmpDirFile() { - return this.tmpDirFile; - } - - public void setTmpDirFile(File tmpDirFile) { - this.tmpDirFile = tmpDirFile; - } - - - @Override - public Object getRequestHttpClient() { - return this.httpClient; - } - - @Override - public Object getRequestHttpProxy() { - return this.httpProxy; - } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/jodd/WxCpServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/jodd/WxCpServiceImpl.java index 8c41f042..f0af3474 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/jodd/WxCpServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/jodd/WxCpServiceImpl.java @@ -1,85 +1,24 @@ package me.chanjar.weixin.cp.api.impl.jodd; -import com.google.gson.*; -import com.google.gson.reflect.TypeToken; import jodd.http.*; import me.chanjar.weixin.common.bean.WxAccessToken; -import me.chanjar.weixin.common.bean.WxJsapiSignature; -import me.chanjar.weixin.common.bean.menu.WxMenu; import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.session.StandardSessionManager; -import me.chanjar.weixin.common.session.WxSession; -import me.chanjar.weixin.common.session.WxSessionManager; -import me.chanjar.weixin.common.util.RandomUtils; -import me.chanjar.weixin.common.util.crypto.SHA1; -import me.chanjar.weixin.common.util.fs.FileUtils; -import me.chanjar.weixin.common.util.http.*; -import me.chanjar.weixin.common.util.json.GsonHelper; -import me.chanjar.weixin.cp.api.WxCpConfigStorage; -import me.chanjar.weixin.cp.api.WxCpService; -import me.chanjar.weixin.cp.bean.WxCpDepart; -import me.chanjar.weixin.cp.bean.WxCpMessage; -import me.chanjar.weixin.cp.bean.WxCpTag; -import me.chanjar.weixin.cp.bean.WxCpUser; -import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.List; -import java.util.UUID; - -public class WxCpServiceImpl implements WxCpService, RequestHttp { - - protected final Logger log = LoggerFactory.getLogger(WxCpServiceImpl.class); - - /** - * 全局的是否正在刷新access token的锁 - */ - protected final Object globalAccessTokenRefreshLock = new Object(); - - /** - * 全局的是否正在刷新jsapi_ticket的锁 - */ - protected final Object globalJsapiTicketRefreshLock = new Object(); - - protected WxCpConfigStorage configStorage; +import me.chanjar.weixin.cp.api.impl.AbstractWxCpService; +public class WxCpServiceImpl extends AbstractWxCpService { protected HttpConnectionProvider httpClient; - protected ProxyInfo httpProxy; - protected WxSessionManager sessionManager = new StandardSessionManager(); - /** - * 临时文件目录 - */ - protected File tmpDirFile; - private int retrySleepMillis = 1000; - private int maxRetryTimes = 5; - @Override - public boolean checkSignature(String msgSignature, String timestamp, String nonce, String data) { - try { - return SHA1.gen(this.configStorage.getToken(), timestamp, nonce, data) - .equals(msgSignature); - } catch (Exception e) { - return false; - } - } @Override - public void userAuthenticated(String userId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/authsucc?userid=" + userId; - get(url, null); + public HttpConnectionProvider getRequestHttpClient() { + return httpClient; } @Override - public String getAccessToken() throws WxErrorException { - return getAccessToken(false); + public ProxyInfo getRequestHttpProxy() { + return httpProxy; } @Override @@ -116,571 +55,11 @@ public class WxCpServiceImpl implements WxCpService, RequestHttp { } @Override - public String getJsapiTicket() throws WxErrorException { - return getJsapiTicket(false); - } - - @Override - public String getJsapiTicket(boolean forceRefresh) throws WxErrorException { - if (forceRefresh) { - this.configStorage.expireJsapiTicket(); - } - if (this.configStorage.isJsapiTicketExpired()) { - synchronized (this.globalJsapiTicketRefreshLock) { - if (this.configStorage.isJsapiTicketExpired()) { - String url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket"; - String responseContent = execute(new SimpleGetRequestExecutor(), url, null); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); - String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); - int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); - this.configStorage.updateJsapiTicket(jsapiTicket, - expiresInSeconds); - } - } - } - return this.configStorage.getJsapiTicket(); - } - - @Override - public WxJsapiSignature createJsapiSignature(String url) throws WxErrorException { - long timestamp = System.currentTimeMillis() / 1000; - String noncestr = RandomUtils.getRandomStr(); - String jsapiTicket = getJsapiTicket(false); - String signature = SHA1.genWithAmple( - "jsapi_ticket=" + jsapiTicket, - "noncestr=" + noncestr, - "timestamp=" + timestamp, - "url=" + url - ); - WxJsapiSignature jsapiSignature = new WxJsapiSignature(); - jsapiSignature.setTimestamp(timestamp); - jsapiSignature.setNonceStr(noncestr); - jsapiSignature.setUrl(url); - jsapiSignature.setSignature(signature); - - // Fixed bug - jsapiSignature.setAppId(this.configStorage.getCorpId()); - - return jsapiSignature; - } - - @Override - public void messageSend(WxCpMessage message) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/message/send"; - post(url, message.toJson()); - } - - @Override - public void menuCreate(WxMenu menu) throws WxErrorException { - menuCreate(this.configStorage.getAgentId(), menu); - } - - @Override - public void menuCreate(Integer agentId, WxMenu menu) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/create?agentid=" - + this.configStorage.getAgentId(); - post(url, menu.toJson()); - } - - @Override - public void menuDelete() throws WxErrorException { - menuDelete(this.configStorage.getAgentId()); - } - - @Override - public void menuDelete(Integer agentId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/delete?agentid=" + agentId; - get(url, null); - } - - @Override - public WxMenu menuGet() throws WxErrorException { - return menuGet(this.configStorage.getAgentId()); - } - - @Override - public WxMenu menuGet(Integer agentId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/get?agentid=" + agentId; - try { - String resultContent = get(url, null); - return WxMenu.fromJson(resultContent); - } catch (WxErrorException e) { - // 46003 不存在的菜单数据 - if (e.getError().getErrorCode() == 46003) { - return null; - } - throw e; - } - } - - @Override - public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) - throws WxErrorException, IOException { - return mediaUpload(mediaType, FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType)); - } - - @Override - public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?type=" + mediaType; - return execute(new MediaUploadRequestExecutor(), url, file); - } - - @Override - public File mediaDownload(String mediaId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/media/get"; - return execute( - new MediaDownloadRequestExecutor( - this.configStorage.getTmpDirFile()), - url, "media_id=" + mediaId); - } - - - @Override - public Integer departCreate(WxCpDepart depart) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/department/create"; - String responseContent = execute( - new SimplePostRequestExecutor(), - url, - depart.toJson()); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return GsonHelper.getAsInteger(tmpJsonElement.getAsJsonObject().get("id")); - } - - @Override - public void departUpdate(WxCpDepart group) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/department/update"; - post(url, group.toJson()); - } - - @Override - public void departDelete(Integer departId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/department/delete?id=" + departId; - get(url, null); - } - - @Override - public List departGet() throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/department/list"; - String responseContent = get(url, null); - /* - * 操蛋的微信API,创建时返回的是 { group : { id : ..., name : ...} } - * 查询时返回的是 { groups : [ { id : ..., name : ..., count : ... }, ... ] } - */ - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return WxCpGsonBuilder.INSTANCE.create() - .fromJson( - tmpJsonElement.getAsJsonObject().get("department"), - new TypeToken>() { - }.getType() - ); - } - - @Override - public void userCreate(WxCpUser user) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/create"; - post(url, user.toJson()); - } - - @Override - public void userUpdate(WxCpUser user) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/update"; - post(url, user.toJson()); - } - - @Override - public void userDelete(String userid) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/delete?userid=" + userid; - get(url, null); - } - - @Override - public void userDelete(String[] userids) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/batchdelete"; - JsonObject jsonObject = new JsonObject(); - JsonArray jsonArray = new JsonArray(); - for (String userid : userids) { - jsonArray.add(new JsonPrimitive(userid)); - } - jsonObject.add("useridlist", jsonArray); - post(url, jsonObject.toString()); - } - - @Override - public WxCpUser userGet(String userid) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/get?userid=" + userid; - String responseContent = get(url, null); - return WxCpUser.fromJson(responseContent); - } - - @Override - public List userList(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/list?department_id=" + departId; - String params = ""; - if (fetchChild != null) { - params += "&fetch_child=" + (fetchChild ? "1" : "0"); - } - if (status != null) { - params += "&status=" + status; - } else { - params += "&status=0"; - } - - String responseContent = get(url, params); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return WxCpGsonBuilder.INSTANCE.create() - .fromJson( - tmpJsonElement.getAsJsonObject().get("userlist"), - new TypeToken>() { - }.getType() - ); - } - - @Override - public List departGetUsers(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?department_id=" + departId; - String params = ""; - if (fetchChild != null) { - params += "&fetch_child=" + (fetchChild ? "1" : "0"); - } - if (status != null) { - params += "&status=" + status; - } else { - params += "&status=0"; - } - - String responseContent = get(url, params); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return WxCpGsonBuilder.INSTANCE.create() - .fromJson( - tmpJsonElement.getAsJsonObject().get("userlist"), - new TypeToken>() { - }.getType() - ); - } - - @Override - public String tagCreate(String tagName) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/create"; - JsonObject o = new JsonObject(); - o.addProperty("tagname", tagName); - String responseContent = post(url, o.toString()); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return tmpJsonElement.getAsJsonObject().get("tagid").getAsString(); - } - - @Override - public void tagUpdate(String tagId, String tagName) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/update"; - JsonObject o = new JsonObject(); - o.addProperty("tagid", tagId); - o.addProperty("tagname", tagName); - post(url, o.toString()); - } - - @Override - public void tagDelete(String tagId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/delete?tagid=" + tagId; - get(url, null); - } - - @Override - public List tagGet() throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/list"; - String responseContent = get(url, null); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return WxCpGsonBuilder.INSTANCE.create() - .fromJson( - tmpJsonElement.getAsJsonObject().get("taglist"), - new TypeToken>() { - }.getType() - ); - } - - @Override - public List tagGetUsers(String tagId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/get?tagid=" + tagId; - String responseContent = get(url, null); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return WxCpGsonBuilder.INSTANCE.create() - .fromJson( - tmpJsonElement.getAsJsonObject().get("userlist"), - new TypeToken>() { - }.getType() - ); - } - - @Override - public void tagAddUsers(String tagId, List userIds, List partyIds) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/addtagusers"; - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("tagid", tagId); - if (userIds != null) { - JsonArray jsonArray = new JsonArray(); - for (String userId : userIds) { - jsonArray.add(new JsonPrimitive(userId)); - } - jsonObject.add("userlist", jsonArray); - } - if (partyIds != null) { - JsonArray jsonArray = new JsonArray(); - for (String userId : partyIds) { - jsonArray.add(new JsonPrimitive(userId)); - } - jsonObject.add("partylist", jsonArray); - } - post(url, jsonObject.toString()); - } - - @Override - public void tagRemoveUsers(String tagId, List userIds) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/deltagusers"; - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("tagid", tagId); - JsonArray jsonArray = new JsonArray(); - for (String userId : userIds) { - jsonArray.add(new JsonPrimitive(userId)); - } - jsonObject.add("userlist", jsonArray); - post(url, jsonObject.toString()); - } - - @Override - public String oauth2buildAuthorizationUrl(String state) { - return this.oauth2buildAuthorizationUrl( - this.configStorage.getOauth2redirectUri(), - state - ); - } - - @Override - public String oauth2buildAuthorizationUrl(String redirectUri, String state) { - String url = "https://open.weixin.qq.com/connect/oauth2/authorize?"; - url += "appid=" + this.configStorage.getCorpId(); - url += "&redirect_uri=" + URIUtil.encodeURIComponent(redirectUri); - url += "&response_type=code"; - url += "&scope=snsapi_base"; - if (state != null) { - url += "&state=" + state; - } - url += "#wechat_redirect"; - return url; - } - - @Override - public String[] oauth2getUserInfo(String code) throws WxErrorException { - return oauth2getUserInfo(this.configStorage.getAgentId(), code); - } - - @Override - public String[] oauth2getUserInfo(Integer agentId, String code) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?" - + "code=" + code - + "&agentid=" + agentId; - String responseText = get(url, null); - JsonElement je = new JsonParser().parse(responseText); - JsonObject jo = je.getAsJsonObject(); - return new String[]{GsonHelper.getString(jo, "UserId"), GsonHelper.getString(jo, "DeviceId"), GsonHelper.getString(jo, "OpenId")}; - } - - @Override - public int invite(String userId, String inviteTips) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/invite/send"; - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("userid", userId); - if (StringUtils.isNotEmpty(inviteTips)) { - jsonObject.addProperty("invite_tips", inviteTips); - } - String responseContent = post(url, jsonObject.toString()); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return tmpJsonElement.getAsJsonObject().get("type").getAsInt(); - } - - @Override - public String[] getCallbackIp() throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/getcallbackip"; - String responseContent = get(url, null); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - JsonArray jsonArray = tmpJsonElement.getAsJsonObject().get("ip_list").getAsJsonArray(); - String[] ips = new String[jsonArray.size()]; - for (int i = 0; i < jsonArray.size(); i++) { - ips[i] = jsonArray.get(i).getAsString(); - } - return ips; - } - - @Override - public String get(String url, String queryParam) throws WxErrorException { - return execute(new SimpleGetRequestExecutor(), url, queryParam); - } - - @Override - public String post(String url, String postData) throws WxErrorException { - return execute(new SimplePostRequestExecutor(), url, postData); - } - - /** - * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 - */ - @Override - public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { - int retryTimes = 0; - do { - try { - T result = this.executeInternal(executor, uri, data); - this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", uri, data, result); - return result; - } catch (WxErrorException e) { - if (retryTimes + 1 > this.maxRetryTimes) { - this.log.warn("重试达到最大次数【{}】", this.maxRetryTimes); - //最后一次重试失败后,直接抛出异常,不再等待 - throw new RuntimeException("微信服务端异常,超出重试次数"); - } - - WxError error = e.getError(); - /* - * -1 系统繁忙, 1000ms后重试 - */ - if (error.getErrorCode() == -1) { - int sleepMillis = this.retrySleepMillis * (1 << retryTimes); - try { - this.log.debug("微信系统繁忙,{} ms 后重试(第{}次)", sleepMillis, retryTimes + 1); - Thread.sleep(sleepMillis); - } catch (InterruptedException e1) { - throw new RuntimeException(e1); - } - } else { - throw e; - } - } - } while (retryTimes++ < this.maxRetryTimes); - - this.log.warn("重试达到最大次数【{}】", this.maxRetryTimes); - throw new RuntimeException("微信服务端异常,超出重试次数"); - } - - - public synchronized T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { - if (uri.contains("access_token=")) { - throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); - } - String accessToken = getAccessToken(false); - - String uriWithAccessToken = uri; - uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken; - - try { - return executor.execute(this, uriWithAccessToken, data); - } catch (WxErrorException e) { - WxError error = e.getError(); - /* - * 发生以下情况时尝试刷新access_token - * 40001 获取access_token时AppSecret错误,或者access_token无效 - * 42001 access_token超时 - */ - if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) { - // 强制设置wxCpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token - this.configStorage.expireAccessToken(); - return execute(executor, uri, data); - } - - if (error.getErrorCode() != 0) { - this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", uri, data, error); - throw new WxErrorException(error); - } - return null; - } catch (IOException e) { - this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[EXCEPTION]: {}", uri, data, e.getMessage()); - throw new RuntimeException(e); - } - } - - protected HttpConnectionProvider getHttpclient() { - return this.httpClient; - } - - @Override - public void setWxCpConfigStorage(WxCpConfigStorage wxConfigProvider) { - this.configStorage = wxConfigProvider; - + public void initHttp() { if (this.configStorage.getHttpProxyHost() != null && this.configStorage.getHttpProxyPort() > 0) { httpProxy = new ProxyInfo(ProxyInfo.ProxyType.HTTP, configStorage.getHttpProxyHost(), configStorage.getHttpProxyPort(), configStorage.getHttpProxyUsername(), configStorage.getHttpProxyPassword()); } httpClient = JoddHttp.httpConnectionProvider; } - - @Override - public void setRetrySleepMillis(int retrySleepMillis) { - this.retrySleepMillis = retrySleepMillis; - } - - - @Override - public void setMaxRetryTimes(int maxRetryTimes) { - this.maxRetryTimes = maxRetryTimes; - } - - @Override - public WxSession getSession(String id) { - if (this.sessionManager == null) { - return null; - } - return this.sessionManager.getSession(id); - } - - @Override - public WxSession getSession(String id, boolean create) { - if (this.sessionManager == null) { - return null; - } - return this.sessionManager.getSession(id, create); - } - - - @Override - public void setSessionManager(WxSessionManager sessionManager) { - this.sessionManager = sessionManager; - } - - @Override - public String replaceParty(String mediaId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/replaceparty"; - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("media_id", mediaId); - return post(url, jsonObject.toString()); - } - - @Override - public String replaceUser(String mediaId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/replaceuser"; - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("media_id", mediaId); - return post(url, jsonObject.toString()); - } - - @Override - public String getTaskResult(String joinId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/getresult?jobid=" + joinId; - return get(url, null); - } - - public File getTmpDirFile() { - return this.tmpDirFile; - } - - public void setTmpDirFile(File tmpDirFile) { - this.tmpDirFile = tmpDirFile; - } - - - @Override - public Object getRequestHttpClient() { - return this.httpClient; - } - - @Override - public Object getRequestHttpProxy() { - return this.httpProxy; - } } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/okhttp/WxCpServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/okhttp/WxCpServiceImpl.java new file mode 100644 index 00000000..39db3816 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/okhttp/WxCpServiceImpl.java @@ -0,0 +1,90 @@ +package me.chanjar.weixin.cp.api.impl.okhttp; + +import java.io.IOException; + +import jodd.http.*; +import me.chanjar.weixin.common.bean.WxAccessToken; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; +import me.chanjar.weixin.cp.api.WxCpConfigStorage; +import me.chanjar.weixin.cp.api.impl.AbstractWxCpService; +import okhttp3.*; + +public class WxCpServiceImpl extends AbstractWxCpService { + protected ConnectionPool httpClient; + protected OkhttpProxyInfo httpProxy; + + + @Override + public ConnectionPool getRequestHttpClient() { + return httpClient; + } + + @Override + public OkhttpProxyInfo getRequestHttpProxy() { + return httpProxy; + } + + @Override + public String getAccessToken(boolean forceRefresh) throws WxErrorException { + if (forceRefresh) { + this.configStorage.expireAccessToken(); + } + if (this.configStorage.isAccessTokenExpired()) { + synchronized (this.globalAccessTokenRefreshLock) { + if (this.configStorage.isAccessTokenExpired()) { + String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?" + + "&corpid=" + this.configStorage.getCorpId() + + "&corpsecret=" + this.configStorage.getCorpSecret(); + + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(httpClient); + //设置代理 + if (httpProxy != null) { + clientBuilder.proxy(getRequestHttpProxy().getProxy()); + } + //设置授权 + clientBuilder.authenticator(new Authenticator() { + @Override + public Request authenticate(Route route, Response response) throws IOException { + String credential = Credentials.basic(httpProxy.getProxyUsername(), httpProxy.getProxyPassword()); + return response.request().newBuilder() + .header("Authorization", credential) + .build(); + } + }); + //得到httpClient + OkHttpClient client = clientBuilder.build(); + //请求的request + Request request = new Request.Builder().url(url).get().build(); + Response response = null; + try { + response = client.newCall(request).execute(); + } catch (IOException e) { + e.printStackTrace(); + } + String resultContent = response.body().toString(); + WxError error = WxError.fromJson(resultContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + WxAccessToken accessToken = WxAccessToken.fromJson(resultContent); + this.configStorage.updateAccessToken(accessToken.getAccessToken(), + accessToken.getExpiresIn()); + } + } + } + return this.configStorage.getAccessToken(); + } + + @Override + public void initHttp() { + WxCpConfigStorage configStorage = this.configStorage; + + if (configStorage.getHttpProxyHost() != null && configStorage.getHttpProxyPort() > 0) { + httpProxy = new OkhttpProxyInfo(OkhttpProxyInfo.ProxyType.SOCKS5, configStorage.getHttpProxyHost(), configStorage.getHttpProxyPort(), configStorage.getHttpProxyUsername(), configStorage.getHttpProxyPassword()); + } + + httpClient = new ConnectionPool(); + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java index 0b968594..33333c44 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java @@ -344,14 +344,10 @@ public interface WxMpService { */ WxMpDeviceService getDeviceService(); - /** - * @return - */ - //Object getHttpclient(); /** - * @return + * 初始化http请求对象 */ - //Object getHttpProxy(); + void initHttp(); } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/AbstractWxMpService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/AbstractWxMpService.java new file mode 100644 index 00000000..5c6b58eb --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/AbstractWxMpService.java @@ -0,0 +1,445 @@ +package me.chanjar.weixin.mp.api.impl; + +import java.io.IOException; +import java.util.concurrent.locks.Lock; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import me.chanjar.weixin.common.bean.WxJsapiSignature; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.session.StandardSessionManager; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.common.util.RandomUtils; +import me.chanjar.weixin.common.util.crypto.SHA1; +import me.chanjar.weixin.common.util.http.*; +import me.chanjar.weixin.mp.api.*; +import me.chanjar.weixin.mp.bean.*; +import me.chanjar.weixin.mp.bean.result.*; + +public abstract class AbstractWxMpService implements WxMpService,RequestHttp { + + private static final JsonParser JSON_PARSER = new JsonParser(); + + protected final Logger log = LoggerFactory.getLogger(this.getClass()); + protected WxSessionManager sessionManager = new StandardSessionManager(); + private WxMpConfigStorage wxMpConfigStorage; + private WxMpKefuService kefuService = new WxMpKefuServiceImpl(this); + private WxMpMaterialService materialService = new WxMpMaterialServiceImpl(this); + private WxMpMenuService menuService = new WxMpMenuServiceImpl(this); + private WxMpUserService userService = new WxMpUserServiceImpl(this); + private WxMpUserTagService tagService = new WxMpUserTagServiceImpl(this); + private WxMpQrcodeService qrCodeService = new WxMpQrcodeServiceImpl(this); + private WxMpCardService cardService = new WxMpCardServiceImpl(this); + private WxMpStoreService storeService = new WxMpStoreServiceImpl(this); + private WxMpDataCubeService dataCubeService = new WxMpDataCubeServiceImpl(this); + private WxMpUserBlacklistService blackListService = new WxMpUserBlacklistServiceImpl(this); + private WxMpTemplateMsgService templateMsgService = new WxMpTemplateMsgServiceImpl(this); + private WxMpDeviceService deviceService = new WxMpDeviceServiceImpl(this); + + private int retrySleepMillis = 1000; + private int maxRetryTimes = 5; + + + @Override + public boolean checkSignature(String timestamp, String nonce, String signature) { + try { + return SHA1.gen(this.getWxMpConfigStorage().getToken(), timestamp, nonce) + .equals(signature); + } catch (Exception e) { + return false; + } + } + + @Override + public String getJsapiTicket() throws WxErrorException { + return getJsapiTicket(false); + } + + @Override + public String getJsapiTicket(boolean forceRefresh) throws WxErrorException { + Lock lock = this.getWxMpConfigStorage().getJsapiTicketLock(); + try { + lock.lock(); + + if (forceRefresh) { + this.getWxMpConfigStorage().expireJsapiTicket(); + } + + if (this.getWxMpConfigStorage().isJsapiTicketExpired()) { + String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi"; + String responseContent = execute(new SimpleGetRequestExecutor(), url, null); + JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); + JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); + String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); + int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); + this.getWxMpConfigStorage().updateJsapiTicket(jsapiTicket, expiresInSeconds); + } + } finally { + lock.unlock(); + } + return this.getWxMpConfigStorage().getJsapiTicket(); + } + + @Override + public WxJsapiSignature createJsapiSignature(String url) throws WxErrorException { + long timestamp = System.currentTimeMillis() / 1000; + String noncestr = RandomUtils.getRandomStr(); + String jsapiTicket = getJsapiTicket(false); + String signature = SHA1.genWithAmple("jsapi_ticket=" + jsapiTicket, + "noncestr=" + noncestr, "timestamp=" + timestamp, "url=" + url); + WxJsapiSignature jsapiSignature = new WxJsapiSignature(); + jsapiSignature.setAppId(this.getWxMpConfigStorage().getAppId()); + jsapiSignature.setTimestamp(timestamp); + jsapiSignature.setNonceStr(noncestr); + jsapiSignature.setUrl(url); + jsapiSignature.setSignature(signature); + return jsapiSignature; + } + + @Override + public String getAccessToken() throws WxErrorException { + return getAccessToken(false); + } + + @Override + public WxMpMassUploadResult massNewsUpload(WxMpMassNews news) throws WxErrorException { + String url = "https://api.weixin.qq.com/cgi-bin/media/uploadnews"; + String responseContent = this.post(url, news.toJson()); + return WxMpMassUploadResult.fromJson(responseContent); + } + + @Override + public WxMpMassUploadResult massVideoUpload(WxMpMassVideo video) throws WxErrorException { + String url = "https://api.weixin.qq.com/cgi-bin/media/uploadvideo"; + String responseContent = this.post(url, video.toJson()); + return WxMpMassUploadResult.fromJson(responseContent); + } + + @Override + public WxMpMassSendResult massGroupMessageSend(WxMpMassTagMessage message) throws WxErrorException { + String url = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall"; + String responseContent = this.post(url, message.toJson()); + return WxMpMassSendResult.fromJson(responseContent); + } + + @Override + public WxMpMassSendResult massOpenIdsMessageSend(WxMpMassOpenIdsMessage message) throws WxErrorException { + String url = "https://api.weixin.qq.com/cgi-bin/message/mass/send"; + String responseContent = this.post(url, message.toJson()); + return WxMpMassSendResult.fromJson(responseContent); + } + + @Override + public WxMpMassSendResult massMessagePreview(WxMpMassPreviewMessage wxMpMassPreviewMessage) throws Exception { + String url = "https://api.weixin.qq.com/cgi-bin/message/mass/preview"; + String responseContent = this.post(url, wxMpMassPreviewMessage.toJson()); + return WxMpMassSendResult.fromJson(responseContent); + } + + @Override + public String shortUrl(String long_url) throws WxErrorException { + String url = "https://api.weixin.qq.com/cgi-bin/shorturl"; + JsonObject o = new JsonObject(); + o.addProperty("action", "long2short"); + o.addProperty("long_url", long_url); + String responseContent = this.post(url, o.toString()); + JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); + return tmpJsonElement.getAsJsonObject().get("short_url").getAsString(); + } + + @Override + public WxMpSemanticQueryResult semanticQuery(WxMpSemanticQuery semanticQuery) throws WxErrorException { + String url = "https://api.weixin.qq.com/semantic/semproxy/search"; + String responseContent = this.post(url, semanticQuery.toJson()); + return WxMpSemanticQueryResult.fromJson(responseContent); + } + + @Override + public String oauth2buildAuthorizationUrl(String redirectURI, String scope, String state) { + StringBuilder url = new StringBuilder(); + url.append("https://open.weixin.qq.com/connect/oauth2/authorize?"); + url.append("appid=").append(this.getWxMpConfigStorage().getAppId()); + url.append("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectURI)); + url.append("&response_type=code"); + url.append("&scope=").append(scope); + if (state != null) { + url.append("&state=").append(state); + } + url.append("#wechat_redirect"); + return url.toString(); + } + + @Override + public String buildQrConnectUrl(String redirectURI, String scope, + String state) { + StringBuilder url = new StringBuilder(); + url.append("https://open.weixin.qq.com/connect/qrconnect?"); + url.append("appid=").append(this.getWxMpConfigStorage().getAppId()); + url.append("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectURI)); + url.append("&response_type=code"); + url.append("&scope=").append(scope); + if (state != null) { + url.append("&state=").append(state); + } + + url.append("#wechat_redirect"); + return url.toString(); + } + + private WxMpOAuth2AccessToken getOAuth2AccessToken(StringBuilder url) throws WxErrorException { + try { + RequestExecutor executor = new SimpleGetRequestExecutor(); + String responseText = executor.execute(this, url.toString(), null); + return WxMpOAuth2AccessToken.fromJson(responseText); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public WxMpOAuth2AccessToken oauth2getAccessToken(String code) throws WxErrorException { + StringBuilder url = new StringBuilder(); + url.append("https://api.weixin.qq.com/sns/oauth2/access_token?"); + url.append("appid=").append(this.getWxMpConfigStorage().getAppId()); + url.append("&secret=").append(this.getWxMpConfigStorage().getSecret()); + url.append("&code=").append(code); + url.append("&grant_type=authorization_code"); + + return this.getOAuth2AccessToken(url); + } + + @Override + public WxMpOAuth2AccessToken oauth2refreshAccessToken(String refreshToken) throws WxErrorException { + StringBuilder url = new StringBuilder(); + url.append("https://api.weixin.qq.com/sns/oauth2/refresh_token?"); + url.append("appid=").append(this.getWxMpConfigStorage().getAppId()); + url.append("&grant_type=refresh_token"); + url.append("&refresh_token=").append(refreshToken); + + return this.getOAuth2AccessToken(url); + } + + @Override + public WxMpUser oauth2getUserInfo(WxMpOAuth2AccessToken oAuth2AccessToken, String lang) throws WxErrorException { + StringBuilder url = new StringBuilder(); + url.append("https://api.weixin.qq.com/sns/userinfo?"); + url.append("access_token=").append(oAuth2AccessToken.getAccessToken()); + url.append("&openid=").append(oAuth2AccessToken.getOpenId()); + if (lang == null) { + url.append("&lang=zh_CN"); + } else { + url.append("&lang=").append(lang); + } + + try { + RequestExecutor executor = new SimpleGetRequestExecutor(); + String responseText = executor.execute(this, url.toString(), null); + return WxMpUser.fromJson(responseText); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public boolean oauth2validateAccessToken(WxMpOAuth2AccessToken oAuth2AccessToken) { + StringBuilder url = new StringBuilder(); + url.append("https://api.weixin.qq.com/sns/auth?"); + url.append("access_token=").append(oAuth2AccessToken.getAccessToken()); + url.append("&openid=").append(oAuth2AccessToken.getOpenId()); + + try { + RequestExecutor executor = new SimpleGetRequestExecutor(); + executor.execute(this, url.toString(), null); + } catch (IOException e) { + throw new RuntimeException(e); + } catch (WxErrorException e) { + return false; + } + return true; + } + + @Override + public String[] getCallbackIP() throws WxErrorException { + String url = "https://api.weixin.qq.com/cgi-bin/getcallbackip"; + String responseContent = get(url, null); + JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); + JsonArray ipList = tmpJsonElement.getAsJsonObject().get("ip_list").getAsJsonArray(); + String[] ipArray = new String[ipList.size()]; + for (int i = 0; i < ipList.size(); i++) { + ipArray[i] = ipList.get(i).getAsString(); + } + return ipArray; + } + + @Override + public String get(String url, String queryParam) throws WxErrorException { + return execute(new SimpleGetRequestExecutor(), url, queryParam); + } + + @Override + public String post(String url, String postData) throws WxErrorException { + return execute(new SimplePostRequestExecutor(), url, postData); + } + + /** + * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 + */ + public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { + int retryTimes = 0; + do { + try { + T result = executeInternal(executor, uri, data); + this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", uri, data, result); + return result; + } catch (WxErrorException e) { + if (retryTimes + 1 > this.maxRetryTimes) { + this.log.warn("重试达到最大次数【{}】", maxRetryTimes); + //最后一次重试失败后,直接抛出异常,不再等待 + throw new RuntimeException("微信服务端异常,超出重试次数"); + } + + WxError error = e.getError(); + // -1 系统繁忙, 1000ms后重试 + if (error.getErrorCode() == -1) { + int sleepMillis = this.retrySleepMillis * (1 << retryTimes); + try { + this.log.warn("微信系统繁忙,{} ms 后重试(第{}次)", sleepMillis, retryTimes + 1); + Thread.sleep(sleepMillis); + } catch (InterruptedException e1) { + throw new RuntimeException(e1); + } + } else { + throw e; + } + } + } while (retryTimes++ < this.maxRetryTimes); + + this.log.warn("重试达到最大次数【{}】", this.maxRetryTimes); + throw new RuntimeException("微信服务端异常,超出重试次数"); + } + + public synchronized T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { + if (uri.indexOf("access_token=") != -1) { + throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); + } + String accessToken = getAccessToken(false); + + String uriWithAccessToken = uri; + uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken; + + try { + return executor.execute(this, uriWithAccessToken, data); + } catch (WxErrorException e) { + WxError error = e.getError(); + /* + * 发生以下情况时尝试刷新access_token + * 40001 获取access_token时AppSecret错误,或者access_token无效 + * 42001 access_token超时 + */ + if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) { + // 强制设置wxMpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token + this.getWxMpConfigStorage().expireAccessToken(); + if (this.getWxMpConfigStorage().autoRefreshToken()) { + return this.execute(executor, uri, data); + } + } + + if (error.getErrorCode() != 0) { + this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", uri, data, error); + throw new WxErrorException(error); + } + return null; + } catch (IOException e) { + this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[EXCEPTION]: {}", uri, data, e.getMessage()); + throw new RuntimeException(e); + } + } + + @Override + public WxMpConfigStorage getWxMpConfigStorage() { + return this.wxMpConfigStorage; + } + + @Override + public void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider) { + this.wxMpConfigStorage = wxConfigProvider; + this.initHttp(); + } + + @Override + public void setRetrySleepMillis(int retrySleepMillis) { + this.retrySleepMillis = retrySleepMillis; + } + + @Override + public void setMaxRetryTimes(int maxRetryTimes) { + this.maxRetryTimes = maxRetryTimes; + } + + @Override + public WxMpKefuService getKefuService() { + return this.kefuService; + } + + @Override + public WxMpMaterialService getMaterialService() { + return this.materialService; + } + + @Override + public WxMpMenuService getMenuService() { + return this.menuService; + } + + @Override + public WxMpUserService getUserService() { + return this.userService; + } + + @Override + public WxMpUserTagService getUserTagService() { + return this.tagService; + } + + @Override + public WxMpQrcodeService getQrcodeService() { + return this.qrCodeService; + } + + @Override + public WxMpCardService getCardService() { + return this.cardService; + } + + @Override + public WxMpDataCubeService getDataCubeService() { + return this.dataCubeService; + } + + @Override + public WxMpUserBlacklistService getBlackListService() { + return this.blackListService; + } + + @Override + public WxMpStoreService getStoreService() { + return this.storeService; + } + + @Override + public WxMpTemplateMsgService getTemplateMsgService() { + return this.templateMsgService; + } + + @Override + public WxMpDeviceService getDeviceService() { + return this.deviceService; + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpServiceImpl.java index 5e6f863a..8c8085da 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpServiceImpl.java @@ -1,73 +1,58 @@ package me.chanjar.weixin.mp.api.impl.apache; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import me.chanjar.weixin.common.bean.WxAccessToken; -import me.chanjar.weixin.common.bean.WxJsapiSignature; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.session.StandardSessionManager; -import me.chanjar.weixin.common.session.WxSessionManager; -import me.chanjar.weixin.common.util.RandomUtils; -import me.chanjar.weixin.common.util.crypto.SHA1; -import me.chanjar.weixin.common.util.http.*; -import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; -import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; -import me.chanjar.weixin.mp.api.*; -import me.chanjar.weixin.mp.api.impl.*; -import me.chanjar.weixin.mp.bean.*; -import me.chanjar.weixin.mp.bean.result.*; +import java.io.IOException; +import java.util.concurrent.locks.Lock; + 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.impl.client.BasicResponseHandler; import org.apache.http.impl.client.CloseableHttpClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.concurrent.locks.Lock; -public class WxMpServiceImpl implements WxMpService,RequestHttp { - - private static final JsonParser JSON_PARSER = new JsonParser(); +import me.chanjar.weixin.common.bean.WxAccessToken; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; +import me.chanjar.weixin.mp.api.WxMpConfigStorage; +import me.chanjar.weixin.mp.api.impl.AbstractWxMpService; - protected final Logger log = LoggerFactory.getLogger(this.getClass()); - protected WxSessionManager sessionManager = new StandardSessionManager(); - private WxMpConfigStorage wxMpConfigStorage; - private WxMpKefuService kefuService = new WxMpKefuServiceImpl(this); - private WxMpMaterialService materialService = new WxMpMaterialServiceImpl(this); - private WxMpMenuService menuService = new WxMpMenuServiceImpl(this); - private WxMpUserService userService = new WxMpUserServiceImpl(this); - private WxMpUserTagService tagService = new WxMpUserTagServiceImpl(this); - private WxMpQrcodeService qrCodeService = new WxMpQrcodeServiceImpl(this); - private WxMpCardService cardService = new WxMpCardServiceImpl(this); - private WxMpStoreService storeService = new WxMpStoreServiceImpl(this); - private WxMpDataCubeService dataCubeService = new WxMpDataCubeServiceImpl(this); - private WxMpUserBlacklistService blackListService = new WxMpUserBlacklistServiceImpl(this); - private WxMpTemplateMsgService templateMsgService = new WxMpTemplateMsgServiceImpl(this); - private WxMpDeviceService deviceService = new WxMpDeviceServiceImpl(this); +/** + * apache-http方式实现 + */ +public class WxMpServiceImpl extends AbstractWxMpService { private CloseableHttpClient httpClient; private HttpHost httpProxy; - private int retrySleepMillis = 1000; - private int maxRetryTimes = 5; @Override - public boolean checkSignature(String timestamp, String nonce, String signature) { - try { - return SHA1.gen(this.getWxMpConfigStorage().getToken(), timestamp, nonce) - .equals(signature); - } catch (Exception e) { - return false; - } + public CloseableHttpClient getRequestHttpClient() { + return httpClient; } @Override - public String getAccessToken() throws WxErrorException { - return getAccessToken(false); + public HttpHost getRequestHttpProxy() { + return httpProxy; + } + + @Override + public void initHttp() { + WxMpConfigStorage configStorage = this.getWxMpConfigStorage(); + ApacheHttpClientBuilder apacheHttpClientBuilder = configStorage.getApacheHttpClientBuilder(); + if (null == apacheHttpClientBuilder) { + apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get(); + } + + apacheHttpClientBuilder.httpProxyHost(configStorage.getHttpProxyHost()) + .httpProxyPort(configStorage.getHttpProxyPort()) + .httpProxyUsername(configStorage.getHttpProxyUsername()) + .httpProxyPassword(configStorage.getHttpProxyPassword()); + + if (configStorage.getHttpProxyHost() != null && configStorage.getHttpProxyPort() > 0) { + this.httpProxy = new HttpHost(configStorage.getHttpProxyHost(), configStorage.getHttpProxyPort()); + } + + this.httpClient = apacheHttpClientBuilder.build(); } @Override @@ -86,11 +71,11 @@ public class WxMpServiceImpl implements WxMpService,RequestHttp { + this.getWxMpConfigStorage().getSecret(); try { HttpGet httpGet = new HttpGet(url); - if (this.httpProxy != null) { - RequestConfig config = RequestConfig.custom().setProxy(this.httpProxy).build(); + if (this.getRequestHttpProxy() != null) { + RequestConfig config = RequestConfig.custom().setProxy(this.getRequestHttpProxy()).build(); httpGet.setConfig(config); } - try (CloseableHttpResponse response = getHttpclient().execute(httpGet)) { + try (CloseableHttpResponse response = getRequestHttpClient().execute(httpGet)) { String resultContent = new BasicResponseHandler().handleResponse(response); WxError error = WxError.fromJson(resultContent); if (error.getErrorCode() != 0) { @@ -111,425 +96,4 @@ public class WxMpServiceImpl implements WxMpService,RequestHttp { } return this.getWxMpConfigStorage().getAccessToken(); } - - @Override - public String getJsapiTicket() throws WxErrorException { - return getJsapiTicket(false); - } - - @Override - public String getJsapiTicket(boolean forceRefresh) throws WxErrorException { - Lock lock = this.getWxMpConfigStorage().getJsapiTicketLock(); - try { - lock.lock(); - - if (forceRefresh) { - this.getWxMpConfigStorage().expireJsapiTicket(); - } - - if (this.getWxMpConfigStorage().isJsapiTicketExpired()) { - String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi"; - String responseContent = execute(new SimpleGetRequestExecutor(), url, null); - JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); - JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); - String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); - int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); - this.getWxMpConfigStorage().updateJsapiTicket(jsapiTicket, expiresInSeconds); - } - } finally { - lock.unlock(); - } - return this.getWxMpConfigStorage().getJsapiTicket(); - } - - @Override - public WxJsapiSignature createJsapiSignature(String url) throws WxErrorException { - long timestamp = System.currentTimeMillis() / 1000; - String noncestr = RandomUtils.getRandomStr(); - String jsapiTicket = getJsapiTicket(false); - String signature = SHA1.genWithAmple("jsapi_ticket=" + jsapiTicket, - "noncestr=" + noncestr, "timestamp=" + timestamp, "url=" + url); - WxJsapiSignature jsapiSignature = new WxJsapiSignature(); - jsapiSignature.setAppId(this.getWxMpConfigStorage().getAppId()); - jsapiSignature.setTimestamp(timestamp); - jsapiSignature.setNonceStr(noncestr); - jsapiSignature.setUrl(url); - jsapiSignature.setSignature(signature); - return jsapiSignature; - } - - @Override - public WxMpMassUploadResult massNewsUpload(WxMpMassNews news) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/media/uploadnews"; - String responseContent = this.post(url, news.toJson()); - return WxMpMassUploadResult.fromJson(responseContent); - } - - @Override - public WxMpMassUploadResult massVideoUpload(WxMpMassVideo video) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/media/uploadvideo"; - String responseContent = this.post(url, video.toJson()); - return WxMpMassUploadResult.fromJson(responseContent); - } - - @Override - public WxMpMassSendResult massGroupMessageSend(WxMpMassTagMessage message) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall"; - String responseContent = this.post(url, message.toJson()); - return WxMpMassSendResult.fromJson(responseContent); - } - - @Override - public WxMpMassSendResult massOpenIdsMessageSend(WxMpMassOpenIdsMessage message) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/message/mass/send"; - String responseContent = this.post(url, message.toJson()); - return WxMpMassSendResult.fromJson(responseContent); - } - - @Override - public WxMpMassSendResult massMessagePreview(WxMpMassPreviewMessage wxMpMassPreviewMessage) throws Exception { - String url = "https://api.weixin.qq.com/cgi-bin/message/mass/preview"; - String responseContent = this.post(url, wxMpMassPreviewMessage.toJson()); - return WxMpMassSendResult.fromJson(responseContent); - } - - @Override - public String shortUrl(String long_url) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/shorturl"; - JsonObject o = new JsonObject(); - o.addProperty("action", "long2short"); - o.addProperty("long_url", long_url); - String responseContent = this.post(url, o.toString()); - JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); - return tmpJsonElement.getAsJsonObject().get("short_url").getAsString(); - } - - @Override - public WxMpSemanticQueryResult semanticQuery(WxMpSemanticQuery semanticQuery) throws WxErrorException { - String url = "https://api.weixin.qq.com/semantic/semproxy/search"; - String responseContent = this.post(url, semanticQuery.toJson()); - return WxMpSemanticQueryResult.fromJson(responseContent); - } - - @Override - public String oauth2buildAuthorizationUrl(String redirectURI, String scope, String state) { - StringBuilder url = new StringBuilder(); - url.append("https://open.weixin.qq.com/connect/oauth2/authorize?"); - url.append("appid=").append(this.getWxMpConfigStorage().getAppId()); - url.append("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectURI)); - url.append("&response_type=code"); - url.append("&scope=").append(scope); - if (state != null) { - url.append("&state=").append(state); - } - url.append("#wechat_redirect"); - return url.toString(); - } - - @Override - public String buildQrConnectUrl(String redirectURI, String scope, - String state) { - StringBuilder url = new StringBuilder(); - url.append("https://open.weixin.qq.com/connect/qrconnect?"); - url.append("appid=").append(this.getWxMpConfigStorage().getAppId()); - url.append("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectURI)); - url.append("&response_type=code"); - url.append("&scope=").append(scope); - if (state != null) { - url.append("&state=").append(state); - } - - url.append("#wechat_redirect"); - return url.toString(); - } - - private WxMpOAuth2AccessToken getOAuth2AccessToken(StringBuilder url) throws WxErrorException { - try { - RequestExecutor executor = new SimpleGetRequestExecutor(); - String responseText = executor.execute(this, url.toString(), null); - return WxMpOAuth2AccessToken.fromJson(responseText); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public WxMpOAuth2AccessToken oauth2getAccessToken(String code) throws WxErrorException { - StringBuilder url = new StringBuilder(); - url.append("https://api.weixin.qq.com/sns/oauth2/access_token?"); - url.append("appid=").append(this.getWxMpConfigStorage().getAppId()); - url.append("&secret=").append(this.getWxMpConfigStorage().getSecret()); - url.append("&code=").append(code); - url.append("&grant_type=authorization_code"); - - return this.getOAuth2AccessToken(url); - } - - @Override - public WxMpOAuth2AccessToken oauth2refreshAccessToken(String refreshToken) throws WxErrorException { - StringBuilder url = new StringBuilder(); - url.append("https://api.weixin.qq.com/sns/oauth2/refresh_token?"); - url.append("appid=").append(this.getWxMpConfigStorage().getAppId()); - url.append("&grant_type=refresh_token"); - url.append("&refresh_token=").append(refreshToken); - - return this.getOAuth2AccessToken(url); - } - - @Override - public WxMpUser oauth2getUserInfo(WxMpOAuth2AccessToken oAuth2AccessToken, String lang) throws WxErrorException { - StringBuilder url = new StringBuilder(); - url.append("https://api.weixin.qq.com/sns/userinfo?"); - url.append("access_token=").append(oAuth2AccessToken.getAccessToken()); - url.append("&openid=").append(oAuth2AccessToken.getOpenId()); - if (lang == null) { - url.append("&lang=zh_CN"); - } else { - url.append("&lang=").append(lang); - } - - try { - RequestExecutor executor = new SimpleGetRequestExecutor(); - String responseText = executor.execute(this, url.toString(), null); - return WxMpUser.fromJson(responseText); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public boolean oauth2validateAccessToken(WxMpOAuth2AccessToken oAuth2AccessToken) { - StringBuilder url = new StringBuilder(); - url.append("https://api.weixin.qq.com/sns/auth?"); - url.append("access_token=").append(oAuth2AccessToken.getAccessToken()); - url.append("&openid=").append(oAuth2AccessToken.getOpenId()); - - try { - RequestExecutor executor = new SimpleGetRequestExecutor(); - executor.execute(this, url.toString(), null); - } catch (IOException e) { - throw new RuntimeException(e); - } catch (WxErrorException e) { - return false; - } - return true; - } - - @Override - public String[] getCallbackIP() throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/getcallbackip"; - String responseContent = get(url, null); - JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); - JsonArray ipList = tmpJsonElement.getAsJsonObject().get("ip_list").getAsJsonArray(); - String[] ipArray = new String[ipList.size()]; - for (int i = 0; i < ipList.size(); i++) { - ipArray[i] = ipList.get(i).getAsString(); - } - return ipArray; - } - - @Override - public String get(String url, String queryParam) throws WxErrorException { - return execute(new SimpleGetRequestExecutor(), url, queryParam); - } - - @Override - public String post(String url, String postData) throws WxErrorException { - return execute(new SimplePostRequestExecutor(), url, postData); - } - - /** - * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 - */ - @Override - public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { - int retryTimes = 0; - do { - try { - T result = executeInternal(executor, uri, data); - this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", uri, data, result); - return result; - } catch (WxErrorException e) { - if (retryTimes + 1 > this.maxRetryTimes) { - this.log.warn("重试达到最大次数【{}】", maxRetryTimes); - //最后一次重试失败后,直接抛出异常,不再等待 - throw new RuntimeException("微信服务端异常,超出重试次数"); - } - - WxError error = e.getError(); - // -1 系统繁忙, 1000ms后重试 - if (error.getErrorCode() == -1) { - int sleepMillis = this.retrySleepMillis * (1 << retryTimes); - try { - this.log.warn("微信系统繁忙,{} ms 后重试(第{}次)", sleepMillis, retryTimes + 1); - Thread.sleep(sleepMillis); - } catch (InterruptedException e1) { - throw new RuntimeException(e1); - } - } else { - throw e; - } - } - } while (retryTimes++ < this.maxRetryTimes); - - this.log.warn("重试达到最大次数【{}】", this.maxRetryTimes); - throw new RuntimeException("微信服务端异常,超出重试次数"); - } - - public synchronized T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { - if (uri.indexOf("access_token=") != -1) { - throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); - } - String accessToken = getAccessToken(false); - - String uriWithAccessToken = uri; - uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken; - - try { - return executor.execute(this, uriWithAccessToken, data); - } catch (WxErrorException e) { - WxError error = e.getError(); - /* - * 发生以下情况时尝试刷新access_token - * 40001 获取access_token时AppSecret错误,或者access_token无效 - * 42001 access_token超时 - */ - if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) { - // 强制设置wxMpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token - this.getWxMpConfigStorage().expireAccessToken(); - if (this.getWxMpConfigStorage().autoRefreshToken()) { - return this.execute(executor, uri, data); - } - } - - if (error.getErrorCode() != 0) { - this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", uri, data, error); - throw new WxErrorException(error); - } - return null; - } catch (IOException e) { - this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[EXCEPTION]: {}", uri, data, e.getMessage()); - throw new RuntimeException(e); - } - } - - //@Override - public HttpHost getHttpProxy() { - return this.httpProxy; - } - - //@Override - public CloseableHttpClient getHttpclient() { - return this.httpClient; - } - - private void initHttpClient() { - WxMpConfigStorage configStorage = this.getWxMpConfigStorage(); - ApacheHttpClientBuilder apacheHttpClientBuilder = configStorage.getApacheHttpClientBuilder(); - if (null == apacheHttpClientBuilder) { - apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get(); - } - - apacheHttpClientBuilder.httpProxyHost(configStorage.getHttpProxyHost()) - .httpProxyPort(configStorage.getHttpProxyPort()) - .httpProxyUsername(configStorage.getHttpProxyUsername()) - .httpProxyPassword(configStorage.getHttpProxyPassword()); - - if (configStorage.getHttpProxyHost() != null && configStorage.getHttpProxyPort() > 0) { - this.httpProxy = new HttpHost(configStorage.getHttpProxyHost(), configStorage.getHttpProxyPort()); - } - - this.httpClient = apacheHttpClientBuilder.build(); - } - - @Override - public WxMpConfigStorage getWxMpConfigStorage() { - return this.wxMpConfigStorage; - } - - @Override - public void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider) { - this.wxMpConfigStorage = wxConfigProvider; - this.initHttpClient(); - } - - @Override - public void setRetrySleepMillis(int retrySleepMillis) { - this.retrySleepMillis = retrySleepMillis; - } - - @Override - public void setMaxRetryTimes(int maxRetryTimes) { - this.maxRetryTimes = maxRetryTimes; - } - - @Override - public WxMpKefuService getKefuService() { - return this.kefuService; - } - - @Override - public WxMpMaterialService getMaterialService() { - return this.materialService; - } - - @Override - public WxMpMenuService getMenuService() { - return this.menuService; - } - - @Override - public WxMpUserService getUserService() { - return this.userService; - } - - @Override - public WxMpUserTagService getUserTagService() { - return this.tagService; - } - - @Override - public WxMpQrcodeService getQrcodeService() { - return this.qrCodeService; - } - - @Override - public WxMpCardService getCardService() { - return this.cardService; - } - - @Override - public WxMpDataCubeService getDataCubeService() { - return this.dataCubeService; - } - - @Override - public WxMpUserBlacklistService getBlackListService() { - return this.blackListService; - } - - @Override - public WxMpStoreService getStoreService() { - return this.storeService; - } - - @Override - public WxMpTemplateMsgService getTemplateMsgService() { - return this.templateMsgService; - } - - @Override - public WxMpDeviceService getDeviceService() { - return this.deviceService; - } - - @Override - public Object getRequestHttpClient() { - return this.httpClient; - } - - @Override - public Object getRequestHttpProxy() { - return this.httpProxy; - } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpServiceImpl.java index fa342f66..0c4bdf81 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/jodd/WxMpServiceImpl.java @@ -1,56 +1,35 @@ package me.chanjar.weixin.mp.api.impl.jodd; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; + import jodd.http.*; import jodd.http.net.SocketHttpConnectionProvider; import me.chanjar.weixin.common.bean.WxAccessToken; -import me.chanjar.weixin.common.bean.WxJsapiSignature; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.session.StandardSessionManager; -import me.chanjar.weixin.common.session.WxSessionManager; -import me.chanjar.weixin.common.util.RandomUtils; -import me.chanjar.weixin.common.util.crypto.SHA1; -import me.chanjar.weixin.common.util.http.*; import me.chanjar.weixin.mp.api.*; import me.chanjar.weixin.mp.api.impl.*; -import me.chanjar.weixin.mp.bean.*; -import me.chanjar.weixin.mp.bean.result.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import java.io.IOException; import java.util.concurrent.locks.Lock; -public class WxMpServiceImpl implements WxMpService,RequestHttp { - - private static final JsonParser JSON_PARSER = new JsonParser(); - - protected final Logger log = LoggerFactory.getLogger(this.getClass()); - protected WxSessionManager sessionManager = new StandardSessionManager(); - private WxMpConfigStorage wxMpConfigStorage; - private WxMpKefuService kefuService = new WxMpKefuServiceImpl(this); - private WxMpMaterialService materialService = new WxMpMaterialServiceImpl(this); - private WxMpMenuService menuService = new WxMpMenuServiceImpl(this); - private WxMpUserService userService = new WxMpUserServiceImpl(this); - private WxMpUserTagService tagService = new WxMpUserTagServiceImpl(this); - private WxMpQrcodeService qrCodeService = new WxMpQrcodeServiceImpl(this); - private WxMpCardService cardService = new WxMpCardServiceImpl(this); - private WxMpStoreService storeService = new WxMpStoreServiceImpl(this); - private WxMpDataCubeService dataCubeService = new WxMpDataCubeServiceImpl(this); - private WxMpUserBlacklistService blackListService = new WxMpUserBlacklistServiceImpl(this); - private WxMpTemplateMsgService templateMsgService = new WxMpTemplateMsgServiceImpl(this); - private WxMpDeviceService deviceService = new WxMpDeviceServiceImpl(this); - +/** + * jodd-http方式实现 + */ +public class WxMpServiceImpl extends AbstractWxMpService { private HttpConnectionProvider httpClient; private ProxyInfo httpProxy; - private int retrySleepMillis = 1000; - private int maxRetryTimes = 5; - private void initHttpClient() { + @Override + public HttpConnectionProvider getRequestHttpClient() { + return httpClient; + } + + @Override + public ProxyInfo getRequestHttpProxy() { + return httpProxy; + } + + @Override + public void initHttp() { WxMpConfigStorage configStorage = this.getWxMpConfigStorage(); if (configStorage.getHttpProxyHost() != null && configStorage.getHttpProxyPort() > 0) { @@ -60,20 +39,7 @@ public class WxMpServiceImpl implements WxMpService,RequestHttp { httpClient = JoddHttp.httpConnectionProvider; } - @Override - public boolean checkSignature(String timestamp, String nonce, String signature) { - try { - return SHA1.gen(this.getWxMpConfigStorage().getToken(), timestamp, nonce) - .equals(signature); - } catch (Exception e) { - return false; - } - } - @Override - public String getAccessToken() throws WxErrorException { - return getAccessToken(false); - } @Override public String getAccessToken(boolean forceRefresh) throws WxErrorException { @@ -91,9 +57,9 @@ public class WxMpServiceImpl implements WxMpService,RequestHttp { + this.getWxMpConfigStorage().getSecret(); HttpRequest request = HttpRequest.get(url); - if (this.httpProxy != null) { + if (this.getRequestHttpProxy() != null) { SocketHttpConnectionProvider provider = new SocketHttpConnectionProvider(); - provider.useProxy(httpProxy); + provider.useProxy(getRequestHttpProxy()); request.withConnectionProvider(provider); } HttpResponse response = request.send(); @@ -111,406 +77,4 @@ public class WxMpServiceImpl implements WxMpService,RequestHttp { } return this.getWxMpConfigStorage().getAccessToken(); } - - @Override - public String getJsapiTicket() throws WxErrorException { - return getJsapiTicket(false); - } - - @Override - public String getJsapiTicket(boolean forceRefresh) throws WxErrorException { - Lock lock = this.getWxMpConfigStorage().getJsapiTicketLock(); - try { - lock.lock(); - - if (forceRefresh) { - this.getWxMpConfigStorage().expireJsapiTicket(); - } - - if (this.getWxMpConfigStorage().isJsapiTicketExpired()) { - String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi"; - String responseContent = execute(new SimpleGetRequestExecutor(), url, null); - JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); - JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); - String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); - int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); - this.getWxMpConfigStorage().updateJsapiTicket(jsapiTicket, expiresInSeconds); - } - } finally { - lock.unlock(); - } - return this.getWxMpConfigStorage().getJsapiTicket(); - } - - @Override - public WxJsapiSignature createJsapiSignature(String url) throws WxErrorException { - long timestamp = System.currentTimeMillis() / 1000; - String noncestr = RandomUtils.getRandomStr(); - String jsapiTicket = getJsapiTicket(false); - String signature = SHA1.genWithAmple("jsapi_ticket=" + jsapiTicket, - "noncestr=" + noncestr, "timestamp=" + timestamp, "url=" + url); - WxJsapiSignature jsapiSignature = new WxJsapiSignature(); - jsapiSignature.setAppId(this.getWxMpConfigStorage().getAppId()); - jsapiSignature.setTimestamp(timestamp); - jsapiSignature.setNonceStr(noncestr); - jsapiSignature.setUrl(url); - jsapiSignature.setSignature(signature); - return jsapiSignature; - } - - @Override - public WxMpMassUploadResult massNewsUpload(WxMpMassNews news) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/media/uploadnews"; - String responseContent = this.post(url, news.toJson()); - return WxMpMassUploadResult.fromJson(responseContent); - } - - @Override - public WxMpMassUploadResult massVideoUpload(WxMpMassVideo video) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/media/uploadvideo"; - String responseContent = this.post(url, video.toJson()); - return WxMpMassUploadResult.fromJson(responseContent); - } - - @Override - public WxMpMassSendResult massGroupMessageSend(WxMpMassTagMessage message) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall"; - String responseContent = this.post(url, message.toJson()); - return WxMpMassSendResult.fromJson(responseContent); - } - - @Override - public WxMpMassSendResult massOpenIdsMessageSend(WxMpMassOpenIdsMessage message) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/message/mass/send"; - String responseContent = this.post(url, message.toJson()); - return WxMpMassSendResult.fromJson(responseContent); - } - - @Override - public WxMpMassSendResult massMessagePreview(WxMpMassPreviewMessage wxMpMassPreviewMessage) throws Exception { - String url = "https://api.weixin.qq.com/cgi-bin/message/mass/preview"; - String responseContent = this.post(url, wxMpMassPreviewMessage.toJson()); - return WxMpMassSendResult.fromJson(responseContent); - } - - @Override - public String shortUrl(String long_url) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/shorturl"; - JsonObject o = new JsonObject(); - o.addProperty("action", "long2short"); - o.addProperty("long_url", long_url); - String responseContent = this.post(url, o.toString()); - JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); - return tmpJsonElement.getAsJsonObject().get("short_url").getAsString(); - } - - @Override - public WxMpSemanticQueryResult semanticQuery(WxMpSemanticQuery semanticQuery) throws WxErrorException { - String url = "https://api.weixin.qq.com/semantic/semproxy/search"; - String responseContent = this.post(url, semanticQuery.toJson()); - return WxMpSemanticQueryResult.fromJson(responseContent); - } - - @Override - public String oauth2buildAuthorizationUrl(String redirectURI, String scope, String state) { - StringBuilder url = new StringBuilder(); - url.append("https://open.weixin.qq.com/connect/oauth2/authorize?"); - url.append("appid=").append(this.getWxMpConfigStorage().getAppId()); - url.append("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectURI)); - url.append("&response_type=code"); - url.append("&scope=").append(scope); - if (state != null) { - url.append("&state=").append(state); - } - url.append("#wechat_redirect"); - return url.toString(); - } - - @Override - public String buildQrConnectUrl(String redirectURI, String scope, - String state) { - StringBuilder url = new StringBuilder(); - url.append("https://open.weixin.qq.com/connect/qrconnect?"); - url.append("appid=").append(this.getWxMpConfigStorage().getAppId()); - url.append("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectURI)); - url.append("&response_type=code"); - url.append("&scope=").append(scope); - if (state != null) { - url.append("&state=").append(state); - } - - url.append("#wechat_redirect"); - return url.toString(); - } - - private WxMpOAuth2AccessToken getOAuth2AccessToken(StringBuilder url) throws WxErrorException { - try { - RequestExecutor executor = new SimpleGetRequestExecutor(); - String responseText = executor.execute(this, url.toString(), null); - return WxMpOAuth2AccessToken.fromJson(responseText); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public WxMpOAuth2AccessToken oauth2getAccessToken(String code) throws WxErrorException { - StringBuilder url = new StringBuilder(); - url.append("https://api.weixin.qq.com/sns/oauth2/access_token?"); - url.append("appid=").append(this.getWxMpConfigStorage().getAppId()); - url.append("&secret=").append(this.getWxMpConfigStorage().getSecret()); - url.append("&code=").append(code); - url.append("&grant_type=authorization_code"); - - return this.getOAuth2AccessToken(url); - } - - @Override - public WxMpOAuth2AccessToken oauth2refreshAccessToken(String refreshToken) throws WxErrorException { - StringBuilder url = new StringBuilder(); - url.append("https://api.weixin.qq.com/sns/oauth2/refresh_token?"); - url.append("appid=").append(this.getWxMpConfigStorage().getAppId()); - url.append("&grant_type=refresh_token"); - url.append("&refresh_token=").append(refreshToken); - - return this.getOAuth2AccessToken(url); - } - - @Override - public WxMpUser oauth2getUserInfo(WxMpOAuth2AccessToken oAuth2AccessToken, String lang) throws WxErrorException { - StringBuilder url = new StringBuilder(); - url.append("https://api.weixin.qq.com/sns/userinfo?"); - url.append("access_token=").append(oAuth2AccessToken.getAccessToken()); - url.append("&openid=").append(oAuth2AccessToken.getOpenId()); - if (lang == null) { - url.append("&lang=zh_CN"); - } else { - url.append("&lang=").append(lang); - } - - try { - RequestExecutor executor = new SimpleGetRequestExecutor(); - String responseText = executor.execute(this, url.toString(), null); - return WxMpUser.fromJson(responseText); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public boolean oauth2validateAccessToken(WxMpOAuth2AccessToken oAuth2AccessToken) { - StringBuilder url = new StringBuilder(); - url.append("https://api.weixin.qq.com/sns/auth?"); - url.append("access_token=").append(oAuth2AccessToken.getAccessToken()); - url.append("&openid=").append(oAuth2AccessToken.getOpenId()); - - try { - RequestExecutor executor = new SimpleGetRequestExecutor(); - executor.execute(this, url.toString(), null); - } catch (IOException e) { - throw new RuntimeException(e); - } catch (WxErrorException e) { - return false; - } - return true; - } - - @Override - public String[] getCallbackIP() throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/getcallbackip"; - String responseContent = get(url, null); - JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); - JsonArray ipList = tmpJsonElement.getAsJsonObject().get("ip_list").getAsJsonArray(); - String[] ipArray = new String[ipList.size()]; - for (int i = 0; i < ipList.size(); i++) { - ipArray[i] = ipList.get(i).getAsString(); - } - return ipArray; - } - - @Override - public String get(String url, String queryParam) throws WxErrorException { - return execute(new SimpleGetRequestExecutor(), url, queryParam); - } - - @Override - public String post(String url, String postData) throws WxErrorException { - return execute(new SimplePostRequestExecutor(), url, postData); - } - - //@Override - public HttpConnectionProvider getHttpclient() { - return this.httpClient; - } - - //@Override - public Object getHttpProxy() { - return null; - } - - /** - * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 - */ - public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { - int retryTimes = 0; - do { - try { - T result = executeInternal(executor, uri, data); - this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", uri, data, result); - return result; - } catch (WxErrorException e) { - if (retryTimes + 1 > this.maxRetryTimes) { - this.log.warn("重试达到最大次数【{}】", maxRetryTimes); - //最后一次重试失败后,直接抛出异常,不再等待 - throw new RuntimeException("微信服务端异常,超出重试次数"); - } - - WxError error = e.getError(); - // -1 系统繁忙, 1000ms后重试 - if (error.getErrorCode() == -1) { - int sleepMillis = this.retrySleepMillis * (1 << retryTimes); - try { - this.log.warn("微信系统繁忙,{} ms 后重试(第{}次)", sleepMillis, retryTimes + 1); - Thread.sleep(sleepMillis); - } catch (InterruptedException e1) { - throw new RuntimeException(e1); - } - } else { - throw e; - } - } - } while (retryTimes++ < this.maxRetryTimes); - - this.log.warn("重试达到最大次数【{}】", this.maxRetryTimes); - throw new RuntimeException("微信服务端异常,超出重试次数"); - } - - public synchronized T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { - if (uri.indexOf("access_token=") != -1) { - throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); - } - String accessToken = getAccessToken(false); - - String uriWithAccessToken = uri; - uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken; - - try { - return executor.execute(this, uriWithAccessToken, data); - } catch (WxErrorException e) { - WxError error = e.getError(); - /* - * 发生以下情况时尝试刷新access_token - * 40001 获取access_token时AppSecret错误,或者access_token无效 - * 42001 access_token超时 - */ - if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) { - // 强制设置wxMpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token - this.getWxMpConfigStorage().expireAccessToken(); - if (this.getWxMpConfigStorage().autoRefreshToken()) { - return this.execute(executor, uri, data); - } - } - - if (error.getErrorCode() != 0) { - this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", uri, data, error); - throw new WxErrorException(error); - } - return null; - } catch (IOException e) { - this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[EXCEPTION]: {}", uri, data, e.getMessage()); - throw new RuntimeException(e); - } - } - - @Override - public Object getRequestHttpClient() { - return this.httpClient; - } - - @Override - public Object getRequestHttpProxy() { - return this.httpProxy; - } - - - @Override - public WxMpConfigStorage getWxMpConfigStorage() { - return this.wxMpConfigStorage; - } - - @Override - public void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider) { - this.wxMpConfigStorage = wxConfigProvider; - this.initHttpClient(); - } - - @Override - public void setRetrySleepMillis(int retrySleepMillis) { - this.retrySleepMillis = retrySleepMillis; - } - - @Override - public void setMaxRetryTimes(int maxRetryTimes) { - this.maxRetryTimes = maxRetryTimes; - } - - @Override - public WxMpKefuService getKefuService() { - return this.kefuService; - } - - @Override - public WxMpMaterialService getMaterialService() { - return this.materialService; - } - - @Override - public WxMpMenuService getMenuService() { - return this.menuService; - } - - @Override - public WxMpUserService getUserService() { - return this.userService; - } - - @Override - public WxMpUserTagService getUserTagService() { - return this.tagService; - } - - @Override - public WxMpQrcodeService getQrcodeService() { - return this.qrCodeService; - } - - @Override - public WxMpCardService getCardService() { - return this.cardService; - } - - @Override - public WxMpDataCubeService getDataCubeService() { - return this.dataCubeService; - } - - @Override - public WxMpUserBlacklistService getBlackListService() { - return this.blackListService; - } - - @Override - public WxMpStoreService getStoreService() { - return this.storeService; - } - - @Override - public WxMpTemplateMsgService getTemplateMsgService() { - return this.templateMsgService; - } - - @Override - public WxMpDeviceService getDeviceService() { - return this.deviceService; - } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/okhttp/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/okhttp/WxMpServiceImpl.java new file mode 100644 index 00000000..2eebb5ff --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/okhttp/WxMpServiceImpl.java @@ -0,0 +1,96 @@ +package me.chanjar.weixin.mp.api.impl.okhttp; + +import java.io.IOException; +import java.util.concurrent.locks.Lock; + +import me.chanjar.weixin.common.bean.WxAccessToken; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; +import me.chanjar.weixin.mp.api.*; +import me.chanjar.weixin.mp.api.impl.*; +import okhttp3.*; + +public class WxMpServiceImpl extends AbstractWxMpService { + + + private ConnectionPool httpClient; + private OkhttpProxyInfo httpProxy; + + + @Override + public ConnectionPool getRequestHttpClient() { + return httpClient; + } + + @Override + public OkhttpProxyInfo getRequestHttpProxy() { + return httpProxy; + } + + + @Override + public String getAccessToken(boolean forceRefresh) throws WxErrorException { + Lock lock = this.getWxMpConfigStorage().getAccessTokenLock(); + try { + lock.lock(); + + if (forceRefresh) { + this.getWxMpConfigStorage().expireAccessToken(); + } + + if (this.getWxMpConfigStorage().isAccessTokenExpired()) { + String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" + + "&appid=" + this.getWxMpConfigStorage().getAppId() + "&secret=" + + this.getWxMpConfigStorage().getSecret(); + + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(httpClient); + //设置代理 + if (httpProxy != null) { + clientBuilder.proxy(getRequestHttpProxy().getProxy()); + } + //设置授权 + clientBuilder.authenticator(new Authenticator() { + @Override + public Request authenticate(Route route, Response response) throws IOException { + String credential = Credentials.basic(httpProxy.getProxyUsername(), httpProxy.getProxyPassword()); + return response.request().newBuilder() + .header("Authorization", credential) + .build(); + } + }); + //得到httpClient + OkHttpClient client = clientBuilder.build(); + + Request request =new Request.Builder().url(url).get().build(); + Response response =client.newCall(request).execute(); + String resultContent = response.body().toString(); + WxError error = WxError.fromJson(resultContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + WxAccessToken accessToken = WxAccessToken.fromJson(resultContent); + this.getWxMpConfigStorage().updateAccessToken(accessToken.getAccessToken(), + accessToken.getExpiresIn()); + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + lock.unlock(); + } + return this.getWxMpConfigStorage().getAccessToken(); + } + + @Override + public void initHttp() { + WxMpConfigStorage configStorage = this.getWxMpConfigStorage(); + + if (configStorage.getHttpProxyHost() != null && configStorage.getHttpProxyPort() > 0) { + httpProxy = new OkhttpProxyInfo(OkhttpProxyInfo.ProxyType.SOCKS5, configStorage.getHttpProxyHost(), configStorage.getHttpProxyPort(), configStorage.getHttpProxyUsername(), configStorage.getHttpProxyPassword()); + } + + httpClient = new ConnectionPool(); + } + + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialDeleteRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialDeleteRequestExecutor.java index ef3f31b6..473d1160 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialDeleteRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialDeleteRequestExecutor.java @@ -6,10 +6,14 @@ import jodd.http.HttpResponse; import jodd.http.ProxyInfo; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.AbstractRequestExecutor; import me.chanjar.weixin.common.util.http.RequestExecutor; import me.chanjar.weixin.common.util.http.RequestHttp; import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import okhttp3.*; + import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; @@ -21,7 +25,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -public class MaterialDeleteRequestExecutor implements RequestExecutor { +public class MaterialDeleteRequestExecutor extends AbstractRequestExecutor { public MaterialDeleteRequestExecutor() { @@ -29,25 +33,32 @@ public class MaterialDeleteRequestExecutor implements RequestExecutor params = new HashMap<>(); + params.put("media_id", materialId); + httpPost.setEntity(new StringEntity(WxGsonBuilder.create().toJson(params))); + try (CloseableHttpResponse response = httpclient.execute(httpPost)) { + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } else { + return true; + } + } finally { + httpPost.releaseConnection(); + } } - private Boolean executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, String materialId) throws WxErrorException, IOException { + @Override + public Boolean executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, String materialId) throws WxErrorException, IOException { HttpRequest request = HttpRequest.post(uri); if (proxyInfo != null) { provider.useProxy(proxyInfo); @@ -65,27 +76,35 @@ public class MaterialDeleteRequestExecutor implements RequestExecutor params = new HashMap<>(); - params.put("media_id", materialId); - httpPost.setEntity(new StringEntity(WxGsonBuilder.create().toJson(params))); - try (CloseableHttpResponse response = httpclient.execute(httpPost)) { - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } else { - return true; + //设置授权 + clientBuilder.authenticator(new Authenticator() { + @Override + public Request authenticate(Route route, Response response) throws IOException { + String credential = Credentials.basic(proxyInfo.getProxyUsername(), proxyInfo.getProxyPassword()); + return response.request().newBuilder() + .header("Authorization", credential) + .build(); } - } finally { - httpPost.releaseConnection(); + }); + //得到httpClient + OkHttpClient client = clientBuilder.build(); + + RequestBody requestBody = new FormBody.Builder().add("media_id", materialId).build(); + Request request = new Request.Builder().url(uri).post(requestBody).build(); + Response response = client.newCall(request).execute(); + String responseContent = response.body().toString(); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } else { + return true; } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialNewsInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialNewsInfoRequestExecutor.java index 87180067..8c36d16b 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialNewsInfoRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialNewsInfoRequestExecutor.java @@ -6,12 +6,16 @@ import jodd.http.HttpResponse; import jodd.http.ProxyInfo; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.AbstractRequestExecutor; import me.chanjar.weixin.common.util.http.RequestExecutor; import me.chanjar.weixin.common.util.http.RequestHttp; import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; 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 okhttp3.*; + import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; @@ -23,30 +27,13 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -public class MaterialNewsInfoRequestExecutor implements RequestExecutor { +public class MaterialNewsInfoRequestExecutor extends AbstractRequestExecutor { public MaterialNewsInfoRequestExecutor() { super(); } @Override - public WxMpMaterialNews execute(RequestHttp requestHttp, String uri, - String materialId) throws WxErrorException, IOException { - if (requestHttp.getRequestHttpClient() instanceof CloseableHttpClient) { - CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getRequestHttpClient(); - HttpHost httpProxy = (HttpHost) requestHttp.getRequestHttpProxy(); - return executeApache(httpClient, httpProxy, uri, materialId); - } - if (requestHttp.getRequestHttpClient() instanceof HttpConnectionProvider) { - HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getRequestHttpClient(); - ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getRequestHttpProxy(); - return executeJodd(provider, proxyInfo, uri, materialId); - } else { - //这里需要抛出异常,需要优化 - return null; - } - } - public WxMpMaterialNews executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String materialId) throws WxErrorException, IOException { HttpPost httpPost = new HttpPost(uri); if (httpProxy != null) { @@ -70,7 +57,7 @@ public class MaterialNewsInfoRequestExecutor implements RequestExecutor { +public class MaterialUploadRequestExecutor extends AbstractRequestExecutor { @Override - public WxMpMaterialUploadResult execute(RequestHttp requestHttp, String uri, WxMpMaterial material) throws WxErrorException, IOException { - if (requestHttp.getRequestHttpClient() instanceof CloseableHttpClient) { - CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getRequestHttpClient(); - HttpHost httpProxy = (HttpHost) requestHttp.getRequestHttpProxy(); - return executeApache(httpClient, httpProxy, uri, material); - } - if (requestHttp.getRequestHttpClient() instanceof HttpConnectionProvider) { - HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getRequestHttpClient(); - ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getRequestHttpProxy(); - return executeJodd(provider, proxyInfo, uri, material); - } else { - //这里需要抛出异常,需要优化 - return null; - } - } - - private WxMpMaterialUploadResult executeJodd(HttpConnectionProvider provider, ProxyInfo httpProxy, String uri, WxMpMaterial material) throws WxErrorException, IOException { + public WxMpMaterialUploadResult executeJodd(HttpConnectionProvider provider, ProxyInfo httpProxy, String uri, WxMpMaterial material) throws WxErrorException, IOException { HttpRequest request = HttpRequest.post(uri); if (httpProxy != null) { provider.useProxy(httpProxy); @@ -76,8 +64,56 @@ public class MaterialUploadRequestExecutor implements RequestExecutor form = material.getForm(); + if (material.getForm() != null) { + bodyBuilder.addFormDataPart("description", WxGsonBuilder.create().toJson(form)); + } + RequestBody body =bodyBuilder.build(); + Request request = new Request.Builder().url(uri).post(body).build(); + Response response = client.newCall(request).execute(); + String responseContent = response.body().toString(); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } else { + return WxMpMaterialUploadResult.fromJson(responseContent); + } + } + + @Override + public WxMpMaterialUploadResult executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, + WxMpMaterial material) throws WxErrorException, IOException { HttpPost httpPost = new HttpPost(uri); if (httpProxy != null) { RequestConfig response = RequestConfig.custom().setProxy(httpProxy).build(); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVideoInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVideoInfoRequestExecutor.java index fb581892..22020ce1 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVideoInfoRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVideoInfoRequestExecutor.java @@ -6,11 +6,16 @@ import jodd.http.HttpResponse; import jodd.http.ProxyInfo; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.AbstractRequestExecutor; import me.chanjar.weixin.common.util.http.RequestExecutor; import me.chanjar.weixin.common.util.http.RequestHttp; import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult; import me.chanjar.weixin.mp.bean.material.WxMpMaterialVideoInfoResult; +import okhttp3.*; + import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; @@ -22,31 +27,14 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -public class MaterialVideoInfoRequestExecutor implements RequestExecutor { +public class MaterialVideoInfoRequestExecutor extends AbstractRequestExecutor { public MaterialVideoInfoRequestExecutor() { super(); } @Override - public WxMpMaterialVideoInfoResult execute(RequestHttp requestHttp, String uri, String materialId) throws WxErrorException, IOException { - if (requestHttp.getRequestHttpClient() instanceof CloseableHttpClient) { - CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getRequestHttpClient(); - HttpHost httpProxy = (HttpHost) requestHttp.getRequestHttpProxy(); - return executeApache(httpClient, httpProxy, uri, materialId); - } - if (requestHttp.getRequestHttpClient() instanceof HttpConnectionProvider) { - HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getRequestHttpClient(); - ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getRequestHttpProxy(); - return executeJodd(provider, proxyInfo, uri, materialId); - } else { - //这里需要抛出异常,需要优化 - return null; - } - } - - - private WxMpMaterialVideoInfoResult executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, String materialId) throws WxErrorException, IOException { + public WxMpMaterialVideoInfoResult executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, String materialId) throws WxErrorException, IOException { HttpRequest request = HttpRequest.post(uri); if (proxyInfo != null) { provider.useProxy(proxyInfo); @@ -64,8 +52,41 @@ public class MaterialVideoInfoRequestExecutor implements RequestExecutor { - +public class MaterialVoiceAndImageDownloadRequestExecutor extends AbstractRequestExecutor { public MaterialVoiceAndImageDownloadRequestExecutor() { super(); @@ -36,24 +40,9 @@ public class MaterialVoiceAndImageDownloadRequestExecutor implements RequestExec super(); } - @Override - public InputStream execute(RequestHttp requestHttp, String uri, String materialId) throws WxErrorException, IOException { - if (requestHttp.getRequestHttpClient() instanceof CloseableHttpClient) { - CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getRequestHttpClient(); - HttpHost httpProxy = (HttpHost) requestHttp.getRequestHttpProxy(); - return executeApache(httpClient, httpProxy, uri, materialId); - } - if (requestHttp.getRequestHttpClient() instanceof HttpConnectionProvider) { - HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getRequestHttpClient(); - ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getRequestHttpProxy(); - return executeJodd(provider, proxyInfo, uri, materialId); - } else { - //这里需要抛出异常,需要优化 - return null; - } - } - private InputStream executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, String materialId) throws WxErrorException, IOException { + @Override + public InputStream executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, String materialId) throws WxErrorException, IOException { HttpRequest request = HttpRequest.post(uri); if (proxyInfo != null) { provider.useProxy(proxyInfo); @@ -81,8 +70,51 @@ public class MaterialVoiceAndImageDownloadRequestExecutor implements RequestExec } - private InputStream executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, - String materialId) throws WxErrorException, IOException { + @Override + public InputStream executeOkhttp(ConnectionPool pool, final OkhttpProxyInfo proxyInfo, String uri, String materialId) throws WxErrorException, IOException { + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(pool); + //设置代理 + if (proxyInfo != null) { + clientBuilder.proxy(proxyInfo.getProxy()); + } + //设置授权 + clientBuilder.authenticator(new Authenticator() { + @Override + public Request authenticate(Route route, Response response) throws IOException { + String credential = Credentials.basic(proxyInfo.getProxyUsername(), proxyInfo.getProxyPassword()); + return response.request().newBuilder() + .header("Authorization", credential) + .build(); + } + }); + //得到httpClient + OkHttpClient client = clientBuilder.build(); + + RequestBody requestBody = new FormBody.Builder().add("media_id", materialId).build(); + Request request = new Request.Builder().url(uri).get().post(requestBody).build(); + Response response = client.newCall(request).execute(); + + try (InputStream inputStream = new ByteArrayInputStream(response.body().bytes())) { + // 下载媒体文件出错 + byte[] responseContent = IOUtils.toByteArray(inputStream); + String responseContentString = new String(responseContent, "UTF-8"); + if (responseContentString.length() < 100) { + 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); + } + } + + @Override + public InputStream executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, + String materialId) throws WxErrorException, IOException { HttpPost httpPost = new HttpPost(uri); if (httpProxy != null) { RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MediaImgUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MediaImgUploadRequestExecutor.java index c22bc310..51f283e6 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MediaImgUploadRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MediaImgUploadRequestExecutor.java @@ -4,12 +4,19 @@ import jodd.http.HttpConnectionProvider; import jodd.http.HttpRequest; import jodd.http.HttpResponse; import jodd.http.ProxyInfo; +import jodd.util.MimeTypes; import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.fs.FileUtils; +import me.chanjar.weixin.common.util.http.AbstractRequestExecutor; import me.chanjar.weixin.common.util.http.RequestExecutor; import me.chanjar.weixin.common.util.http.RequestHttp; import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult; +import okhttp3.*; + import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; @@ -20,34 +27,20 @@ import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.impl.client.CloseableHttpClient; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.util.UUID; /** * @author miller */ -public class MediaImgUploadRequestExecutor implements RequestExecutor { - - @Override - public WxMediaImgUploadResult execute(RequestHttp requestHttp, String uri, File data) throws WxErrorException, IOException { - if (requestHttp.getRequestHttpClient() instanceof CloseableHttpClient) { - CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getRequestHttpClient(); - HttpHost httpProxy = (HttpHost) requestHttp.getRequestHttpProxy(); - return executeApache(httpClient, httpProxy, uri, data); - } - if (requestHttp.getRequestHttpClient() instanceof HttpConnectionProvider) { - HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getRequestHttpClient(); - ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getRequestHttpProxy(); - return executeJodd(provider, proxyInfo, uri, data); - } else { - //这里需要抛出异常,需要优化 - return null; - } - - } +public class MediaImgUploadRequestExecutor extends AbstractRequestExecutor { - private WxMediaImgUploadResult executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, File data) throws WxErrorException, IOException { + @Override + public WxMediaImgUploadResult executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, File data) throws WxErrorException, IOException { if (data == null) { throw new WxErrorException(WxError.newBuilder().setErrorMsg("文件对象为空").build()); } @@ -69,8 +62,43 @@ public class MediaImgUploadRequestExecutor implements RequestExecutor { - - @Override - public File execute(RequestHttp requestHttp, String uri, - WxMpQrCodeTicket ticket) throws WxErrorException, IOException { - if (requestHttp.getRequestHttpClient() instanceof CloseableHttpClient) { - CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getRequestHttpClient(); - HttpHost httpProxy = (HttpHost) requestHttp.getRequestHttpProxy(); - return executeApache(httpClient, httpProxy, uri, ticket); - } - if (requestHttp.getRequestHttpClient() instanceof HttpConnectionProvider) { - HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getRequestHttpClient(); - ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getRequestHttpProxy(); - return executeJodd(provider, proxyInfo, uri, ticket); - } else { - //这里需要抛出异常,需要优化 - return null; - } - } +public class QrCodeRequestExecutor extends AbstractRequestExecutor { - private File executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, WxMpQrCodeTicket ticket) throws WxErrorException, IOException { +@Override + public File executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, WxMpQrCodeTicket ticket) throws WxErrorException, IOException { if (ticket != null) { if (uri.indexOf('?') == -1) { uri += '?'; @@ -80,8 +66,41 @@ public class QrCodeRequestExecutor implements RequestExecutor T executeInternal( diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/ApiTestModule.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/ApiTestModule.java index 2cfaec54..b9ce06c6 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/ApiTestModule.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/ApiTestModule.java @@ -6,7 +6,6 @@ import com.thoughtworks.xstream.XStream; import me.chanjar.weixin.common.util.xml.XStreamInitializer; import me.chanjar.weixin.mp.api.WxMpConfigStorage; import me.chanjar.weixin.mp.api.WxMpService; -import me.chanjar.weixin.mp.api.impl.apache.WxMpServiceImpl; import java.io.IOException; import java.io.InputStream; @@ -19,7 +18,7 @@ public class ApiTestModule implements Module { try (InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml")) { TestConfigStorage config = this.fromXml(TestConfigStorage.class, is1); config.setAccessTokenLock(new ReentrantLock()); - WxMpService wxService = new WxMpServiceImpl(); + WxMpService wxService = new WxMpServiceImpl0(); wxService.setWxMpConfigStorage(config); binder.bind(WxMpService.class).toInstance(wxService); diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java index e2c75f83..4d3ce9df 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java @@ -5,7 +5,7 @@ import me.chanjar.weixin.mp.api.WxMpConfigStorage; import me.chanjar.weixin.mp.api.WxMpMessageHandler; import me.chanjar.weixin.mp.api.WxMpMessageRouter; import me.chanjar.weixin.mp.api.WxMpService; -import me.chanjar.weixin.mp.api.impl.apache.WxMpServiceImpl; + import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHolder; @@ -47,7 +47,7 @@ public class WxMpDemoServer { .fromXml(is1); wxMpConfigStorage = config; - wxMpService = new WxMpServiceImpl(); + wxMpService = new WxMpServiceImpl0(); wxMpService.setWxMpConfigStorage(config); WxMpMessageHandler logHandler = new DemoLogHandler(); diff --git a/weixin-java-pay/pom.xml b/weixin-java-pay/pom.xml index d0d50455..0b2b6c0b 100644 --- a/weixin-java-pay/pom.xml +++ b/weixin-java-pay/pom.xml @@ -19,13 +19,6 @@ weixin-java-common ${project.version} - - - org.jodd - jodd-http - 3.7 - - com.github.binarywang qrcode-utils From d01d372b654ff1714c1498d117ca7277a0f1cc05 Mon Sep 17 00:00:00 2001 From: ecoolper Date: Thu, 27 Apr 2017 20:14:52 +0800 Subject: [PATCH 16/27] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E5=86=B2?= =?UTF-8?q?=E7=AA=81=E5=92=8C=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../http/MediaDownloadRequestExecutor.java | 22 +++---------------- .../cp/api/impl/apache/WxCpServiceImpl.java | 4 +--- .../cp/api/impl/jodd/WxCpServiceImpl.java | 3 --- .../mp/api/impl/apache/WxMpServiceImpl.java | 4 ---- .../weixin/mp/api/WxMpBusyRetryTest.java | 2 +- .../weixin/mp/api/test/ApiTestModule.java | 2 +- .../weixin/mp/demo/WxMpDemoServer.java | 3 +-- 7 files changed, 7 insertions(+), 33 deletions(-) diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java index 3cb1d563..e95f02de 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java @@ -10,7 +10,6 @@ import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.fs.FileUtils; import me.chanjar.weixin.common.util.http.apache.InputStreamResponseHandler; import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; - import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; import okhttp3.*; @@ -112,7 +111,7 @@ public class MediaDownloadRequestExecutor extends AbstractRequestExecutor 0) { httpProxy = new ProxyInfo(ProxyInfo.ProxyType.HTTP, configStorage.getHttpProxyHost(), configStorage.getHttpProxyPort(), configStorage.getHttpProxyUsername(), configStorage.getHttpProxyPassword()); } httpClient = JoddHttp.httpConnectionProvider; } - } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpServiceImpl.java index 37f7e5a4..8c8085da 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpServiceImpl.java @@ -1,6 +1,5 @@ package me.chanjar.weixin.mp.api.impl.apache; - import java.io.IOException; import java.util.concurrent.locks.Lock; @@ -72,13 +71,11 @@ public class WxMpServiceImpl extends AbstractWxMpService T executeInternal( diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/ApiTestModule.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/ApiTestModule.java index 696c9416..03e01444 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/ApiTestModule.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/ApiTestModule.java @@ -20,7 +20,7 @@ public class ApiTestModule implements Module { try (InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml")) { TestConfigStorage config = this.fromXml(TestConfigStorage.class, is1); config.setAccessTokenLock(new ReentrantLock()); - WxMpService wxService = new WxMpServiceImpl0(); + WxMpService wxService = new WxMpServiceImpl(); wxService.setWxMpConfigStorage(config); binder.bind(WxMpService.class).toInstance(wxService); diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java index 7e6c585a..66b90d0f 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java @@ -5,7 +5,6 @@ import me.chanjar.weixin.mp.api.WxMpConfigStorage; import me.chanjar.weixin.mp.api.WxMpMessageHandler; import me.chanjar.weixin.mp.api.WxMpMessageRouter; import me.chanjar.weixin.mp.api.WxMpService; - import me.chanjar.weixin.mp.api.impl.apache.WxMpServiceImpl; import org.eclipse.jetty.server.Server; @@ -49,7 +48,7 @@ public class WxMpDemoServer { .fromXml(is1); wxMpConfigStorage = config; - wxMpService = new WxMpServiceImpl0(); + wxMpService = new WxMpServiceImpl(); wxMpService.setWxMpConfigStorage(config); WxMpMessageHandler logHandler = new DemoLogHandler(); From f42b22f5c19fba66ffd8f726533d55758085538c Mon Sep 17 00:00:00 2001 From: ecoolper Date: Thu, 27 Apr 2017 20:24:42 +0800 Subject: [PATCH 17/27] =?UTF-8?q?WxCpService=E6=B7=BB=E5=8A=A0getWxMpConfi?= =?UTF-8?q?gStorage=E6=96=B9=E6=B3=95=EF=BC=8C=E5=90=8C=E6=97=B6=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E7=9B=B8=E5=85=B3=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/me/chanjar/weixin/cp/api/WxCpService.java | 7 +++++++ .../chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java | 6 ++++++ .../chanjar/weixin/cp/api/impl/jodd/WxCpServiceImpl.java | 6 ++++++ .../chanjar/weixin/cp/api/impl/okhttp/WxCpServiceImpl.java | 5 +++++ .../weixin/cp/api/impl/apache/WxCpMessageAPITest.java | 2 +- 5 files changed, 25 insertions(+), 1 deletion(-) diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java index 4b15fdb1..3da42ea1 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java @@ -556,4 +556,11 @@ public interface WxCpService { * 初始化http请求对象 */ void initHttp(); + + /** + * 获取WxMpConfigStorage 对象 + * + * @return WxMpConfigStorage + */ + WxCpConfigStorage getWxMpConfigStorage(); } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java index 8e4d57e3..453e33be 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java @@ -6,6 +6,7 @@ import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; +import me.chanjar.weixin.cp.api.WxCpConfigStorage; import me.chanjar.weixin.cp.api.impl.AbstractWxCpService; import org.apache.http.HttpHost; @@ -91,4 +92,9 @@ public class WxCpServiceImpl extends AbstractWxCpService { @@ -62,4 +63,9 @@ public class WxCpServiceImpl extends AbstractWxCpService Date: Thu, 27 Apr 2017 20:32:05 +0800 Subject: [PATCH 18/27] =?UTF-8?q?WxCpService=E7=9A=84getWxMpConfigStorage?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E4=BF=AE=E6=94=B9=E4=B8=BAgetWxCpConfigStora?= =?UTF-8?q?ge?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/me/chanjar/weixin/cp/api/WxCpService.java | 2 +- .../me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java | 2 +- .../me/chanjar/weixin/cp/api/impl/jodd/WxCpServiceImpl.java | 2 +- .../me/chanjar/weixin/cp/api/impl/okhttp/WxCpServiceImpl.java | 2 +- .../me/chanjar/weixin/cp/api/impl/apache/WxCpBaseAPITest.java | 2 +- .../chanjar/weixin/cp/api/impl/apache/WxCpMessageAPITest.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java index 3da42ea1..f02b7589 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java @@ -562,5 +562,5 @@ public interface WxCpService { * * @return WxMpConfigStorage */ - WxCpConfigStorage getWxMpConfigStorage(); + WxCpConfigStorage getWxCpConfigStorage(); } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java index 453e33be..cff7e13d 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java @@ -94,7 +94,7 @@ public class WxCpServiceImpl extends AbstractWxCpService Date: Sat, 29 Apr 2017 13:40:53 +0800 Subject: [PATCH 19/27] =?UTF-8?q?=E6=B7=BB=E5=8A=A0httpType=E6=9E=9A?= =?UTF-8?q?=E4=B8=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/me/chanjar/weixin/common/util/http/HttpType.java | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpType.java diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpType.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpType.java new file mode 100644 index 00000000..5e78a6f1 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpType.java @@ -0,0 +1,8 @@ +package me.chanjar.weixin.common.util.http; + +/** + * Created by ecoolper on 2017/4/28. + */ +public enum HttpType { + joddHttp, apacheHttp, okHttp; +} From 2384b4b86335d1880c296f200679b5f4eb216c9c Mon Sep 17 00:00:00 2001 From: ecoolper Date: Wed, 3 May 2017 20:55:49 +0800 Subject: [PATCH 20/27] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=9E=9A=E4=B8=BEHttpT?= =?UTF-8?q?ype?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../util/http/AbstractRequestExecutor.java | 43 ++++++++++--------- .../weixin/common/util/http/RequestHttp.java | 6 +++ 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/AbstractRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/AbstractRequestExecutor.java index 23881e66..731bec77 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/AbstractRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/AbstractRequestExecutor.java @@ -17,26 +17,29 @@ import okhttp3.ConnectionPool; public abstract class AbstractRequestExecutor implements RequestExecutor { @Override - public T execute(RequestHttp requestHttp, String uri, E data) throws WxErrorException, IOException{ - if (requestHttp.getRequestHttpClient() instanceof CloseableHttpClient) { - //apache-http请求 - CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getRequestHttpClient(); - HttpHost httpProxy = (HttpHost) requestHttp.getRequestHttpProxy(); - return executeApache(httpClient, httpProxy, uri, data); - } - if (requestHttp.getRequestHttpClient() instanceof HttpConnectionProvider) { - //jodd-http请求 - HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getRequestHttpClient(); - ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getRequestHttpProxy(); - return executeJodd(provider, proxyInfo, uri, data); - } else if (requestHttp.getRequestHttpClient() instanceof ConnectionPool) { - //okhttp请求 - ConnectionPool pool = (ConnectionPool) requestHttp.getRequestHttpClient(); - OkhttpProxyInfo proxyInfo = (OkhttpProxyInfo) requestHttp.getRequestHttpProxy(); - return executeOkhttp(pool, proxyInfo, uri, data); - } else { - //TODO 这里需要抛出异常,需要优化 - return null; + public T execute(RequestHttp requestHttp, String uri, E data) throws WxErrorException, IOException { + switch (requestHttp.getRequestType()) { + case apacheHttp: { + //apache-http请求 + CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getRequestHttpClient(); + HttpHost httpProxy = (HttpHost) requestHttp.getRequestHttpProxy(); + return executeApache(httpClient, httpProxy, uri, data); + } + case joddHttp: { + //jodd-http请求 + HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getRequestHttpClient(); + ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getRequestHttpProxy(); + return executeJodd(provider, proxyInfo, uri, data); + } + case okHttp: { + //okhttp请求 + ConnectionPool pool = (ConnectionPool) requestHttp.getRequestHttpClient(); + OkhttpProxyInfo proxyInfo = (OkhttpProxyInfo) requestHttp.getRequestHttpProxy(); + return executeOkhttp(pool, proxyInfo, uri, data); + } + default: + //TODO 这里需要抛出异常,需要优化 + return null; } } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestHttp.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestHttp.java index 5af68e07..13eaf939 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestHttp.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestHttp.java @@ -17,4 +17,10 @@ public interface RequestHttp { */ P getRequestHttpProxy(); + /** + * + * @return + */ + HttpType getRequestType(); + } From 6b7c86da956be53180cdf633e8013eb04ca20633 Mon Sep 17 00:00:00 2001 From: ecoolper Date: Wed, 3 May 2017 21:11:56 +0800 Subject: [PATCH 21/27] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=9E=9A=E4=B8=BEHttpT?= =?UTF-8?q?ype?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java | 6 ++++++ .../me/chanjar/weixin/cp/api/impl/jodd/WxCpServiceImpl.java | 6 ++++++ .../chanjar/weixin/cp/api/impl/okhttp/WxCpServiceImpl.java | 6 ++++++ .../chanjar/weixin/mp/api/impl/apache/WxMpServiceImpl.java | 5 +++++ .../me/chanjar/weixin/mp/api/impl/jodd/WxMpServiceImpl.java | 6 ++++++ .../chanjar/weixin/mp/api/impl/okhttp/WxMpServiceImpl.java | 6 ++++++ 6 files changed, 35 insertions(+) diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java index cff7e13d..7c1334b4 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java @@ -4,6 +4,7 @@ package me.chanjar.weixin.cp.api.impl.apache; import me.chanjar.weixin.common.bean.WxAccessToken; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.HttpType; import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; import me.chanjar.weixin.cp.api.WxCpConfigStorage; @@ -32,6 +33,11 @@ public class WxCpServiceImpl extends AbstractWxCpService Date: Thu, 4 May 2017 11:02:24 +0800 Subject: [PATCH 22/27] =?UTF-8?q?okhttp=E4=BD=BF=E7=94=A8=E6=96=B9?= =?UTF-8?q?=E5=BC=8F=E6=9C=89=E9=94=99=E8=AF=AF=EF=BC=8Cbody().toString()?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=BAbody().string()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/util/http/MediaDownloadRequestExecutor.java | 2 +- .../common/util/http/MediaUploadRequestExecutor.java | 2 +- .../weixin/common/util/http/SimpleGetRequestExecutor.java | 2 +- .../weixin/common/util/http/SimplePostRequestExecutor.java | 2 +- .../chanjar/weixin/cp/api/impl/okhttp/WxCpServiceImpl.java | 7 ++++++- .../chanjar/weixin/mp/api/impl/okhttp/WxMpServiceImpl.java | 2 +- .../weixin/mp/util/http/MaterialDeleteRequestExecutor.java | 2 +- .../mp/util/http/MaterialNewsInfoRequestExecutor.java | 2 +- .../weixin/mp/util/http/MaterialUploadRequestExecutor.java | 2 +- .../mp/util/http/MaterialVideoInfoRequestExecutor.java | 2 +- .../weixin/mp/util/http/MediaImgUploadRequestExecutor.java | 2 +- .../chanjar/weixin/mp/util/http/QrCodeRequestExecutor.java | 2 +- 12 files changed, 17 insertions(+), 12 deletions(-) diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java index e95f02de..6da7c65c 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java @@ -213,7 +213,7 @@ public class MediaDownloadRequestExecutor extends AbstractRequestExecutor Date: Thu, 4 May 2017 13:57:48 +0800 Subject: [PATCH 23/27] =?UTF-8?q?1=E3=80=81=E5=88=A0=E9=99=A4AbstractWxMpS?= =?UTF-8?q?ervice=E3=80=81AbstractWxCPService=E7=B1=BB=202=E3=80=81?= =?UTF-8?q?=E4=BF=AE=E6=94=B9apache.WxCpServiceImpl=E7=B1=BB=E7=9A=84?= =?UTF-8?q?=E7=88=B6=E7=B1=BB=E4=B8=BAAbstractWxCpServiceImpl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cp/api/impl/AbstractWxCpService.java | 632 ------------------ .../cp/api/impl/apache/WxCpServiceImpl.java | 4 +- .../mp/api/impl/AbstractWxMpService.java | 445 ------------ 3 files changed, 2 insertions(+), 1079 deletions(-) delete mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/AbstractWxCpService.java delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/AbstractWxMpService.java diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/AbstractWxCpService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/AbstractWxCpService.java deleted file mode 100644 index 82fcdef9..00000000 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/AbstractWxCpService.java +++ /dev/null @@ -1,632 +0,0 @@ -package me.chanjar.weixin.cp.api.impl; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.List; -import java.util.UUID; - -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.gson.*; -import com.google.gson.reflect.TypeToken; - -import me.chanjar.weixin.common.bean.WxJsapiSignature; -import me.chanjar.weixin.common.bean.menu.WxMenu; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.session.StandardSessionManager; -import me.chanjar.weixin.common.session.WxSession; -import me.chanjar.weixin.common.session.WxSessionManager; -import me.chanjar.weixin.common.util.RandomUtils; -import me.chanjar.weixin.common.util.crypto.SHA1; -import me.chanjar.weixin.common.util.fs.FileUtils; -import me.chanjar.weixin.common.util.http.*; -import me.chanjar.weixin.common.util.json.GsonHelper; -import me.chanjar.weixin.cp.api.WxCpConfigStorage; -import me.chanjar.weixin.cp.api.WxCpService; -import me.chanjar.weixin.cp.bean.WxCpDepart; -import me.chanjar.weixin.cp.bean.WxCpMessage; -import me.chanjar.weixin.cp.bean.WxCpTag; -import me.chanjar.weixin.cp.bean.WxCpUser; -import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; - -public abstract class AbstractWxCpService implements WxCpService, RequestHttp { - - protected final Logger log = LoggerFactory.getLogger(AbstractWxCpService.class); - - /** - * 全局的是否正在刷新access token的锁 - */ - protected final Object globalAccessTokenRefreshLock = new Object(); - - /** - * 全局的是否正在刷新jsapi_ticket的锁 - */ - protected final Object globalJsapiTicketRefreshLock = new Object(); - - protected WxCpConfigStorage configStorage; - - - protected WxSessionManager sessionManager = new StandardSessionManager(); - /** - * 临时文件目录 - */ - protected File tmpDirFile; - private int retrySleepMillis = 1000; - private int maxRetryTimes = 5; - - @Override - public boolean checkSignature(String msgSignature, String timestamp, String nonce, String data) { - try { - return SHA1.gen(this.configStorage.getToken(), timestamp, nonce, data) - .equals(msgSignature); - } catch (Exception e) { - return false; - } - } - - @Override - public void userAuthenticated(String userId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/authsucc?userid=" + userId; - get(url, null); - } - - @Override - public String getAccessToken() throws WxErrorException { - return getAccessToken(false); - } - - - @Override - public String getJsapiTicket() throws WxErrorException { - return getJsapiTicket(false); - } - - @Override - public String getJsapiTicket(boolean forceRefresh) throws WxErrorException { - if (forceRefresh) { - this.configStorage.expireJsapiTicket(); - } - if (this.configStorage.isJsapiTicketExpired()) { - synchronized (this.globalJsapiTicketRefreshLock) { - if (this.configStorage.isJsapiTicketExpired()) { - String url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket"; - String responseContent = execute(new SimpleGetRequestExecutor(), url, null); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); - String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); - int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); - this.configStorage.updateJsapiTicket(jsapiTicket, - expiresInSeconds); - } - } - } - return this.configStorage.getJsapiTicket(); - } - - @Override - public WxJsapiSignature createJsapiSignature(String url) throws WxErrorException { - long timestamp = System.currentTimeMillis() / 1000; - String noncestr = RandomUtils.getRandomStr(); - String jsapiTicket = getJsapiTicket(false); - String signature = SHA1.genWithAmple( - "jsapi_ticket=" + jsapiTicket, - "noncestr=" + noncestr, - "timestamp=" + timestamp, - "url=" + url - ); - WxJsapiSignature jsapiSignature = new WxJsapiSignature(); - jsapiSignature.setTimestamp(timestamp); - jsapiSignature.setNonceStr(noncestr); - jsapiSignature.setUrl(url); - jsapiSignature.setSignature(signature); - - // Fixed bug - jsapiSignature.setAppId(this.configStorage.getCorpId()); - - return jsapiSignature; - } - - @Override - public void messageSend(WxCpMessage message) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/message/send"; - post(url, message.toJson()); - } - - @Override - public void menuCreate(WxMenu menu) throws WxErrorException { - menuCreate(this.configStorage.getAgentId(), menu); - } - - @Override - public void menuCreate(Integer agentId, WxMenu menu) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/create?agentid=" - + this.configStorage.getAgentId(); - post(url, menu.toJson()); - } - - @Override - public void menuDelete() throws WxErrorException { - menuDelete(this.configStorage.getAgentId()); - } - - @Override - public void menuDelete(Integer agentId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/delete?agentid=" + agentId; - get(url, null); - } - - @Override - public WxMenu menuGet() throws WxErrorException { - return menuGet(this.configStorage.getAgentId()); - } - - @Override - public WxMenu menuGet(Integer agentId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/get?agentid=" + agentId; - try { - String resultContent = get(url, null); - return WxMenu.fromJson(resultContent); - } catch (WxErrorException e) { - // 46003 不存在的菜单数据 - if (e.getError().getErrorCode() == 46003) { - return null; - } - throw e; - } - } - - @Override - public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) - throws WxErrorException, IOException { - return mediaUpload(mediaType, FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType)); - } - - @Override - public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?type=" + mediaType; - return execute(new MediaUploadRequestExecutor(), url, file); - } - - @Override - public File mediaDownload(String mediaId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/media/get"; - return execute( - new MediaDownloadRequestExecutor( - this.configStorage.getTmpDirFile()), - url, "media_id=" + mediaId); - } - - - @Override - public Integer departCreate(WxCpDepart depart) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/department/create"; - String responseContent = execute( - new SimplePostRequestExecutor(), - url, - depart.toJson()); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return GsonHelper.getAsInteger(tmpJsonElement.getAsJsonObject().get("id")); - } - - @Override - public void departUpdate(WxCpDepart group) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/department/update"; - post(url, group.toJson()); - } - - @Override - public void departDelete(Integer departId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/department/delete?id=" + departId; - get(url, null); - } - - @Override - public List departGet() throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/department/list"; - String responseContent = get(url, null); - /* - * 操蛋的微信API,创建时返回的是 { group : { id : ..., name : ...} } - * 查询时返回的是 { groups : [ { id : ..., name : ..., count : ... }, ... ] } - */ - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return WxCpGsonBuilder.INSTANCE.create() - .fromJson( - tmpJsonElement.getAsJsonObject().get("department"), - new TypeToken>() { - }.getType() - ); - } - - @Override - public void userCreate(WxCpUser user) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/create"; - post(url, user.toJson()); - } - - @Override - public void userUpdate(WxCpUser user) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/update"; - post(url, user.toJson()); - } - - @Override - public void userDelete(String userid) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/delete?userid=" + userid; - get(url, null); - } - - @Override - public void userDelete(String[] userids) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/batchdelete"; - JsonObject jsonObject = new JsonObject(); - JsonArray jsonArray = new JsonArray(); - for (String userid : userids) { - jsonArray.add(new JsonPrimitive(userid)); - } - jsonObject.add("useridlist", jsonArray); - post(url, jsonObject.toString()); - } - - @Override - public WxCpUser userGet(String userid) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/get?userid=" + userid; - String responseContent = get(url, null); - return WxCpUser.fromJson(responseContent); - } - - @Override - public List userList(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/list?department_id=" + departId; - String params = ""; - if (fetchChild != null) { - params += "&fetch_child=" + (fetchChild ? "1" : "0"); - } - if (status != null) { - params += "&status=" + status; - } else { - params += "&status=0"; - } - - String responseContent = get(url, params); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return WxCpGsonBuilder.INSTANCE.create() - .fromJson( - tmpJsonElement.getAsJsonObject().get("userlist"), - new TypeToken>() { - }.getType() - ); - } - - @Override - public List departGetUsers(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?department_id=" + departId; - String params = ""; - if (fetchChild != null) { - params += "&fetch_child=" + (fetchChild ? "1" : "0"); - } - if (status != null) { - params += "&status=" + status; - } else { - params += "&status=0"; - } - - String responseContent = get(url, params); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return WxCpGsonBuilder.INSTANCE.create() - .fromJson( - tmpJsonElement.getAsJsonObject().get("userlist"), - new TypeToken>() { - }.getType() - ); - } - - @Override - public String tagCreate(String tagName) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/create"; - JsonObject o = new JsonObject(); - o.addProperty("tagname", tagName); - String responseContent = post(url, o.toString()); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return tmpJsonElement.getAsJsonObject().get("tagid").getAsString(); - } - - @Override - public void tagUpdate(String tagId, String tagName) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/update"; - JsonObject o = new JsonObject(); - o.addProperty("tagid", tagId); - o.addProperty("tagname", tagName); - post(url, o.toString()); - } - - @Override - public void tagDelete(String tagId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/delete?tagid=" + tagId; - get(url, null); - } - - @Override - public List tagGet() throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/list"; - String responseContent = get(url, null); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return WxCpGsonBuilder.INSTANCE.create() - .fromJson( - tmpJsonElement.getAsJsonObject().get("taglist"), - new TypeToken>() { - }.getType() - ); - } - - @Override - public List tagGetUsers(String tagId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/get?tagid=" + tagId; - String responseContent = get(url, null); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return WxCpGsonBuilder.INSTANCE.create() - .fromJson( - tmpJsonElement.getAsJsonObject().get("userlist"), - new TypeToken>() { - }.getType() - ); - } - - @Override - public void tagAddUsers(String tagId, List userIds, List partyIds) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/addtagusers"; - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("tagid", tagId); - if (userIds != null) { - JsonArray jsonArray = new JsonArray(); - for (String userId : userIds) { - jsonArray.add(new JsonPrimitive(userId)); - } - jsonObject.add("userlist", jsonArray); - } - if (partyIds != null) { - JsonArray jsonArray = new JsonArray(); - for (String userId : partyIds) { - jsonArray.add(new JsonPrimitive(userId)); - } - jsonObject.add("partylist", jsonArray); - } - post(url, jsonObject.toString()); - } - - @Override - public void tagRemoveUsers(String tagId, List userIds) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/deltagusers"; - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("tagid", tagId); - JsonArray jsonArray = new JsonArray(); - for (String userId : userIds) { - jsonArray.add(new JsonPrimitive(userId)); - } - jsonObject.add("userlist", jsonArray); - post(url, jsonObject.toString()); - } - - @Override - public String oauth2buildAuthorizationUrl(String state) { - return this.oauth2buildAuthorizationUrl( - this.configStorage.getOauth2redirectUri(), - state - ); - } - - @Override - public String oauth2buildAuthorizationUrl(String redirectUri, String state) { - String url = "https://open.weixin.qq.com/connect/oauth2/authorize?"; - url += "appid=" + this.configStorage.getCorpId(); - url += "&redirect_uri=" + URIUtil.encodeURIComponent(redirectUri); - url += "&response_type=code"; - url += "&scope=snsapi_base"; - if (state != null) { - url += "&state=" + state; - } - url += "#wechat_redirect"; - return url; - } - - @Override - public String[] oauth2getUserInfo(String code) throws WxErrorException { - return oauth2getUserInfo(this.configStorage.getAgentId(), code); - } - - @Override - public String[] oauth2getUserInfo(Integer agentId, String code) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?" - + "code=" + code - + "&agentid=" + agentId; - String responseText = get(url, null); - JsonElement je = new JsonParser().parse(responseText); - JsonObject jo = je.getAsJsonObject(); - return new String[]{GsonHelper.getString(jo, "UserId"), GsonHelper.getString(jo, "DeviceId"), GsonHelper.getString(jo, "OpenId")}; - } - - @Override - public int invite(String userId, String inviteTips) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/invite/send"; - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("userid", userId); - if (StringUtils.isNotEmpty(inviteTips)) { - jsonObject.addProperty("invite_tips", inviteTips); - } - String responseContent = post(url, jsonObject.toString()); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return tmpJsonElement.getAsJsonObject().get("type").getAsInt(); - } - - @Override - public String[] getCallbackIp() throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/getcallbackip"; - String responseContent = get(url, null); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - JsonArray jsonArray = tmpJsonElement.getAsJsonObject().get("ip_list").getAsJsonArray(); - String[] ips = new String[jsonArray.size()]; - for (int i = 0; i < jsonArray.size(); i++) { - ips[i] = jsonArray.get(i).getAsString(); - } - return ips; - } - - @Override - public String get(String url, String queryParam) throws WxErrorException { - return execute(new SimpleGetRequestExecutor(), url, queryParam); - } - - @Override - public String post(String url, String postData) throws WxErrorException { - return execute(new SimplePostRequestExecutor(), url, postData); - } - - /** - * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 - */ - @Override - public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { - int retryTimes = 0; - do { - try { - T result = this.executeInternal(executor, uri, data); - this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}",uri, data, result); - return result; - } catch (WxErrorException e) { - if (retryTimes + 1 > this.maxRetryTimes) { - this.log.warn("重试达到最大次数【{}】", this.maxRetryTimes); - //最后一次重试失败后,直接抛出异常,不再等待 - throw new RuntimeException("微信服务端异常,超出重试次数"); - } - - WxError error = e.getError(); - /* - * -1 系统繁忙, 1000ms后重试 - */ - if (error.getErrorCode() == -1) { - int sleepMillis = this.retrySleepMillis * (1 << retryTimes); - try { - this.log.debug("微信系统繁忙,{} ms 后重试(第{}次)", sleepMillis, retryTimes + 1); - Thread.sleep(sleepMillis); - } catch (InterruptedException e1) { - throw new RuntimeException(e1); - } - } else { - throw e; - } - } - } while (retryTimes++ < this.maxRetryTimes); - - this.log.warn("重试达到最大次数【{}】", this.maxRetryTimes); - throw new RuntimeException("微信服务端异常,超出重试次数"); - } - - public synchronized T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { - if (uri.contains("access_token=")) { - throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); - } - String accessToken = getAccessToken(false); - - String uriWithAccessToken = uri; - uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken; - - try { - return executor.execute(this, uriWithAccessToken, data); - } catch (WxErrorException e) { - WxError error = e.getError(); - /* - * 发生以下情况时尝试刷新access_token - * 40001 获取access_token时AppSecret错误,或者access_token无效 - * 42001 access_token超时 - */ - if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) { - // 强制设置wxCpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token - this.configStorage.expireAccessToken(); - return execute(executor, uri, data); - } - - if (error.getErrorCode() != 0) { - this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", uri, data, error); - throw new WxErrorException(error); - } - return null; - } catch (IOException e) { - this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[EXCEPTION]: {}", uri, data, e.getMessage()); - throw new RuntimeException(e); - } - } - - @Override - public void setWxCpConfigStorage(WxCpConfigStorage wxConfigProvider) { - this.configStorage = wxConfigProvider; - this.initHttp(); - } - - @Override - public void setRetrySleepMillis(int retrySleepMillis) { - this.retrySleepMillis = retrySleepMillis; - } - - - @Override - public void setMaxRetryTimes(int maxRetryTimes) { - this.maxRetryTimes = maxRetryTimes; - } - - @Override - public WxSession getSession(String id) { - if (this.sessionManager == null) { - return null; - } - return this.sessionManager.getSession(id); - } - - @Override - public WxSession getSession(String id, boolean create) { - if (this.sessionManager == null) { - return null; - } - return this.sessionManager.getSession(id, create); - } - - - @Override - public void setSessionManager(WxSessionManager sessionManager) { - this.sessionManager = sessionManager; - } - - @Override - public String replaceParty(String mediaId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/replaceparty"; - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("media_id", mediaId); - return post(url, jsonObject.toString()); - } - - @Override - public String replaceUser(String mediaId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/replaceuser"; - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("media_id", mediaId); - return post(url, jsonObject.toString()); - } - - @Override - public String getTaskResult(String joinId) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/getresult?jobid=" + joinId; - return get(url, null); - } - - public File getTmpDirFile() { - return this.tmpDirFile; - } - - public void setTmpDirFile(File tmpDirFile) { - this.tmpDirFile = tmpDirFile; - } - -} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java index 7c1334b4..61b75cb5 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/apache/WxCpServiceImpl.java @@ -8,7 +8,7 @@ import me.chanjar.weixin.common.util.http.HttpType; import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; import me.chanjar.weixin.cp.api.WxCpConfigStorage; -import me.chanjar.weixin.cp.api.impl.AbstractWxCpService; +import me.chanjar.weixin.cp.api.impl.AbstractWxCpServiceImpl; import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; @@ -19,7 +19,7 @@ import org.apache.http.impl.client.CloseableHttpClient; import java.io.IOException; -public class WxCpServiceImpl extends AbstractWxCpService { +public class WxCpServiceImpl extends AbstractWxCpServiceImpl { protected CloseableHttpClient httpClient; protected HttpHost httpProxy; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/AbstractWxMpService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/AbstractWxMpService.java deleted file mode 100644 index 5c6b58eb..00000000 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/AbstractWxMpService.java +++ /dev/null @@ -1,445 +0,0 @@ -package me.chanjar.weixin.mp.api.impl; - -import java.io.IOException; -import java.util.concurrent.locks.Lock; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; - -import me.chanjar.weixin.common.bean.WxJsapiSignature; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.session.StandardSessionManager; -import me.chanjar.weixin.common.session.WxSessionManager; -import me.chanjar.weixin.common.util.RandomUtils; -import me.chanjar.weixin.common.util.crypto.SHA1; -import me.chanjar.weixin.common.util.http.*; -import me.chanjar.weixin.mp.api.*; -import me.chanjar.weixin.mp.bean.*; -import me.chanjar.weixin.mp.bean.result.*; - -public abstract class AbstractWxMpService implements WxMpService,RequestHttp { - - private static final JsonParser JSON_PARSER = new JsonParser(); - - protected final Logger log = LoggerFactory.getLogger(this.getClass()); - protected WxSessionManager sessionManager = new StandardSessionManager(); - private WxMpConfigStorage wxMpConfigStorage; - private WxMpKefuService kefuService = new WxMpKefuServiceImpl(this); - private WxMpMaterialService materialService = new WxMpMaterialServiceImpl(this); - private WxMpMenuService menuService = new WxMpMenuServiceImpl(this); - private WxMpUserService userService = new WxMpUserServiceImpl(this); - private WxMpUserTagService tagService = new WxMpUserTagServiceImpl(this); - private WxMpQrcodeService qrCodeService = new WxMpQrcodeServiceImpl(this); - private WxMpCardService cardService = new WxMpCardServiceImpl(this); - private WxMpStoreService storeService = new WxMpStoreServiceImpl(this); - private WxMpDataCubeService dataCubeService = new WxMpDataCubeServiceImpl(this); - private WxMpUserBlacklistService blackListService = new WxMpUserBlacklistServiceImpl(this); - private WxMpTemplateMsgService templateMsgService = new WxMpTemplateMsgServiceImpl(this); - private WxMpDeviceService deviceService = new WxMpDeviceServiceImpl(this); - - private int retrySleepMillis = 1000; - private int maxRetryTimes = 5; - - - @Override - public boolean checkSignature(String timestamp, String nonce, String signature) { - try { - return SHA1.gen(this.getWxMpConfigStorage().getToken(), timestamp, nonce) - .equals(signature); - } catch (Exception e) { - return false; - } - } - - @Override - public String getJsapiTicket() throws WxErrorException { - return getJsapiTicket(false); - } - - @Override - public String getJsapiTicket(boolean forceRefresh) throws WxErrorException { - Lock lock = this.getWxMpConfigStorage().getJsapiTicketLock(); - try { - lock.lock(); - - if (forceRefresh) { - this.getWxMpConfigStorage().expireJsapiTicket(); - } - - if (this.getWxMpConfigStorage().isJsapiTicketExpired()) { - String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi"; - String responseContent = execute(new SimpleGetRequestExecutor(), url, null); - JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); - JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); - String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); - int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); - this.getWxMpConfigStorage().updateJsapiTicket(jsapiTicket, expiresInSeconds); - } - } finally { - lock.unlock(); - } - return this.getWxMpConfigStorage().getJsapiTicket(); - } - - @Override - public WxJsapiSignature createJsapiSignature(String url) throws WxErrorException { - long timestamp = System.currentTimeMillis() / 1000; - String noncestr = RandomUtils.getRandomStr(); - String jsapiTicket = getJsapiTicket(false); - String signature = SHA1.genWithAmple("jsapi_ticket=" + jsapiTicket, - "noncestr=" + noncestr, "timestamp=" + timestamp, "url=" + url); - WxJsapiSignature jsapiSignature = new WxJsapiSignature(); - jsapiSignature.setAppId(this.getWxMpConfigStorage().getAppId()); - jsapiSignature.setTimestamp(timestamp); - jsapiSignature.setNonceStr(noncestr); - jsapiSignature.setUrl(url); - jsapiSignature.setSignature(signature); - return jsapiSignature; - } - - @Override - public String getAccessToken() throws WxErrorException { - return getAccessToken(false); - } - - @Override - public WxMpMassUploadResult massNewsUpload(WxMpMassNews news) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/media/uploadnews"; - String responseContent = this.post(url, news.toJson()); - return WxMpMassUploadResult.fromJson(responseContent); - } - - @Override - public WxMpMassUploadResult massVideoUpload(WxMpMassVideo video) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/media/uploadvideo"; - String responseContent = this.post(url, video.toJson()); - return WxMpMassUploadResult.fromJson(responseContent); - } - - @Override - public WxMpMassSendResult massGroupMessageSend(WxMpMassTagMessage message) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall"; - String responseContent = this.post(url, message.toJson()); - return WxMpMassSendResult.fromJson(responseContent); - } - - @Override - public WxMpMassSendResult massOpenIdsMessageSend(WxMpMassOpenIdsMessage message) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/message/mass/send"; - String responseContent = this.post(url, message.toJson()); - return WxMpMassSendResult.fromJson(responseContent); - } - - @Override - public WxMpMassSendResult massMessagePreview(WxMpMassPreviewMessage wxMpMassPreviewMessage) throws Exception { - String url = "https://api.weixin.qq.com/cgi-bin/message/mass/preview"; - String responseContent = this.post(url, wxMpMassPreviewMessage.toJson()); - return WxMpMassSendResult.fromJson(responseContent); - } - - @Override - public String shortUrl(String long_url) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/shorturl"; - JsonObject o = new JsonObject(); - o.addProperty("action", "long2short"); - o.addProperty("long_url", long_url); - String responseContent = this.post(url, o.toString()); - JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); - return tmpJsonElement.getAsJsonObject().get("short_url").getAsString(); - } - - @Override - public WxMpSemanticQueryResult semanticQuery(WxMpSemanticQuery semanticQuery) throws WxErrorException { - String url = "https://api.weixin.qq.com/semantic/semproxy/search"; - String responseContent = this.post(url, semanticQuery.toJson()); - return WxMpSemanticQueryResult.fromJson(responseContent); - } - - @Override - public String oauth2buildAuthorizationUrl(String redirectURI, String scope, String state) { - StringBuilder url = new StringBuilder(); - url.append("https://open.weixin.qq.com/connect/oauth2/authorize?"); - url.append("appid=").append(this.getWxMpConfigStorage().getAppId()); - url.append("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectURI)); - url.append("&response_type=code"); - url.append("&scope=").append(scope); - if (state != null) { - url.append("&state=").append(state); - } - url.append("#wechat_redirect"); - return url.toString(); - } - - @Override - public String buildQrConnectUrl(String redirectURI, String scope, - String state) { - StringBuilder url = new StringBuilder(); - url.append("https://open.weixin.qq.com/connect/qrconnect?"); - url.append("appid=").append(this.getWxMpConfigStorage().getAppId()); - url.append("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectURI)); - url.append("&response_type=code"); - url.append("&scope=").append(scope); - if (state != null) { - url.append("&state=").append(state); - } - - url.append("#wechat_redirect"); - return url.toString(); - } - - private WxMpOAuth2AccessToken getOAuth2AccessToken(StringBuilder url) throws WxErrorException { - try { - RequestExecutor executor = new SimpleGetRequestExecutor(); - String responseText = executor.execute(this, url.toString(), null); - return WxMpOAuth2AccessToken.fromJson(responseText); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public WxMpOAuth2AccessToken oauth2getAccessToken(String code) throws WxErrorException { - StringBuilder url = new StringBuilder(); - url.append("https://api.weixin.qq.com/sns/oauth2/access_token?"); - url.append("appid=").append(this.getWxMpConfigStorage().getAppId()); - url.append("&secret=").append(this.getWxMpConfigStorage().getSecret()); - url.append("&code=").append(code); - url.append("&grant_type=authorization_code"); - - return this.getOAuth2AccessToken(url); - } - - @Override - public WxMpOAuth2AccessToken oauth2refreshAccessToken(String refreshToken) throws WxErrorException { - StringBuilder url = new StringBuilder(); - url.append("https://api.weixin.qq.com/sns/oauth2/refresh_token?"); - url.append("appid=").append(this.getWxMpConfigStorage().getAppId()); - url.append("&grant_type=refresh_token"); - url.append("&refresh_token=").append(refreshToken); - - return this.getOAuth2AccessToken(url); - } - - @Override - public WxMpUser oauth2getUserInfo(WxMpOAuth2AccessToken oAuth2AccessToken, String lang) throws WxErrorException { - StringBuilder url = new StringBuilder(); - url.append("https://api.weixin.qq.com/sns/userinfo?"); - url.append("access_token=").append(oAuth2AccessToken.getAccessToken()); - url.append("&openid=").append(oAuth2AccessToken.getOpenId()); - if (lang == null) { - url.append("&lang=zh_CN"); - } else { - url.append("&lang=").append(lang); - } - - try { - RequestExecutor executor = new SimpleGetRequestExecutor(); - String responseText = executor.execute(this, url.toString(), null); - return WxMpUser.fromJson(responseText); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public boolean oauth2validateAccessToken(WxMpOAuth2AccessToken oAuth2AccessToken) { - StringBuilder url = new StringBuilder(); - url.append("https://api.weixin.qq.com/sns/auth?"); - url.append("access_token=").append(oAuth2AccessToken.getAccessToken()); - url.append("&openid=").append(oAuth2AccessToken.getOpenId()); - - try { - RequestExecutor executor = new SimpleGetRequestExecutor(); - executor.execute(this, url.toString(), null); - } catch (IOException e) { - throw new RuntimeException(e); - } catch (WxErrorException e) { - return false; - } - return true; - } - - @Override - public String[] getCallbackIP() throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/getcallbackip"; - String responseContent = get(url, null); - JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); - JsonArray ipList = tmpJsonElement.getAsJsonObject().get("ip_list").getAsJsonArray(); - String[] ipArray = new String[ipList.size()]; - for (int i = 0; i < ipList.size(); i++) { - ipArray[i] = ipList.get(i).getAsString(); - } - return ipArray; - } - - @Override - public String get(String url, String queryParam) throws WxErrorException { - return execute(new SimpleGetRequestExecutor(), url, queryParam); - } - - @Override - public String post(String url, String postData) throws WxErrorException { - return execute(new SimplePostRequestExecutor(), url, postData); - } - - /** - * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 - */ - public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { - int retryTimes = 0; - do { - try { - T result = executeInternal(executor, uri, data); - this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", uri, data, result); - return result; - } catch (WxErrorException e) { - if (retryTimes + 1 > this.maxRetryTimes) { - this.log.warn("重试达到最大次数【{}】", maxRetryTimes); - //最后一次重试失败后,直接抛出异常,不再等待 - throw new RuntimeException("微信服务端异常,超出重试次数"); - } - - WxError error = e.getError(); - // -1 系统繁忙, 1000ms后重试 - if (error.getErrorCode() == -1) { - int sleepMillis = this.retrySleepMillis * (1 << retryTimes); - try { - this.log.warn("微信系统繁忙,{} ms 后重试(第{}次)", sleepMillis, retryTimes + 1); - Thread.sleep(sleepMillis); - } catch (InterruptedException e1) { - throw new RuntimeException(e1); - } - } else { - throw e; - } - } - } while (retryTimes++ < this.maxRetryTimes); - - this.log.warn("重试达到最大次数【{}】", this.maxRetryTimes); - throw new RuntimeException("微信服务端异常,超出重试次数"); - } - - public synchronized T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException { - if (uri.indexOf("access_token=") != -1) { - throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); - } - String accessToken = getAccessToken(false); - - String uriWithAccessToken = uri; - uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken; - - try { - return executor.execute(this, uriWithAccessToken, data); - } catch (WxErrorException e) { - WxError error = e.getError(); - /* - * 发生以下情况时尝试刷新access_token - * 40001 获取access_token时AppSecret错误,或者access_token无效 - * 42001 access_token超时 - */ - if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) { - // 强制设置wxMpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token - this.getWxMpConfigStorage().expireAccessToken(); - if (this.getWxMpConfigStorage().autoRefreshToken()) { - return this.execute(executor, uri, data); - } - } - - if (error.getErrorCode() != 0) { - this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", uri, data, error); - throw new WxErrorException(error); - } - return null; - } catch (IOException e) { - this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[EXCEPTION]: {}", uri, data, e.getMessage()); - throw new RuntimeException(e); - } - } - - @Override - public WxMpConfigStorage getWxMpConfigStorage() { - return this.wxMpConfigStorage; - } - - @Override - public void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider) { - this.wxMpConfigStorage = wxConfigProvider; - this.initHttp(); - } - - @Override - public void setRetrySleepMillis(int retrySleepMillis) { - this.retrySleepMillis = retrySleepMillis; - } - - @Override - public void setMaxRetryTimes(int maxRetryTimes) { - this.maxRetryTimes = maxRetryTimes; - } - - @Override - public WxMpKefuService getKefuService() { - return this.kefuService; - } - - @Override - public WxMpMaterialService getMaterialService() { - return this.materialService; - } - - @Override - public WxMpMenuService getMenuService() { - return this.menuService; - } - - @Override - public WxMpUserService getUserService() { - return this.userService; - } - - @Override - public WxMpUserTagService getUserTagService() { - return this.tagService; - } - - @Override - public WxMpQrcodeService getQrcodeService() { - return this.qrCodeService; - } - - @Override - public WxMpCardService getCardService() { - return this.cardService; - } - - @Override - public WxMpDataCubeService getDataCubeService() { - return this.dataCubeService; - } - - @Override - public WxMpUserBlacklistService getBlackListService() { - return this.blackListService; - } - - @Override - public WxMpStoreService getStoreService() { - return this.storeService; - } - - @Override - public WxMpTemplateMsgService getTemplateMsgService() { - return this.templateMsgService; - } - - @Override - public WxMpDeviceService getDeviceService() { - return this.deviceService; - } -} From 26d68cd3e8262994856a60d1f2d9da1b61e32ae3 Mon Sep 17 00:00:00 2001 From: ecoolper Date: Sat, 6 May 2017 19:05:01 +0800 Subject: [PATCH 24/27] =?UTF-8?q?RequestExecutor=E5=AE=9E=E4=BE=8B?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=BA=E9=80=9A=E8=BF=87create=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E6=9E=84=E5=BB=BA=EF=BC=8C=E8=A7=A3=E5=86=B3=E4=BA=86?= =?UTF-8?q?=E5=BF=85=E9=A1=BB=E5=90=8C=E6=97=B6=E5=BC=95=E5=85=A5apache-ht?= =?UTF-8?q?tp=E3=80=81jodd-http=E3=80=81okhttp=20jar=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../util/http/AbstractRequestExecutor.java | 46 ---- .../http/MediaDownloadRequestExecutor.java | 214 ++---------------- .../util/http/MediaUploadRequestExecutor.java | 124 ++-------- .../common/util/http/RequestExecutor.java | 14 +- .../util/http/SimpleGetRequestExecutor.java | 132 ++--------- .../util/http/SimplePostRequestExecutor.java | 150 ++---------- .../ApacheMediaDownloadRequestExecutor.java | 90 ++++++++ .../ApacheMediaUploadRequestExecutor.java | 58 +++++ .../ApacheSimpleGetRequestExecutor.java | 52 +++++ .../ApacheSimplePostRequestExecutor.java | 63 ++++++ .../JoddMediaDownloadRequestExecutor.java | 79 +++++++ .../jodd/JoddMediaUploadRequestExecutor.java | 41 ++++ .../jodd/JoddSimpleGetRequestExecutor.java | 54 +++++ .../jodd/JoddSimplePostRequestExecutor.java | 58 +++++ .../OkMediaDownloadRequestExecutor.java | 92 ++++++++ .../okhttp/OkMediaUploadRequestExecutor.java | 56 +++++ .../okhttp/OkSimpleGetRequestExecutor.java | 63 ++++++ .../okhttp/OkSimplePostRequestExecutor.java | 59 +++++ .../cp/api/impl/AbstractWxCpServiceImpl.java | 14 +- .../weixin/mp/api/WxMpCardService.java | 2 +- .../me/chanjar/weixin/mp/api/WxMpService.java | 7 + .../mp/api/impl/AbstractWxMpServiceImpl.java | 21 +- .../mp/api/impl/WxMpCardServiceImpl.java | 6 +- .../mp/api/impl/WxMpKefuServiceImpl.java | 2 +- .../mp/api/impl/WxMpMaterialServiceImpl.java | 16 +- .../mp/api/impl/WxMpQrcodeServiceImpl.java | 2 +- .../impl/WxMpUserBlacklistServiceImpl.java | 6 +- .../mp/api/impl/apache/WxMpServiceImpl.java | 5 + .../mp/api/impl/jodd/WxMpServiceImpl.java | 6 + .../mp/api/impl/okhttp/WxMpServiceImpl.java | 6 + .../http/MaterialDeleteRequestExecutor.java | 96 ++------ .../http/MaterialNewsInfoRequestExecutor.java | 98 ++------ .../http/MaterialUploadRequestExecutor.java | 137 ++--------- .../MaterialVideoInfoRequestExecutor.java | 97 ++------ ...lVoiceAndImageDownloadRequestExecutor.java | 129 ++--------- .../http/MediaImgUploadRequestExecutor.java | 112 ++------- .../mp/util/http/QrCodeRequestExecutor.java | 112 ++------- .../ApacheMaterialDeleteRequestExecutor.java | 52 +++++ ...ApacheMaterialNewsInfoRequestExecutor.java | 54 +++++ .../ApacheMaterialUploadRequestExecutor.java | 75 ++++++ ...pacheMaterialVideoInfoRequestExecutor.java | 53 +++++ ...lVoiceAndImageDownloadRequestExecutor.java | 64 ++++++ .../ApacheMediaImgUploadRequestExecutor.java | 61 +++++ .../apache/ApacheQrCodeRequestExecutor.java | 66 ++++++ .../JoddMaterialDeleteRequestExecutor.java | 40 ++++ .../JoddMaterialNewsInfoRequestExecutor.java | 43 ++++ .../JoddMaterialUploadRequestExecutor.java | 59 +++++ .../JoddMaterialVideoInfoRequestExecutor.java | 41 ++++ ...lVoiceAndImageDownloadRequestExecutor.java | 56 +++++ .../JoddMediaImgUploadRequestExecutor.java | 46 ++++ .../http/jodd/JoddQrCodeRequestExecutor.java | 57 +++++ .../OkhttpMaterialDeleteRequestExecutor.java | 54 +++++ ...OkhttpMaterialNewsInfoRequestExecutor.java | 55 +++++ .../OkhttpMaterialUploadRequestExecutor.java | 80 +++++++ ...khttpMaterialVideoInfoRequestExecutor.java | 52 +++++ ...lVoiceAndImageDownloadRequestExecutor.java | 68 ++++++ .../OkhttpMediaImgUploadRequestExecutor.java | 56 +++++ .../okhttp/OkhttpQrCodeRequestExecutor.java | 58 +++++ 58 files changed, 2214 insertions(+), 1295 deletions(-) delete mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/AbstractRequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheMediaDownloadRequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheMediaUploadRequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheSimpleGetRequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheSimplePostRequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddMediaDownloadRequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddMediaUploadRequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddSimpleGetRequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddSimplePostRequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkMediaDownloadRequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkMediaUploadRequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkSimpleGetRequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkSimplePostRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialDeleteRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialNewsInfoRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialUploadRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialVideoInfoRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialVoiceAndImageDownloadRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMediaImgUploadRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheQrCodeRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddMaterialDeleteRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddMaterialNewsInfoRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddMaterialUploadRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddMaterialVideoInfoRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddMaterialVoiceAndImageDownloadRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddMediaImgUploadRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddQrCodeRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpMaterialDeleteRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpMaterialNewsInfoRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpMaterialUploadRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpMaterialVideoInfoRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpMaterialVoiceAndImageDownloadRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpMediaImgUploadRequestExecutor.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpQrCodeRequestExecutor.java diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/AbstractRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/AbstractRequestExecutor.java deleted file mode 100644 index 731bec77..00000000 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/AbstractRequestExecutor.java +++ /dev/null @@ -1,46 +0,0 @@ -package me.chanjar.weixin.common.util.http; - -import java.io.IOException; - -import org.apache.http.HttpHost; -import org.apache.http.impl.client.CloseableHttpClient; - -import jodd.http.HttpConnectionProvider; -import jodd.http.ProxyInfo; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; -import okhttp3.ConnectionPool; - -/** - * Created by ecoolper on 2017/4/27. - */ -public abstract class AbstractRequestExecutor implements RequestExecutor { - - @Override - public T execute(RequestHttp requestHttp, String uri, E data) throws WxErrorException, IOException { - switch (requestHttp.getRequestType()) { - case apacheHttp: { - //apache-http请求 - CloseableHttpClient httpClient = (CloseableHttpClient) requestHttp.getRequestHttpClient(); - HttpHost httpProxy = (HttpHost) requestHttp.getRequestHttpProxy(); - return executeApache(httpClient, httpProxy, uri, data); - } - case joddHttp: { - //jodd-http请求 - HttpConnectionProvider provider = (HttpConnectionProvider) requestHttp.getRequestHttpClient(); - ProxyInfo proxyInfo = (ProxyInfo) requestHttp.getRequestHttpProxy(); - return executeJodd(provider, proxyInfo, uri, data); - } - case okHttp: { - //okhttp请求 - ConnectionPool pool = (ConnectionPool) requestHttp.getRequestHttpClient(); - OkhttpProxyInfo proxyInfo = (OkhttpProxyInfo) requestHttp.getRequestHttpProxy(); - return executeOkhttp(pool, proxyInfo, uri, data); - } - default: - //TODO 这里需要抛出异常,需要优化 - return null; - } - } - -} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java index 6da7c65c..8ea7658d 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaDownloadRequestExecutor.java @@ -8,8 +8,11 @@ import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.fs.FileUtils; +import me.chanjar.weixin.common.util.http.apache.ApacheMediaDownloadRequestExecutor; import me.chanjar.weixin.common.util.http.apache.InputStreamResponseHandler; import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.http.jodd.JoddMediaDownloadRequestExecutor; +import me.chanjar.weixin.common.util.http.okhttp.OkMediaDownloadRequestExecutor; import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; import okhttp3.*; @@ -37,207 +40,26 @@ import java.util.regex.Pattern; * * @author Daniel Qian */ -public class MediaDownloadRequestExecutor extends AbstractRequestExecutor { - - private File tmpDirFile; - - public MediaDownloadRequestExecutor(File tmpDirFile) { - this.tmpDirFile = tmpDirFile; - } - - private String getFileName(HttpResponse response) throws WxErrorException { - String content = response.header("Content-disposition"); - if (content == null || content.length() == 0) { - throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); - } - - Pattern p = Pattern.compile(".*filename=\"(.*)\""); - Matcher m = p.matcher(content); - if (m.matches()) { - return m.group(1); - } - throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); - } - - private String getFileName(CloseableHttpResponse response) throws WxErrorException { - Header[] contentDispositionHeader = response.getHeaders("Content-disposition"); - if (contentDispositionHeader == null || contentDispositionHeader.length == 0) { - throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); - } - - Pattern p = Pattern.compile(".*filename=\"(.*)\""); - Matcher m = p.matcher(contentDispositionHeader[0].getValue()); - if (m.matches()) { - return m.group(1); - } - throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); - } - - - /** - * apache-http实现方式 - * - * @param httpclient - * @param httpProxy - * @param uri - * @param queryParam - * @return - * @throws WxErrorException - * @throws IOException - */ - public File executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String queryParam) throws WxErrorException, IOException { - if (queryParam != null) { - if (uri.indexOf('?') == -1) { - uri += '?'; - } - uri += uri.endsWith("?") ? queryParam : '&' + queryParam; - } - - HttpGet httpGet = new HttpGet(uri); - if (httpProxy != null) { - RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); - httpGet.setConfig(config); - } - - try (CloseableHttpResponse response = httpclient.execute(httpGet); - InputStream inputStream = InputStreamResponseHandler.INSTANCE - .handleResponse(response)) { - Header[] contentTypeHeader = response.getHeaders("Content-Type"); - if (contentTypeHeader != null && contentTypeHeader.length > 0) { - if (contentTypeHeader[0].getValue().startsWith(ContentType.APPLICATION_JSON.getMimeType())) { - // application/json; encoding=utf-8 下载媒体文件出错 - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - throw new WxErrorException(WxError.fromJson(responseContent)); - } - } - - String fileName = getFileName(response); - if (StringUtils.isBlank(fileName)) { +public abstract class MediaDownloadRequestExecutor implements RequestExecutor { + + public static RequestExecutor create(RequestHttp requestHttp, File tmpDirFile){ + switch (requestHttp.getRequestType()){ + case apacheHttp: + return new ApacheMediaDownloadRequestExecutor(requestHttp, tmpDirFile); + case joddHttp: + return new JoddMediaDownloadRequestExecutor(requestHttp, tmpDirFile); + case okHttp: + return new OkMediaDownloadRequestExecutor(requestHttp, tmpDirFile); + default: return null; - } - - String[] nameAndExt = fileName.split("\\."); - return FileUtils.createTmpFile(inputStream, nameAndExt[0], nameAndExt[1], this.tmpDirFile); - - } finally { - httpGet.releaseConnection(); } - } + protected RequestHttp requestHttp; + protected File tmpDirFile; - /** - * jodd-http实现方式 - * - * @param provider - * @param proxyInfo - * @param uri - * @param queryParam - * @return - * @throws WxErrorException - * @throws IOException - */ - public File executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, String queryParam) throws WxErrorException, IOException { - if (queryParam != null) { - if (uri.indexOf('?') == -1) { - uri += '?'; - } - uri += uri.endsWith("?") ? queryParam : '&' + queryParam; - } - - HttpRequest request = HttpRequest.get(uri); - if (proxyInfo != null) { - provider.useProxy(proxyInfo); - } - request.withConnectionProvider(provider); - - HttpResponse response = request.send(); - String contentType = response.header("Content-Type"); - if (contentType != null && contentType.startsWith("application/json")) { - // application/json; encoding=utf-8 下载媒体文件出错 - throw new WxErrorException(WxError.fromJson(response.bodyText())); - } - - String fileName = getFileName(response); - if (StringUtils.isBlank(fileName)) { - return null; - } - - InputStream inputStream = new ByteArrayInputStream(response.bodyBytes()); - String[] nameAndExt = fileName.split("\\."); - return FileUtils.createTmpFile(inputStream, nameAndExt[0], nameAndExt[1], this.tmpDirFile); - } - - - /** - * okhttp现实方式 - * - * @param pool - * @param proxyInfo - * @param uri - * @param queryParam - * @return - * @throws WxErrorException - * @throws IOException - */ - public File executeOkhttp(ConnectionPool pool, final OkhttpProxyInfo proxyInfo, String uri, String queryParam) throws WxErrorException, IOException { - if (queryParam != null) { - if (uri.indexOf('?') == -1) { - uri += '?'; - } - uri += uri.endsWith("?") ? queryParam : '&' + queryParam; - } - - OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(pool); - //设置代理 - if (proxyInfo != null) { - clientBuilder.proxy(proxyInfo.getProxy()); - } - //设置授权 - clientBuilder.authenticator(new Authenticator() { - @Override - public Request authenticate(Route route, Response response) throws IOException { - String credential = Credentials.basic(proxyInfo.getProxyUsername(), proxyInfo.getProxyPassword()); - return response.request().newBuilder() - .header("Authorization", credential) - .build(); - } - }); - //得到httpClient - OkHttpClient client = clientBuilder.build(); - - Request request = new Request.Builder().url(uri).get().build(); - - Response response = client.newCall(request).execute(); - - String contentType = response.header("Content-Type"); - if (contentType != null && contentType.startsWith("application/json")) { - // application/json; encoding=utf-8 下载媒体文件出错 - throw new WxErrorException(WxError.fromJson(response.body().string())); - } - - String fileName = getFileName(response); - if (StringUtils.isBlank(fileName)) { - return null; - } - - InputStream inputStream = new ByteArrayInputStream(response.body().bytes()); - String[] nameAndExt = fileName.split("\\."); - return FileUtils.createTmpFile(inputStream, nameAndExt[0], nameAndExt[1], this.tmpDirFile); - } - - private String getFileName(Response response) throws WxErrorException { - String content = response.header("Content-disposition"); - if (content == null || content.length() == 0) { - throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); - } - - Pattern p = Pattern.compile(".*filename=\"(.*)\""); - Matcher m = p.matcher(content); - if (m.matches()) { - return m.group(1); - } - throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); + public MediaDownloadRequestExecutor(RequestHttp requestHttp, File tmpDirFile) { + this.tmpDirFile = tmpDirFile; } } 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 a6366f54..abe3dbd6 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 @@ -7,8 +7,11 @@ import jodd.http.ProxyInfo; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.apache.ApacheMediaUploadRequestExecutor; import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.http.jodd.JoddMediaUploadRequestExecutor; +import me.chanjar.weixin.common.util.http.okhttp.OkMediaUploadRequestExecutor; import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; import okhttp3.*; @@ -32,117 +35,24 @@ import java.net.Proxy; * * @author Daniel Qian */ -public class MediaUploadRequestExecutor extends AbstractRequestExecutor { +public abstract class MediaUploadRequestExecutor implements RequestExecutor { + protected RequestHttp requestHttp; - /** - * apache-http实现方式 - * - * @param httpclient - * @param httpProxy - * @param uri - * @param file - * @return - * @throws WxErrorException - * @throws IOException - */ - public WxMediaUploadResult executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, File file) throws WxErrorException, IOException { - HttpPost httpPost = new HttpPost(uri); - if (httpProxy != null) { - RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); - httpPost.setConfig(config); - } - if (file != null) { - HttpEntity entity = MultipartEntityBuilder - .create() - .addBinaryBody("media", file) - .setMode(HttpMultipartMode.RFC6532) - .build(); - httpPost.setEntity(entity); - httpPost.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.toString()); - } - try (CloseableHttpResponse response = httpclient.execute(httpPost)) { - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } - return WxMediaUploadResult.fromJson(responseContent); - } finally { - httpPost.releaseConnection(); - } + public MediaUploadRequestExecutor(RequestHttp requestHttp){ + this.requestHttp =requestHttp; } - - /** - * jodd-http实现方式 - * - * @param provider - * @param proxyInfo - * @param uri - * @param file - * @return - * @throws WxErrorException - * @throws IOException - */ - public WxMediaUploadResult executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, File file) throws WxErrorException, IOException { - HttpRequest request = HttpRequest.post(uri); - if (proxyInfo != null) { - provider.useProxy(proxyInfo); + public static RequestExecutor create(RequestHttp requestHttp){ + switch (requestHttp.getRequestType()){ + case apacheHttp: + return new ApacheMediaUploadRequestExecutor(requestHttp); + case joddHttp: + return new JoddMediaUploadRequestExecutor(requestHttp); + case okHttp: + return new OkMediaUploadRequestExecutor(requestHttp); + default: + return null; } - request.withConnectionProvider(provider); - request.form("media", file); - HttpResponse response = request.send(); - String responseContent = response.bodyText(); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } - return WxMediaUploadResult.fromJson(responseContent); } - - /** - * okhttp现实方式 - * - * @param pool - * @param proxyInfo - * @param uri - * @param file - * @return - * @throws WxErrorException - * @throws IOException - */ - public WxMediaUploadResult executeOkhttp(ConnectionPool pool, final OkhttpProxyInfo proxyInfo, String uri, File file) throws WxErrorException, IOException { - OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(pool); - //设置代理 - if (proxyInfo != null) { - clientBuilder.proxy(proxyInfo.getProxy()); - } - //设置授权 - clientBuilder.authenticator(new Authenticator() { - @Override - public Request authenticate(Route route, Response response) throws IOException { - String credential = Credentials.basic(proxyInfo.getProxyUsername(), proxyInfo.getProxyPassword()); - return response.request().newBuilder() - .header("Authorization", credential) - .build(); - } - }); - //得到httpClient - OkHttpClient client = clientBuilder.build(); - - RequestBody fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), file); - RequestBody body = new MultipartBody.Builder().addFormDataPart("media", null, fileBody).build(); - Request request = new Request.Builder().url(uri).post(body).build(); - - Response response = client.newCall(request).execute(); - String responseContent = response.body().string(); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } - return WxMediaUploadResult.fromJson(responseContent); - } - - } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestExecutor.java index 42fa76f9..b58249e9 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestExecutor.java @@ -26,7 +26,7 @@ public interface RequestExecutor { * @throws WxErrorException * @throws IOException */ - T execute(RequestHttp requestHttp, String uri, E data) throws WxErrorException, IOException; + T execute(String uri, E data) throws WxErrorException, IOException; /** * apache-http实现方式 @@ -37,10 +37,10 @@ public interface RequestExecutor { * @return * @throws WxErrorException * @throws IOException - */ + *//* T executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, E data) throws WxErrorException, IOException; - /** + *//** * jodd-http实现方式 * @param provider * @param proxyInfo @@ -49,11 +49,11 @@ public interface RequestExecutor { * @return * @throws WxErrorException * @throws IOException - */ + *//* T executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, E data) throws WxErrorException, IOException; - /** okhttp实现方式 + *//** okhttp实现方式 * @param pool * @param proxyInfo * @param uri @@ -61,7 +61,7 @@ public interface RequestExecutor { * @return * @throws WxErrorException * @throws IOException - */ + *//* T executeOkhttp(ConnectionPool pool, final OkhttpProxyInfo proxyInfo, String uri, E data) throws WxErrorException, IOException; - +*/ } 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 f29739d6..ec7a2e57 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,8 +6,11 @@ import jodd.http.HttpResponse; import jodd.http.ProxyInfo; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.apache.ApacheSimpleGetRequestExecutor; import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.http.jodd.JoddSimpleGetRequestExecutor; +import me.chanjar.weixin.common.util.http.okhttp.OkSimpleGetRequestExecutor; import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; import okhttp3.*; @@ -27,126 +30,25 @@ import java.util.concurrent.TimeUnit; * * @author Daniel Qian */ -public class SimpleGetRequestExecutor extends AbstractRequestExecutor { +public abstract class SimpleGetRequestExecutor implements RequestExecutor { + protected RequestHttp requestHttp; - - /** - * apache-http实现方式 - * - * @param httpclient - * @param httpProxy - * @param uri - * @param queryParam - * @return - * @throws WxErrorException - * @throws IOException - */ - public String executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String queryParam) throws WxErrorException, IOException { - if (queryParam != null) { - if (uri.indexOf('?') == -1) { - uri += '?'; - } - uri += uri.endsWith("?") ? queryParam : '&' + queryParam; - } - HttpGet httpGet = new HttpGet(uri); - if (httpProxy != null) { - RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); - httpGet.setConfig(config); - } - - try (CloseableHttpResponse response = httpclient.execute(httpGet)) { - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } - return responseContent; - } finally { - httpGet.releaseConnection(); - } + public SimpleGetRequestExecutor(RequestHttp requestHttp){ + this.requestHttp =requestHttp; } - /** - * jodd-http实现方式 - * - * @param provider - * @param proxyInfo - * @param uri - * @param queryParam - * @return - * @throws WxErrorException - * @throws IOException - */ - public String executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, String queryParam) throws WxErrorException, IOException { - if (queryParam != null) { - if (uri.indexOf('?') == -1) { - uri += '?'; - } - uri += uri.endsWith("?") ? queryParam : '&' + queryParam; - } - - HttpRequest request = HttpRequest.get(uri); - if (proxyInfo != null) { - provider.useProxy(proxyInfo); - } - request.withConnectionProvider(provider); - HttpResponse response = request.send(); - String responseContent = response.bodyText(); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } - return responseContent; - } - - - /** - * okHttp实现方式 - * - * @param pool - * @param proxyInfo - * @param uri - * @param queryParam - * @return - * @throws WxErrorException - * @throws IOException - */ - public String executeOkhttp(ConnectionPool pool, final OkhttpProxyInfo proxyInfo, String uri, String queryParam) throws WxErrorException, IOException { - if (queryParam != null) { - if (uri.indexOf('?') == -1) { - uri += '?'; - } - uri += uri.endsWith("?") ? queryParam : '&' + queryParam; - } - - OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(pool); - //设置代理 - if (proxyInfo != null) { - clientBuilder.proxy(proxyInfo.getProxy()); - } - //设置授权 - clientBuilder.authenticator(new Authenticator() { - @Override - public Request authenticate(Route route, Response response) throws IOException { - String credential = Credentials.basic(proxyInfo.getProxyUsername(), proxyInfo.getProxyPassword()); - return response.request().newBuilder() - .header("Authorization", credential) - .build(); - } - }); - //得到httpClient - OkHttpClient client =clientBuilder.build(); - - Request request = new Request.Builder().url(uri).build(); - - Response response = client.newCall(request).execute(); - String responseContent = response.body().string(); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); + public static RequestExecutor create(RequestHttp requestHttp){ + switch(requestHttp.getRequestType()){ + case apacheHttp: + return new ApacheSimpleGetRequestExecutor(requestHttp); + case joddHttp: + return new JoddSimpleGetRequestExecutor(requestHttp); + case okHttp: + return new OkSimpleGetRequestExecutor(requestHttp); + default: + return null; } - return responseContent; } } 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 c89309b7..c6f4e6a7 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,8 +6,12 @@ import jodd.http.HttpResponse; import jodd.http.ProxyInfo; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.apache.ApacheSimpleGetRequestExecutor; +import me.chanjar.weixin.common.util.http.apache.ApacheSimplePostRequestExecutor; import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.http.jodd.JoddSimplePostRequestExecutor; +import me.chanjar.weixin.common.util.http.okhttp.OkSimplePostRequestExecutor; import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; import okhttp3.*; @@ -27,142 +31,24 @@ import java.io.IOException; * * @author Daniel Qian */ -public class SimplePostRequestExecutor extends AbstractRequestExecutor { +public abstract class SimplePostRequestExecutor implements RequestExecutor { + protected RequestHttp requestHttp; - /** - * apache-http实现方式 - * - * @param httpclient - * @param httpProxy - * @param uri - * @param postEntity - * @return - * @throws WxErrorException - * @throws IOException - */ - public String executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String postEntity) throws WxErrorException, IOException { - - HttpPost httpPost = new HttpPost(uri); - if (httpProxy != null) { - RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); - httpPost.setConfig(config); - } - - if (postEntity != null) { - StringEntity entity = new StringEntity(postEntity, Consts.UTF_8); - httpPost.setEntity(entity); - } - - try (CloseableHttpResponse response = httpclient.execute(httpPost)) { - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - if (responseContent.isEmpty()) { - throw new WxErrorException( - WxError.newBuilder().setErrorCode(9999).setErrorMsg("无响应内容") - .build()); - } - - if (responseContent.startsWith("")) { - //xml格式输出直接返回 - return responseContent; - } - - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } - return responseContent; - } finally { - httpPost.releaseConnection(); - } - } - - - /** - * jodd-http实现方式 - * - * @param provider - * @param proxyInfo - * @param uri - * @param postEntity - * @return - * @throws WxErrorException - * @throws IOException - */ - public String executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, String postEntity) throws WxErrorException, IOException { - HttpRequest request = HttpRequest.post(uri); - if (proxyInfo != null) { - provider.useProxy(proxyInfo); - } - request.withConnectionProvider(provider); - if (postEntity != null) { - request.bodyText(postEntity); - } - HttpResponse response = request.send(); - - String responseContent = response.bodyText(); - if (responseContent.isEmpty()) { - throw new WxErrorException( - WxError.newBuilder().setErrorCode(9999).setErrorMsg("无响应内容") - .build()); - } - - if (responseContent.startsWith("")) { - //xml格式输出直接返回 - return responseContent; - } - - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } - return responseContent; + public SimplePostRequestExecutor(RequestHttp requestHttp){ + this.requestHttp =requestHttp; } - - /** - * okHttp实现方式 - * - * @param pool - * @param proxyInfo - * @param uri - * @param postEntity - * @return - * @throws WxErrorException - * @throws IOException - */ - public String executeOkhttp(ConnectionPool pool, final OkhttpProxyInfo proxyInfo, String uri, String postEntity) throws WxErrorException, IOException { - OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(pool); - //设置代理 - if (proxyInfo != null) { - clientBuilder.proxy(proxyInfo.getProxy()); + public static RequestExecutor create(RequestHttp requestHttp){ + switch (requestHttp.getRequestType()){ + case apacheHttp: + return new ApacheSimplePostRequestExecutor(requestHttp); + case joddHttp: + return new JoddSimplePostRequestExecutor(requestHttp); + case okHttp: + return new OkSimplePostRequestExecutor(requestHttp); + default: + return null; } - //设置授权 - clientBuilder.authenticator(new Authenticator() { - @Override - public Request authenticate(Route route, Response response) throws IOException { - String credential = Credentials.basic(proxyInfo.getProxyUsername(), proxyInfo.getProxyPassword()); - return response.request().newBuilder() - .header("Authorization", credential) - .build(); - } - }); - //得到httpClient - OkHttpClient client = clientBuilder.build(); - - - MediaType mediaType = MediaType.parse("text/plain; charset=utf-8"); - RequestBody body = RequestBody.create(mediaType, postEntity); - - Request request = new Request.Builder().url(uri).post(body).build(); - - Response response = client.newCall(request).execute(); - String responseContent = response.body().string(); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } - return responseContent; } - } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheMediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheMediaDownloadRequestExecutor.java new file mode 100644 index 00000000..8546a791 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheMediaDownloadRequestExecutor.java @@ -0,0 +1,90 @@ +package me.chanjar.weixin.common.util.http.apache; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +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 me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.fs.FileUtils; +import me.chanjar.weixin.common.util.http.MediaDownloadRequestExecutor; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class ApacheMediaDownloadRequestExecutor extends MediaDownloadRequestExecutor { + + + public ApacheMediaDownloadRequestExecutor(RequestHttp requestHttp, File tmpDirFile) { + super(requestHttp, tmpDirFile); + } + + @Override + public File execute(String uri, String queryParam) throws WxErrorException, IOException { + if (queryParam != null) { + if (uri.indexOf('?') == -1) { + uri += '?'; + } + uri += uri.endsWith("?") ? queryParam : '&' + queryParam; + } + + 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 (contentTypeHeader[0].getValue().startsWith(ContentType.APPLICATION_JSON.getMimeType())) { + // application/json; encoding=utf-8 下载媒体文件出错 + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + throw new WxErrorException(WxError.fromJson(responseContent)); + } + } + + String fileName = getFileName(response); + if (StringUtils.isBlank(fileName)) { + return null; + } + + String[] nameAndExt = fileName.split("\\."); + return FileUtils.createTmpFile(inputStream, nameAndExt[0], nameAndExt[1], super.tmpDirFile); + + } finally { + httpGet.releaseConnection(); + } + } + + private String getFileName(CloseableHttpResponse response) throws WxErrorException { + Header[] contentDispositionHeader = response.getHeaders("Content-disposition"); + if (contentDispositionHeader == null || contentDispositionHeader.length == 0) { + throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); + } + + Pattern p = Pattern.compile(".*filename=\"(.*)\""); + Matcher m = p.matcher(contentDispositionHeader[0].getValue()); + if (m.matches()) { + return m.group(1); + } + throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); + } + +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheMediaUploadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheMediaUploadRequestExecutor.java new file mode 100644 index 00000000..a9c10a58 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheMediaUploadRequestExecutor.java @@ -0,0 +1,58 @@ +package me.chanjar.weixin.common.util.http.apache; + +import java.io.File; +import java.io.IOException; + +import org.apache.http.HttpEntity; +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.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.impl.client.CloseableHttpClient; + +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class ApacheMediaUploadRequestExecutor extends MediaUploadRequestExecutor { + public ApacheMediaUploadRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public WxMediaUploadResult execute(String uri, File file) 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); + httpPost.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.toString()); + } + try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpPost)) { + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return WxMediaUploadResult.fromJson(responseContent); + } finally { + httpPost.releaseConnection(); + } + } +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheSimpleGetRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheSimpleGetRequestExecutor.java new file mode 100644 index 00000000..9564fd36 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheSimpleGetRequestExecutor.java @@ -0,0 +1,52 @@ +package me.chanjar.weixin.common.util.http.apache; + +import java.io.IOException; + +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.impl.client.CloseableHttpClient; + +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; + +/** + * Created by ecoolper on 2017/5/4. + */ +public class ApacheSimpleGetRequestExecutor extends SimpleGetRequestExecutor { + + public ApacheSimpleGetRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public String execute(String uri, String queryParam) throws WxErrorException, IOException { + if (queryParam != null) { + if (uri.indexOf('?') == -1) { + uri += '?'; + } + uri += uri.endsWith("?") ? queryParam : '&' + queryParam; + } + 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)) { + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return responseContent; + } finally { + httpGet.releaseConnection(); + } + } + +} 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 new file mode 100644 index 00000000..4e092c43 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheSimplePostRequestExecutor.java @@ -0,0 +1,63 @@ +package me.chanjar.weixin.common.util.http.apache; + +import java.io.IOException; + +import org.apache.http.Consts; +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.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; + +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; + +/** + * Created by ecoolper on 2017/5/4. + */ +public class ApacheSimplePostRequestExecutor extends SimplePostRequestExecutor { + + public ApacheSimplePostRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public String execute(String uri, String postEntity) throws WxErrorException, IOException { + HttpPost httpPost = new HttpPost(uri); + if (requestHttp.getRequestHttpProxy() != null) { + RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build(); + httpPost.setConfig(config); + } + + if (postEntity != null) { + StringEntity entity = new StringEntity(postEntity, Consts.UTF_8); + httpPost.setEntity(entity); + } + + try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpPost)) { + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + if (responseContent.isEmpty()) { + throw new WxErrorException( + WxError.newBuilder().setErrorCode(9999).setErrorMsg("无响应内容") + .build()); + } + + if (responseContent.startsWith("")) { + //xml格式输出直接返回 + return responseContent; + } + + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return responseContent; + } finally { + httpPost.releaseConnection(); + } + } +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddMediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddMediaDownloadRequestExecutor.java new file mode 100644 index 00000000..f392f5ac --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddMediaDownloadRequestExecutor.java @@ -0,0 +1,79 @@ +package me.chanjar.weixin.common.util.http.jodd; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.lang3.StringUtils; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.fs.FileUtils; +import me.chanjar.weixin.common.util.http.MediaDownloadRequestExecutor; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class JoddMediaDownloadRequestExecutor extends MediaDownloadRequestExecutor { + + + public JoddMediaDownloadRequestExecutor(RequestHttp requestHttp, File tmpDirFile) { + super(requestHttp, tmpDirFile); + } + + @Override + public File execute(String uri, String queryParam) throws WxErrorException, IOException { + if (queryParam != null) { + if (uri.indexOf('?') == -1) { + uri += '?'; + } + uri += uri.endsWith("?") ? queryParam : '&' + queryParam; + } + + HttpRequest request = HttpRequest.get(uri); + if (requestHttp.getRequestHttpProxy() != null) { + requestHttp.getRequestHttpClient().useProxy(requestHttp.getRequestHttpProxy()); + } + request.withConnectionProvider(requestHttp.getRequestHttpClient()); + + HttpResponse response = request.send(); + String contentType = response.header("Content-Type"); + if (contentType != null && contentType.startsWith("application/json")) { + // application/json; encoding=utf-8 下载媒体文件出错 + throw new WxErrorException(WxError.fromJson(response.bodyText())); + } + + String fileName = getFileName(response); + if (StringUtils.isBlank(fileName)) { + return null; + } + + InputStream inputStream = new ByteArrayInputStream(response.bodyBytes()); + String[] nameAndExt = fileName.split("\\."); + return FileUtils.createTmpFile(inputStream, nameAndExt[0], nameAndExt[1], super.tmpDirFile); + } + + private String getFileName(HttpResponse response) throws WxErrorException { + String content = response.header("Content-disposition"); + if (content == null || content.length() == 0) { + throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); + } + + Pattern p = Pattern.compile(".*filename=\"(.*)\""); + Matcher m = p.matcher(content); + if (m.matches()) { + return m.group(1); + } + throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); + } + +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddMediaUploadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddMediaUploadRequestExecutor.java new file mode 100644 index 00000000..91cae4fc --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddMediaUploadRequestExecutor.java @@ -0,0 +1,41 @@ +package me.chanjar.weixin.common.util.http.jodd; + +import java.io.File; +import java.io.IOException; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class JoddMediaUploadRequestExecutor extends MediaUploadRequestExecutor { + public JoddMediaUploadRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public WxMediaUploadResult execute(String uri, File file) throws WxErrorException, IOException { + HttpRequest request = HttpRequest.post(uri); + if (requestHttp.getRequestHttpProxy() != null) { + requestHttp.getRequestHttpClient().useProxy(requestHttp.getRequestHttpProxy()); + } + request.withConnectionProvider(requestHttp.getRequestHttpClient()); + request.form("media", file); + HttpResponse response = request.send(); + String responseContent = response.bodyText(); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return WxMediaUploadResult.fromJson(responseContent); + } +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddSimpleGetRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddSimpleGetRequestExecutor.java new file mode 100644 index 00000000..ea44e5a6 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddSimpleGetRequestExecutor.java @@ -0,0 +1,54 @@ +package me.chanjar.weixin.common.util.http.jodd; + +import java.io.IOException; + +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.impl.client.CloseableHttpClient; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; +import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; + +/** + * Created by ecoolper on 2017/5/4. + */ +public class JoddSimpleGetRequestExecutor extends SimpleGetRequestExecutor { + + public JoddSimpleGetRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public String execute(String uri, String queryParam) throws WxErrorException, IOException { + if (queryParam != null) { + if (uri.indexOf('?') == -1) { + uri += '?'; + } + uri += uri.endsWith("?") ? queryParam : '&' + queryParam; + } + + HttpRequest request = HttpRequest.get(uri); + if (requestHttp.getRequestHttpProxy() != null) { + requestHttp.getRequestHttpClient().useProxy(requestHttp.getRequestHttpProxy()); + } + request.withConnectionProvider(requestHttp.getRequestHttpClient()); + HttpResponse response = request.send(); + String responseContent = response.bodyText(); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return responseContent; + } + +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddSimplePostRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddSimplePostRequestExecutor.java new file mode 100644 index 00000000..59eea7b2 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddSimplePostRequestExecutor.java @@ -0,0 +1,58 @@ +package me.chanjar.weixin.common.util.http.jodd; + +import java.io.IOException; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; + +/** + * Created by ecoolper on 2017/5/4. + */ +public class JoddSimplePostRequestExecutor extends SimplePostRequestExecutor { + + public JoddSimplePostRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public String execute(String uri, String postEntity) throws WxErrorException, IOException { + HttpConnectionProvider provider = requestHttp.getRequestHttpClient(); + ProxyInfo proxyInfo = requestHttp.getRequestHttpProxy(); + + HttpRequest request = HttpRequest.post(uri); + if (proxyInfo != null) { + provider.useProxy(proxyInfo); + } + request.withConnectionProvider(provider); + if (postEntity != null) { + request.bodyText(postEntity); + } + HttpResponse response = request.send(); + + String responseContent = response.bodyText(); + if (responseContent.isEmpty()) { + throw new WxErrorException( + WxError.newBuilder().setErrorCode(9999).setErrorMsg("无响应内容") + .build()); + } + + if (responseContent.startsWith("")) { + //xml格式输出直接返回 + return responseContent; + } + + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return responseContent; + } + +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkMediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkMediaDownloadRequestExecutor.java new file mode 100644 index 00000000..a2f6f8ed --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkMediaDownloadRequestExecutor.java @@ -0,0 +1,92 @@ +package me.chanjar.weixin.common.util.http.okhttp; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.lang3.StringUtils; + +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.fs.FileUtils; +import me.chanjar.weixin.common.util.http.MediaDownloadRequestExecutor; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; +import okhttp3.*; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class OkMediaDownloadRequestExecutor extends MediaDownloadRequestExecutor { + + + public OkMediaDownloadRequestExecutor(RequestHttp requestHttp, File tmpDirFile) { + super(requestHttp, tmpDirFile); + } + + @Override + public File execute(String uri, String queryParam) throws WxErrorException, IOException { + if (queryParam != null) { + if (uri.indexOf('?') == -1) { + uri += '?'; + } + uri += uri.endsWith("?") ? queryParam : '&' + queryParam; + } + + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(requestHttp.getRequestHttpClient()); + //设置代理 + if (requestHttp.getRequestHttpProxy() != null) { + clientBuilder.proxy(requestHttp.getRequestHttpProxy().getProxy()); + } + //设置授权 + clientBuilder.authenticator(new Authenticator() { + @Override + public Request authenticate(Route route, Response response) throws IOException { + String credential = Credentials.basic(requestHttp.getRequestHttpProxy().getProxyUsername(), requestHttp.getRequestHttpProxy().getProxyPassword()); + return response.request().newBuilder() + .header("Authorization", credential) + .build(); + } + }); + //得到httpClient + OkHttpClient client = clientBuilder.build(); + + Request request = new Request.Builder().url(uri).get().build(); + + Response response = client.newCall(request).execute(); + + String contentType = response.header("Content-Type"); + if (contentType != null && contentType.startsWith("application/json")) { + // application/json; encoding=utf-8 下载媒体文件出错 + throw new WxErrorException(WxError.fromJson(response.body().string())); + } + + String fileName = getFileName(response); + if (StringUtils.isBlank(fileName)) { + return null; + } + + InputStream inputStream = new ByteArrayInputStream(response.body().bytes()); + String[] nameAndExt = fileName.split("\\."); + return FileUtils.createTmpFile(inputStream, nameAndExt[0], nameAndExt[1], super.tmpDirFile); + } + + private String getFileName(Response response) throws WxErrorException { + String content = response.header("Content-disposition"); + if (content == null || content.length() == 0) { + throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); + } + + Pattern p = Pattern.compile(".*filename=\"(.*)\""); + Matcher m = p.matcher(content); + if (m.matches()) { + return m.group(1); + } + throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); + } + +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkMediaUploadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkMediaUploadRequestExecutor.java new file mode 100644 index 00000000..b3808956 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkMediaUploadRequestExecutor.java @@ -0,0 +1,56 @@ +package me.chanjar.weixin.common.util.http.okhttp; + +import java.io.File; +import java.io.IOException; + +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; +import okhttp3.*; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class OkMediaUploadRequestExecutor extends MediaUploadRequestExecutor { + + public OkMediaUploadRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public WxMediaUploadResult execute(String uri, File file) throws WxErrorException, IOException { + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(requestHttp.getRequestHttpClient()); + //设置代理 + if (requestHttp.getRequestHttpProxy() != null) { + clientBuilder.proxy(requestHttp.getRequestHttpProxy().getProxy()); + } + //设置授权 + clientBuilder.authenticator(new Authenticator() { + @Override + public Request authenticate(Route route, Response response) throws IOException { + String credential = Credentials.basic(requestHttp.getRequestHttpProxy().getProxyUsername(), requestHttp.getRequestHttpProxy().getProxyPassword()); + return response.request().newBuilder() + .header("Authorization", credential) + .build(); + } + }); + //得到httpClient + OkHttpClient client = clientBuilder.build(); + + RequestBody fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), file); + RequestBody body = new MultipartBody.Builder().addFormDataPart("media", null, fileBody).build(); + Request request = new Request.Builder().url(uri).post(body).build(); + + Response response = client.newCall(request).execute(); + String responseContent = response.body().string(); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return WxMediaUploadResult.fromJson(responseContent); + } + +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkSimpleGetRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkSimpleGetRequestExecutor.java new file mode 100644 index 00000000..5d77bf7d --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkSimpleGetRequestExecutor.java @@ -0,0 +1,63 @@ +package me.chanjar.weixin.common.util.http.okhttp; + +import java.io.IOException; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; +import okhttp3.*; + +/** + * Created by ecoolper on 2017/5/4. + */ +public class OkSimpleGetRequestExecutor extends SimpleGetRequestExecutor { + + public OkSimpleGetRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public String execute(String uri, String queryParam) throws WxErrorException, IOException { + if (queryParam != null) { + if (uri.indexOf('?') == -1) { + uri += '?'; + } + uri += uri.endsWith("?") ? queryParam : '&' + queryParam; + } + + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(requestHttp.getRequestHttpClient()); + //设置代理 + if (requestHttp.getRequestHttpProxy() != null) { + clientBuilder.proxy(requestHttp.getRequestHttpProxy().getProxy()); + } + //设置授权 + clientBuilder.authenticator(new Authenticator() { + @Override + public Request authenticate(Route route, Response response) throws IOException { + String credential = Credentials.basic(requestHttp.getRequestHttpProxy().getProxyUsername(), requestHttp.getRequestHttpProxy().getProxyPassword()); + return response.request().newBuilder() + .header("Authorization", credential) + .build(); + } + }); + //得到httpClient + OkHttpClient client =clientBuilder.build(); + + Request request = new Request.Builder().url(uri).build(); + + Response response = client.newCall(request).execute(); + String responseContent = response.body().string(); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return responseContent; + } + +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkSimplePostRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkSimplePostRequestExecutor.java new file mode 100644 index 00000000..1fddcb26 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkSimplePostRequestExecutor.java @@ -0,0 +1,59 @@ +package me.chanjar.weixin.common.util.http.okhttp; + +import java.io.IOException; + +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; +import okhttp3.*; + +/** + * Created by ecoolper on 2017/5/4. + */ +public class OkSimplePostRequestExecutor extends SimplePostRequestExecutor{ + + public OkSimplePostRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public String execute(String uri, String postEntity) throws WxErrorException, IOException { + ConnectionPool pool = requestHttp.getRequestHttpClient(); + final OkhttpProxyInfo proxyInfo = requestHttp.getRequestHttpProxy(); + + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(pool); + //设置代理 + if (proxyInfo != null) { + clientBuilder.proxy(proxyInfo.getProxy()); + } + //设置授权 + clientBuilder.authenticator(new Authenticator() { + @Override + public Request authenticate(Route route, Response response) throws IOException { + String credential = Credentials.basic(proxyInfo.getProxyUsername(), proxyInfo.getProxyPassword()); + return response.request().newBuilder() + .header("Authorization", credential) + .build(); + } + }); + //得到httpClient + OkHttpClient client = clientBuilder.build(); + + + MediaType mediaType = MediaType.parse("text/plain; charset=utf-8"); + RequestBody body = RequestBody.create(mediaType, postEntity); + + Request request = new Request.Builder().url(uri).post(body).build(); + + Response response = client.newCall(request).execute(); + String responseContent = response.body().string(); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return responseContent; + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/AbstractWxCpServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/AbstractWxCpServiceImpl.java index 27928d8b..85065a71 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/AbstractWxCpServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/AbstractWxCpServiceImpl.java @@ -93,7 +93,7 @@ public abstract class AbstractWxCpServiceImpl implements WxCpService, Requ synchronized (this.globalJsapiTicketRefreshLock) { if (this.configStorage.isJsapiTicketExpired()) { String url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket"; - String responseContent = execute(new SimpleGetRequestExecutor(), url, null); + String responseContent = execute(SimpleGetRequestExecutor.create(this), url, null); JsonElement tmpJsonElement = new JsonParser().parse(responseContent); JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); @@ -187,14 +187,14 @@ public abstract class AbstractWxCpServiceImpl implements WxCpService, Requ @Override public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException { String url = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?type=" + mediaType; - return execute(new MediaUploadRequestExecutor(), url, file); + return execute(MediaUploadRequestExecutor.create(this), url, file); } @Override public File mediaDownload(String mediaId) throws WxErrorException { String url = "https://qyapi.weixin.qq.com/cgi-bin/media/get"; return execute( - new MediaDownloadRequestExecutor( + MediaDownloadRequestExecutor.create(this, this.configStorage.getTmpDirFile()), url, "media_id=" + mediaId); } @@ -204,7 +204,7 @@ public abstract class AbstractWxCpServiceImpl implements WxCpService, Requ public Integer departCreate(WxCpDepart depart) throws WxErrorException { String url = "https://qyapi.weixin.qq.com/cgi-bin/department/create"; String responseContent = execute( - new SimplePostRequestExecutor(), + SimplePostRequestExecutor.create(this), url, depart.toJson()); JsonElement tmpJsonElement = new JsonParser().parse(responseContent); @@ -475,12 +475,12 @@ public abstract class AbstractWxCpServiceImpl implements WxCpService, Requ @Override public String get(String url, String queryParam) throws WxErrorException { - return execute(new SimpleGetRequestExecutor(), url, queryParam); + return execute(SimpleGetRequestExecutor.create(this), url, queryParam); } @Override public String post(String url, String postData) throws WxErrorException { - return execute(new SimplePostRequestExecutor(), url, postData); + return execute(SimplePostRequestExecutor.create(this), url, postData); } /** @@ -530,7 +530,7 @@ public abstract class AbstractWxCpServiceImpl implements WxCpService, Requ String uriWithAccessToken = uri + (uri.contains("?") ? "&" : "?") + "access_token=" + accessToken; try { - T result = executor.execute(this, uriWithAccessToken, data); + T result = executor.execute(uriWithAccessToken, data); this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", uriWithAccessToken, data, result); return result; } catch (WxErrorException e) { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpCardService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpCardService.java index 35a23f70..34a80fc5 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpCardService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpCardService.java @@ -8,7 +8,7 @@ import me.chanjar.weixin.mp.bean.result.WxMpCardResult; * 卡券相关接口 * @author YuJian(mgcnrx11@hotmail.com) on 01/11/2016 */ -public interface WxMpCardService { +public interface WxMpCardService { /** * 得到WxMpService diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java index 8f03350b..da51c001 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java @@ -4,6 +4,7 @@ import me.chanjar.weixin.common.bean.WxJsapiSignature; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; import me.chanjar.weixin.mp.bean.*; import me.chanjar.weixin.mp.bean.result.*; @@ -414,5 +415,11 @@ public interface WxMpService { */ void initHttp(); + /** + * + * @return + */ + RequestHttp getRequestHttp(); + } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/AbstractWxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/AbstractWxMpServiceImpl.java index 00880ffd..527f6fe2 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/AbstractWxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/AbstractWxMpServiceImpl.java @@ -45,6 +45,7 @@ public abstract class AbstractWxMpServiceImpl implements WxMpService, Requ private int retrySleepMillis = 1000; private int maxRetryTimes = 5; + @Override public boolean checkSignature(String timestamp, String nonce, String signature) { try { @@ -71,7 +72,7 @@ public abstract class AbstractWxMpServiceImpl implements WxMpService, Requ } if (this.getWxMpConfigStorage().isJsapiTicketExpired()) { - String responseContent = execute(new SimpleGetRequestExecutor(), WxMpService.GET_JSAPI_TICKET_URL, null); + String responseContent = execute(SimpleGetRequestExecutor.create(this), WxMpService.GET_JSAPI_TICKET_URL, null); JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); @@ -165,8 +166,8 @@ public abstract class AbstractWxMpServiceImpl implements WxMpService, Requ private WxMpOAuth2AccessToken getOAuth2AccessToken(String url) throws WxErrorException { try { - RequestExecutor executor = new SimpleGetRequestExecutor(); - String responseText = executor.execute(this, url, null); + RequestExecutor executor = SimpleGetRequestExecutor.create(this); + String responseText = executor.execute(url, null); return WxMpOAuth2AccessToken.fromJson(responseText); } catch (IOException e) { throw new RuntimeException(e); @@ -194,8 +195,8 @@ public abstract class AbstractWxMpServiceImpl implements WxMpService, Requ String url = String.format(WxMpService.OAUTH2_USERINFO_URL, oAuth2AccessToken.getAccessToken(), oAuth2AccessToken.getOpenId(), lang); try { - RequestExecutor executor = new SimpleGetRequestExecutor(); - String responseText = executor.execute(this, url, null); + RequestExecutor executor = SimpleGetRequestExecutor.create(this); + String responseText = executor.execute(url, null); return WxMpUser.fromJson(responseText); } catch (IOException e) { throw new RuntimeException(e); @@ -207,8 +208,8 @@ public abstract class AbstractWxMpServiceImpl implements WxMpService, Requ String url = String.format(WxMpService.OAUTH2_VALIDATE_TOKEN_URL, oAuth2AccessToken.getAccessToken(), oAuth2AccessToken.getOpenId()); try { - RequestExecutor executor = new SimpleGetRequestExecutor(); - executor.execute(this, url, null); + RequestExecutor executor = SimpleGetRequestExecutor.create(this); + executor.execute(url, null); } catch (IOException e) { throw new RuntimeException(e); } catch (WxErrorException e) { @@ -231,12 +232,12 @@ public abstract class AbstractWxMpServiceImpl implements WxMpService, Requ @Override public String get(String url, String queryParam) throws WxErrorException { - return execute(new SimpleGetRequestExecutor(), url, queryParam); + return execute(SimpleGetRequestExecutor.create(this), url, queryParam); } @Override public String post(String url, String postData) throws WxErrorException { - return execute(new SimplePostRequestExecutor(), url, postData); + return execute(SimplePostRequestExecutor.create(this), url, postData); } /** @@ -283,7 +284,7 @@ public abstract class AbstractWxMpServiceImpl implements WxMpService, Requ String uriWithAccessToken = uri + (uri.contains("?") ? "&" : "?") + "access_token=" + accessToken; try { - T result = executor.execute(this, uriWithAccessToken, data); + T result = executor.execute(uriWithAccessToken, data); this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", uriWithAccessToken, data, result); return result; } catch (WxErrorException e) { 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 9e64d043..388bca56 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 @@ -15,8 +15,6 @@ import me.chanjar.weixin.mp.api.WxMpCardService; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.bean.result.WxMpCardResult; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; -import org.apache.http.HttpHost; -import org.apache.http.impl.client.CloseableHttpClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,7 +24,7 @@ import java.util.concurrent.locks.Lock; /** * Created by Binary Wang on 2016/7/27. */ -public class WxMpCardServiceImpl implements WxMpCardService { +public class WxMpCardServiceImpl implements WxMpCardService { private final Logger log = LoggerFactory.getLogger(WxMpCardServiceImpl.class); @@ -81,7 +79,7 @@ public class WxMpCardServiceImpl implements WxMpCardService map = new HashMap<>(); map.put("openid_list", openidList); String url = API_BLACKLIST_PREFIX + "/batchblacklist"; - this.wxMpService.execute(new SimplePostRequestExecutor(), url, new Gson().toJson(map)); + this.wxMpService.execute(SimplePostRequestExecutor.create(this.wxMpService.getRequestHttp()), url, new Gson().toJson(map)); } @Override @@ -45,6 +45,6 @@ public class WxMpUserBlacklistServiceImpl implements WxMpUserBlacklistService { Map map = new HashMap<>(); map.put("openid_list", openidList); String url = API_BLACKLIST_PREFIX + "/batchunblacklist"; - this.wxMpService.execute(new SimplePostRequestExecutor(), url, new Gson().toJson(map)); + this.wxMpService.execute(SimplePostRequestExecutor.create(this.wxMpService.getRequestHttp()), url, new Gson().toJson(map)); } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpServiceImpl.java index 835fbe18..d0991a5b 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/apache/WxMpServiceImpl.java @@ -71,6 +71,11 @@ public class WxMpServiceImpl extends AbstractWxMpServiceImpl { +public abstract class MaterialDeleteRequestExecutor implements RequestExecutor { + protected RequestHttp requestHttp; - - public MaterialDeleteRequestExecutor() { - super(); - } - - @Override - public Boolean executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, - String materialId) throws WxErrorException, IOException { - HttpPost httpPost = new HttpPost(uri); - if (httpProxy != null) { - RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); - httpPost.setConfig(config); - } - - Map params = new HashMap<>(); - params.put("media_id", materialId); - httpPost.setEntity(new StringEntity(WxGsonBuilder.create().toJson(params))); - try (CloseableHttpResponse response = httpclient.execute(httpPost)) { - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } else { - return true; - } - } finally { - httpPost.releaseConnection(); - } - } - - - @Override - public Boolean executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, String materialId) throws WxErrorException, IOException { - HttpRequest request = HttpRequest.post(uri); - if (proxyInfo != null) { - provider.useProxy(proxyInfo); - } - request.withConnectionProvider(provider); - - request.query("media_id", materialId); - HttpResponse response = request.send(); - String responseContent = response.bodyText(); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } else { - return true; - } + public MaterialDeleteRequestExecutor(RequestHttp requestHttp){ + this.requestHttp =requestHttp; } - @Override - public Boolean executeOkhttp(ConnectionPool pool, final OkhttpProxyInfo proxyInfo, String uri, String materialId) throws WxErrorException, IOException { - OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(pool); - //设置代理 - if (proxyInfo != null) { - clientBuilder.proxy(proxyInfo.getProxy()); - } - //设置授权 - clientBuilder.authenticator(new Authenticator() { - @Override - public Request authenticate(Route route, Response response) throws IOException { - String credential = Credentials.basic(proxyInfo.getProxyUsername(), proxyInfo.getProxyPassword()); - return response.request().newBuilder() - .header("Authorization", credential) - .build(); - } - }); - //得到httpClient - OkHttpClient client = clientBuilder.build(); - - RequestBody requestBody = new FormBody.Builder().add("media_id", materialId).build(); - Request request = new Request.Builder().url(uri).post(requestBody).build(); - Response response = client.newCall(request).execute(); - String responseContent = response.body().string(); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } else { - return true; + public static RequestExecutor create(RequestHttp requestHttp){ + switch (requestHttp.getRequestType()){ + case apacheHttp: + return new ApacheMaterialDeleteRequestExecutor(requestHttp); + case joddHttp: + return new JoddMaterialDeleteRequestExecutor(requestHttp); + case okHttp: + return new OkhttpMaterialDeleteRequestExecutor(requestHttp); + default: + return null; } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialNewsInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialNewsInfoRequestExecutor.java index de5f2342..92188b2a 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialNewsInfoRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialNewsInfoRequestExecutor.java @@ -6,7 +6,6 @@ import jodd.http.HttpResponse; import jodd.http.ProxyInfo; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.AbstractRequestExecutor; import me.chanjar.weixin.common.util.http.RequestExecutor; import me.chanjar.weixin.common.util.http.RequestHttp; import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; @@ -15,6 +14,9 @@ import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; import me.chanjar.weixin.common.util.json.WxGsonBuilder; import me.chanjar.weixin.mp.bean.material.WxMpMaterialNews; +import me.chanjar.weixin.mp.util.http.apache.ApacheMaterialNewsInfoRequestExecutor; +import me.chanjar.weixin.mp.util.http.jodd.JoddMaterialNewsInfoRequestExecutor; +import me.chanjar.weixin.mp.util.http.okhttp.OkhttpMaterialNewsInfoRequestExecutor; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; import okhttp3.*; @@ -29,88 +31,24 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -public class MaterialNewsInfoRequestExecutor extends AbstractRequestExecutor { +public abstract class MaterialNewsInfoRequestExecutor implements RequestExecutor { + protected RequestHttp requestHttp; - public MaterialNewsInfoRequestExecutor() { - super(); + public MaterialNewsInfoRequestExecutor(RequestHttp requestHttp){ + this.requestHttp =requestHttp; } - @Override - public WxMpMaterialNews executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String materialId) throws WxErrorException, IOException { - HttpPost httpPost = new HttpPost(uri); - if (httpProxy != null) { - RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); - httpPost.setConfig(config); - } - - Map params = new HashMap<>(); - params.put("media_id", materialId); - httpPost.setEntity(new StringEntity(WxGsonBuilder.create().toJson(params))); - try (CloseableHttpResponse response = httpclient.execute(httpPost)) { - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } else { - return WxMpGsonBuilder.create().fromJson(responseContent, WxMpMaterialNews.class); - } - } finally { - httpPost.releaseConnection(); - } - } - - - @Override - public WxMpMaterialNews executeJodd(HttpConnectionProvider httpclient, ProxyInfo httpProxy, String uri, String materialId) throws WxErrorException, IOException { - HttpRequest request = HttpRequest.post(uri); - if (httpProxy != null) { - httpclient.useProxy(httpProxy); - } - request.withConnectionProvider(httpclient); - - request.query("media_id", materialId); - HttpResponse response = request.send(); - - String responseContent = response.bodyText(); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } else { - return WxMpGsonBuilder.create().fromJson(responseContent, WxMpMaterialNews.class); - } - } - - @Override - public WxMpMaterialNews executeOkhttp(ConnectionPool pool, final OkhttpProxyInfo proxyInfo, String uri, String materialId) throws WxErrorException, IOException { - OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(pool); - //设置代理 - if (proxyInfo != null) { - clientBuilder.proxy(proxyInfo.getProxy()); - } - //设置授权 - clientBuilder.authenticator(new Authenticator() { - @Override - public Request authenticate(Route route, Response response) throws IOException { - String credential = Credentials.basic(proxyInfo.getProxyUsername(), proxyInfo.getProxyPassword()); - return response.request().newBuilder() - .header("Authorization", credential) - .build(); - } - }); - //得到httpClient - OkHttpClient client = clientBuilder.build(); - - RequestBody requestBody = new FormBody.Builder().add("media_id", materialId).build(); - Request request = new Request.Builder().url(uri).post(requestBody).build(); - - Response response = client.newCall(request).execute(); - String responseContent = response.body().string(); - - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } else { - return WxMpGsonBuilder.create().fromJson(responseContent, WxMpMaterialNews.class); + public static RequestExecutor create(RequestHttp requestHttp){ + switch (requestHttp.getRequestType()){ + case apacheHttp: + return new ApacheMaterialNewsInfoRequestExecutor(requestHttp); + case joddHttp: + return new JoddMaterialNewsInfoRequestExecutor(requestHttp); + case okHttp: + return new OkhttpMaterialNewsInfoRequestExecutor(requestHttp); + default: + //TODO 需要优化抛出异常 + return null; } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialUploadRequestExecutor.java index 772684ab..54d1d0e7 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialUploadRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialUploadRequestExecutor.java @@ -6,7 +6,6 @@ import jodd.http.HttpResponse; import jodd.http.ProxyInfo; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.AbstractRequestExecutor; import me.chanjar.weixin.common.util.http.RequestExecutor; import me.chanjar.weixin.common.util.http.RequestHttp; import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; @@ -16,6 +15,9 @@ import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; 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 me.chanjar.weixin.mp.util.http.apache.ApacheMaterialUploadRequestExecutor; +import me.chanjar.weixin.mp.util.http.jodd.JoddMaterialUploadRequestExecutor; +import me.chanjar.weixin.mp.util.http.okhttp.OkhttpMaterialUploadRequestExecutor; import okhttp3.*; import org.apache.http.HttpHost; @@ -32,127 +34,22 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.util.Map; -public class MaterialUploadRequestExecutor extends AbstractRequestExecutor { - - @Override - public WxMpMaterialUploadResult executeJodd(HttpConnectionProvider provider, ProxyInfo httpProxy, String uri, WxMpMaterial material) throws WxErrorException, IOException { - HttpRequest request = HttpRequest.post(uri); - if (httpProxy != null) { - provider.useProxy(httpProxy); - } - request.withConnectionProvider(provider); - - if (material == null) { - throw new WxErrorException(WxError.newBuilder().setErrorMsg("非法请求,material参数为空").build()); - } - - File file = material.getFile(); - if (file == null || !file.exists()) { - throw new FileNotFoundException(); - } - request.form("media", file); - Map form = material.getForm(); - if (material.getForm() != null) { - request.form("description", WxGsonBuilder.create().toJson(form)); - } - - HttpResponse response = request.send(); - String responseContent = response.bodyText(); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } else { - return WxMpMaterialUploadResult.fromJson(responseContent); - } - } - - @Override - public WxMpMaterialUploadResult executeOkhttp(ConnectionPool pool, final OkhttpProxyInfo proxyInfo, String uri, WxMpMaterial material) throws WxErrorException, IOException { - OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(pool); - //设置代理 - if (proxyInfo != null) { - clientBuilder.proxy(proxyInfo.getProxy()); - } - //设置授权 - clientBuilder.authenticator(new Authenticator() { - @Override - public Request authenticate(Route route, Response response) throws IOException { - String credential = Credentials.basic(proxyInfo.getProxyUsername(), proxyInfo.getProxyPassword()); - return response.request().newBuilder() - .header("Authorization", credential) - .build(); - } - }); - //得到httpClient - OkHttpClient client = clientBuilder.build(); - - - if (material == null) { - throw new WxErrorException(WxError.newBuilder().setErrorMsg("非法请求,material参数为空").build()); - } - - File file = material.getFile(); - if (file == null || !file.exists()) { - throw new FileNotFoundException(); - } - RequestBody fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), file); - MultipartBody.Builder bodyBuilder = new MultipartBody.Builder().addFormDataPart("media", null, fileBody); - Map form = material.getForm(); - if (material.getForm() != null) { - bodyBuilder.addFormDataPart("description", WxGsonBuilder.create().toJson(form)); - } - RequestBody body =bodyBuilder.build(); - Request request = new Request.Builder().url(uri).post(body).build(); - Response response = client.newCall(request).execute(); - String responseContent = response.body().string(); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } else { - return WxMpMaterialUploadResult.fromJson(responseContent); - } +public abstract class MaterialUploadRequestExecutor implements RequestExecutor { + protected RequestHttp requestHttp; + public MaterialUploadRequestExecutor(RequestHttp requestHttp){ + this.requestHttp =requestHttp; } - @Override - public WxMpMaterialUploadResult executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, - WxMpMaterial material) throws WxErrorException, IOException { - HttpPost httpPost = new HttpPost(uri); - if (httpProxy != null) { - RequestConfig response = RequestConfig.custom().setProxy(httpProxy).build(); - httpPost.setConfig(response); - } - - if (material == null) { - throw new WxErrorException(WxError.newBuilder().setErrorMsg("非法请求,material参数为空").build()); - } - - File file = material.getFile(); - if (file == null || !file.exists()) { - throw new FileNotFoundException(); - } - - MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create(); - multipartEntityBuilder - .addBinaryBody("media", file) - .setMode(HttpMultipartMode.RFC6532); - Map form = material.getForm(); - if (material.getForm() != null) { - multipartEntityBuilder.addTextBody("description", WxGsonBuilder.create().toJson(form)); - } - - httpPost.setEntity(multipartEntityBuilder.build()); - httpPost.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.toString()); - - try (CloseableHttpResponse response = httpclient.execute(httpPost)) { - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } else { - return WxMpMaterialUploadResult.fromJson(responseContent); - } - } finally { - httpPost.releaseConnection(); + public static RequestExecutor create(RequestHttp requestHttp){ + switch (requestHttp.getRequestType()){ + case apacheHttp: + return new ApacheMaterialUploadRequestExecutor(requestHttp); + case joddHttp: + return new JoddMaterialUploadRequestExecutor(requestHttp); + case okHttp: + return new OkhttpMaterialUploadRequestExecutor(requestHttp); + default: + return null; } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVideoInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVideoInfoRequestExecutor.java index 3c481f7c..c042d261 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVideoInfoRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVideoInfoRequestExecutor.java @@ -6,7 +6,6 @@ import jodd.http.HttpResponse; import jodd.http.ProxyInfo; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.AbstractRequestExecutor; import me.chanjar.weixin.common.util.http.RequestExecutor; import me.chanjar.weixin.common.util.http.RequestHttp; import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; @@ -14,8 +13,10 @@ import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; import me.chanjar.weixin.common.util.json.WxGsonBuilder; -import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult; import me.chanjar.weixin.mp.bean.material.WxMpMaterialVideoInfoResult; +import me.chanjar.weixin.mp.util.http.apache.ApacheMaterialVideoInfoRequestExecutor; +import me.chanjar.weixin.mp.util.http.jodd.JoddMaterialVideoInfoRequestExecutor; +import me.chanjar.weixin.mp.util.http.okhttp.OkhttpMaterialVideoInfoRequestExecutor; import okhttp3.*; import org.apache.http.HttpHost; @@ -29,87 +30,23 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -public class MaterialVideoInfoRequestExecutor extends AbstractRequestExecutor { - - public MaterialVideoInfoRequestExecutor() { - super(); - } - - @Override - public WxMpMaterialVideoInfoResult executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, String materialId) throws WxErrorException, IOException { - HttpRequest request = HttpRequest.post(uri); - if (proxyInfo != null) { - provider.useProxy(proxyInfo); - } - request.withConnectionProvider(provider); - - request.query("media_id", materialId); - HttpResponse response = request.send(); - String responseContent = response.bodyText(); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } else { - return WxMpMaterialVideoInfoResult.fromJson(responseContent); - } - } - - @Override - public WxMpMaterialVideoInfoResult executeOkhttp(ConnectionPool pool, final OkhttpProxyInfo proxyInfo, String uri, String materialId) throws WxErrorException, IOException { - OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(pool); - //设置代理 - if (proxyInfo != null) { - clientBuilder.proxy(proxyInfo.getProxy()); - } - //设置授权 - clientBuilder.authenticator(new Authenticator() { - @Override - public Request authenticate(Route route, Response response) throws IOException { - String credential = Credentials.basic(proxyInfo.getProxyUsername(), proxyInfo.getProxyPassword()); - return response.request().newBuilder() - .header("Authorization", credential) - .build(); - } - }); - //得到httpClient - OkHttpClient client = clientBuilder.build(); - - RequestBody requestBody =new FormBody.Builder().add("media_id", materialId).build(); - Request request = new Request.Builder().url(uri).post(requestBody).build(); - Response response = client.newCall(request).execute(); - String responseContent = response.body().string(); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } else { - return WxMpMaterialVideoInfoResult.fromJson(responseContent); - } +public abstract class MaterialVideoInfoRequestExecutor implements RequestExecutor { + protected RequestHttp requestHttp; + public MaterialVideoInfoRequestExecutor(RequestHttp requestHttp){ + this.requestHttp =requestHttp; } - @Override - public WxMpMaterialVideoInfoResult executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, - String materialId) throws WxErrorException, IOException { - HttpPost httpPost = new HttpPost(uri); - if (httpProxy != null) { - RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); - httpPost.setConfig(config); - } - - Map params = new HashMap<>(); - params.put("media_id", materialId); - httpPost.setEntity(new StringEntity(WxGsonBuilder.create().toJson(params))); - try (CloseableHttpResponse response = httpclient.execute(httpPost)) { - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } else { - return WxMpMaterialVideoInfoResult.fromJson(responseContent); - } - } finally { - httpPost.releaseConnection(); + public static RequestExecutor create(RequestHttp requestHttp){ + switch (requestHttp.getRequestType()){ + case apacheHttp: + return new ApacheMaterialVideoInfoRequestExecutor(requestHttp); + case joddHttp: + return new JoddMaterialVideoInfoRequestExecutor(requestHttp); + case okHttp: + return new OkhttpMaterialVideoInfoRequestExecutor(requestHttp); + default: + return null; } } - } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVoiceAndImageDownloadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVoiceAndImageDownloadRequestExecutor.java index d536223c..75255346 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVoiceAndImageDownloadRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVoiceAndImageDownloadRequestExecutor.java @@ -7,13 +7,14 @@ import jodd.http.ProxyInfo; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.AbstractRequestExecutor; import me.chanjar.weixin.common.util.http.RequestExecutor; import me.chanjar.weixin.common.util.http.RequestHttp; import me.chanjar.weixin.common.util.http.apache.InputStreamResponseHandler; import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; import me.chanjar.weixin.common.util.json.WxGsonBuilder; -import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult; +import me.chanjar.weixin.mp.util.http.apache.ApacheMaterialVoiceAndImageDownloadRequestExecutor; +import me.chanjar.weixin.mp.util.http.jodd.JoddMaterialVoiceAndImageDownloadRequestExecutor; +import me.chanjar.weixin.mp.util.http.okhttp.OkhttpMaterialVoiceAndImageDownloadRequestExecutor; import okhttp3.*; import org.apache.commons.io.IOUtils; @@ -31,119 +32,27 @@ import java.io.InputStream; import java.util.HashMap; import java.util.Map; -public class MaterialVoiceAndImageDownloadRequestExecutor extends AbstractRequestExecutor { +public abstract class MaterialVoiceAndImageDownloadRequestExecutor implements RequestExecutor { + protected RequestHttp requestHttp; + protected File tmpDirFile; - public MaterialVoiceAndImageDownloadRequestExecutor() { - super(); - } - - public MaterialVoiceAndImageDownloadRequestExecutor(File tmpDirFile) { - super(); - } - - - @Override - public InputStream executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, String materialId) throws WxErrorException, IOException { - HttpRequest request = HttpRequest.post(uri); - if (proxyInfo != null) { - provider.useProxy(proxyInfo); - } - request.withConnectionProvider(provider); - - request.query("media_id", materialId); - HttpResponse response = request.send(); - try (InputStream inputStream = new ByteArrayInputStream(response.bodyBytes())) { - // 下载媒体文件出错 - byte[] responseContent = IOUtils.toByteArray(inputStream); - String responseContentString = new String(responseContent, "UTF-8"); - if (responseContentString.length() < 100) { - 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); - } + public MaterialVoiceAndImageDownloadRequestExecutor(RequestHttp requestHttp, File tmpDirFile) { + this.requestHttp = requestHttp; + this.tmpDirFile = tmpDirFile; } - @Override - public InputStream executeOkhttp(ConnectionPool pool, final OkhttpProxyInfo proxyInfo, String uri, String materialId) throws WxErrorException, IOException { - OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(pool); - //设置代理 - if (proxyInfo != null) { - clientBuilder.proxy(proxyInfo.getProxy()); - } - //设置授权 - clientBuilder.authenticator(new Authenticator() { - @Override - public Request authenticate(Route route, Response response) throws IOException { - String credential = Credentials.basic(proxyInfo.getProxyUsername(), proxyInfo.getProxyPassword()); - return response.request().newBuilder() - .header("Authorization", credential) - .build(); - } - }); - //得到httpClient - OkHttpClient client = clientBuilder.build(); - - RequestBody requestBody = new FormBody.Builder().add("media_id", materialId).build(); - Request request = new Request.Builder().url(uri).get().post(requestBody).build(); - Response response = client.newCall(request).execute(); - - try (InputStream inputStream = new ByteArrayInputStream(response.body().bytes())) { - - // 下载媒体文件出错 - byte[] responseContent = IOUtils.toByteArray(inputStream); - String responseContentString = new String(responseContent, "UTF-8"); - if (responseContentString.length() < 100) { - 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); - } - } - - @Override - public InputStream executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, - String materialId) throws WxErrorException, IOException { - HttpPost httpPost = new HttpPost(uri); - if (httpProxy != null) { - RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); - httpPost.setConfig(config); - } - Map params = new HashMap<>(); - params.put("media_id", materialId); - httpPost.setEntity(new StringEntity(WxGsonBuilder.create().toJson(params))); - try (CloseableHttpResponse response = httpclient.execute(httpPost); - InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response);) { - // 下载媒体文件出错 - byte[] responseContent = IOUtils.toByteArray(inputStream); - String responseContentString = new String(responseContent, "UTF-8"); - if (responseContentString.length() < 100) { - 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); - } finally { - httpPost.releaseConnection(); + public static RequestExecutor create(RequestHttp requestHttp, File tmpDirFile) { + switch (requestHttp.getRequestType()) { + case apacheHttp: + return new ApacheMaterialVoiceAndImageDownloadRequestExecutor(requestHttp, tmpDirFile); + case joddHttp: + return new JoddMaterialVoiceAndImageDownloadRequestExecutor(requestHttp, tmpDirFile); + case okHttp: + return new OkhttpMaterialVoiceAndImageDownloadRequestExecutor(requestHttp, tmpDirFile); + default: + return null; } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MediaImgUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MediaImgUploadRequestExecutor.java index 4232f333..f4713afd 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MediaImgUploadRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MediaImgUploadRequestExecutor.java @@ -5,13 +5,8 @@ import jodd.http.HttpRequest; import jodd.http.HttpResponse; import jodd.http.ProxyInfo; -import jodd.util.MimeTypes; - import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.fs.FileUtils; -import me.chanjar.weixin.common.util.http.AbstractRequestExecutor; import me.chanjar.weixin.common.util.http.RequestExecutor; import me.chanjar.weixin.common.util.http.RequestHttp; import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; @@ -19,6 +14,9 @@ import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult; +import me.chanjar.weixin.mp.util.http.apache.ApacheMediaImgUploadRequestExecutor; +import me.chanjar.weixin.mp.util.http.jodd.JoddMediaImgUploadRequestExecutor; +import me.chanjar.weixin.mp.util.http.okhttp.OkhttpMediaImgUploadRequestExecutor; import okhttp3.*; import org.apache.http.HttpEntity; @@ -31,104 +29,28 @@ import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.impl.client.CloseableHttpClient; -import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.util.UUID; /** * @author miller */ -public class MediaImgUploadRequestExecutor extends AbstractRequestExecutor { - - @Override - public WxMediaImgUploadResult executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, File data) throws WxErrorException, IOException { - if (data == null) { - throw new WxErrorException(WxError.newBuilder().setErrorMsg("文件对象为空").build()); - } - - HttpRequest request = HttpRequest.post(uri); - if (proxyInfo != null) { - provider.useProxy(proxyInfo); - } - request.withConnectionProvider(provider); - - request.form("media", data); - HttpResponse response = request.send(); - String responseContent = response.bodyText(); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } - - return WxMediaImgUploadResult.fromJson(responseContent); - } - - @Override - public WxMediaImgUploadResult executeOkhttp(ConnectionPool pool, final OkhttpProxyInfo proxyInfo, String uri, File data) throws WxErrorException, IOException { - OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(pool); - //设置代理 - if (proxyInfo != null) { - clientBuilder.proxy(proxyInfo.getProxy()); - } - //设置授权 - clientBuilder.authenticator(new Authenticator() { - @Override - public Request authenticate(Route route, Response response) throws IOException { - String credential = Credentials.basic(proxyInfo.getProxyUsername(), proxyInfo.getProxyPassword()); - return response.request().newBuilder() - .header("Authorization", credential) - .build(); - } - }); - //得到httpClient - OkHttpClient client = clientBuilder.build(); - - RequestBody fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), data); - RequestBody body = new MultipartBody.Builder().addFormDataPart("media", null, fileBody).build(); - Request request = new Request.Builder().url(uri).post(body).build(); - - Response response = client.newCall(request).execute(); - String responseContent = response.body().string(); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } - - return WxMediaImgUploadResult.fromJson(responseContent); +public abstract class MediaImgUploadRequestExecutor implements RequestExecutor { + protected RequestHttp requestHttp; + public MediaImgUploadRequestExecutor(RequestHttp requestHttp){ + this.requestHttp =requestHttp; } - @Override - public WxMediaImgUploadResult executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, - File data) throws WxErrorException, IOException { - - if (data == null) { - throw new WxErrorException(WxError.newBuilder().setErrorMsg("文件对象为空").build()); - } - - HttpPost httpPost = new HttpPost(uri); - if (httpProxy != null) { - RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); - httpPost.setConfig(config); - } - - HttpEntity entity = MultipartEntityBuilder - .create() - .addBinaryBody("media", data) - .setMode(HttpMultipartMode.RFC6532) - .build(); - httpPost.setEntity(entity); - httpPost.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.toString()); - - try (CloseableHttpResponse response = httpclient.execute(httpPost)) { - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - WxError error = WxError.fromJson(responseContent); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } - - return WxMediaImgUploadResult.fromJson(responseContent); + public static RequestExecutor create(RequestHttp requestHttp){ + switch (requestHttp.getRequestType()){ + case apacheHttp: + return new ApacheMediaImgUploadRequestExecutor(requestHttp); + case joddHttp: + return new JoddMediaImgUploadRequestExecutor(requestHttp); + case okHttp: + return new OkhttpMediaImgUploadRequestExecutor(requestHttp); + default: + return null; } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/QrCodeRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/QrCodeRequestExecutor.java index d37d0bb9..151a20e4 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/QrCodeRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/QrCodeRequestExecutor.java @@ -9,13 +9,16 @@ import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.fs.FileUtils; -import me.chanjar.weixin.common.util.http.AbstractRequestExecutor; +import me.chanjar.weixin.common.util.http.RequestExecutor; import me.chanjar.weixin.common.util.http.RequestHttp; import me.chanjar.weixin.common.util.http.apache.InputStreamResponseHandler; import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; +import me.chanjar.weixin.mp.util.http.apache.ApacheQrCodeRequestExecutor; +import me.chanjar.weixin.mp.util.http.jodd.JoddQrCodeRequestExecutor; +import me.chanjar.weixin.mp.util.http.okhttp.OkhttpQrCodeRequestExecutor; import okhttp3.*; import org.apache.http.Header; @@ -38,102 +41,25 @@ import java.util.UUID; * * @author chanjarster */ -public class QrCodeRequestExecutor extends AbstractRequestExecutor { +public abstract class QrCodeRequestExecutor implements RequestExecutor { + protected RequestHttp requestHttp; -@Override - public File executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, WxMpQrCodeTicket ticket) 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"); - } - - HttpRequest request = HttpRequest.get(uri); - if (proxyInfo != null) { - provider.useProxy(proxyInfo); - } - request.withConnectionProvider(provider); - - HttpResponse response = request.send(); - String contentTypeHeader = response.header("Content-Type"); - if (MimeTypes.MIME_TEXT_PLAIN.equals(contentTypeHeader)) { - String responseContent = response.bodyText(); - throw new WxErrorException(WxError.fromJson(responseContent)); - } - try (InputStream inputStream = new ByteArrayInputStream(response.bodyBytes())) { - return FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), "jpg"); - } - } - - @Override - public File executeOkhttp(ConnectionPool pool, final OkhttpProxyInfo proxyInfo, String uri, WxMpQrCodeTicket data) throws WxErrorException, IOException { - OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(pool); - //设置代理 - if (proxyInfo != null) { - clientBuilder.proxy(proxyInfo.getProxy()); - } - //设置授权 - clientBuilder.authenticator(new Authenticator() { - @Override - public Request authenticate(Route route, Response response) throws IOException { - String credential = Credentials.basic(proxyInfo.getProxyUsername(), proxyInfo.getProxyPassword()); - return response.request().newBuilder() - .header("Authorization", credential) - .build(); - } - }); - //得到httpClient - OkHttpClient client = clientBuilder.build(); - - Request request = new Request.Builder().url(uri).get().build(); - Response response = client.newCall(request).execute(); - String contentTypeHeader = response.header("Content-Type"); - if (MimeTypes.MIME_TEXT_PLAIN.equals(contentTypeHeader)) { - String responseContent = response.body().string(); - throw new WxErrorException(WxError.fromJson(responseContent)); - } - try (InputStream inputStream = new ByteArrayInputStream(response.body().bytes())) { - return FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), "jpg"); - } + public QrCodeRequestExecutor(RequestHttp requestHttp){ + this.requestHttp =requestHttp; } - @Override - public File executeApache(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, - WxMpQrCodeTicket ticket) 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 (httpProxy != null) { - RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); - httpGet.setConfig(config); - } - - try (CloseableHttpResponse response = httpclient.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(contentTypeHeader[0].getValue())) { - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - throw new WxErrorException(WxError.fromJson(responseContent)); - } - } - return FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), "jpg"); - } finally { - httpGet.releaseConnection(); + public static RequestExecutor create(RequestHttp requestHttp){ + switch (requestHttp.getRequestType()){ + case apacheHttp: + return new ApacheQrCodeRequestExecutor(requestHttp); + case joddHttp: + return new JoddQrCodeRequestExecutor(requestHttp); + case okHttp: + return new OkhttpQrCodeRequestExecutor(requestHttp); + default: + //TODO 需要优化,最好抛出异常 + return null; } } - } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialDeleteRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialDeleteRequestExecutor.java new file mode 100644 index 00000000..5446483f --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialDeleteRequestExecutor.java @@ -0,0 +1,52 @@ +package me.chanjar.weixin.mp.util.http.apache; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +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.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; + +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import me.chanjar.weixin.mp.util.http.MaterialDeleteRequestExecutor; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class ApacheMaterialDeleteRequestExecutor extends MaterialDeleteRequestExecutor { + public ApacheMaterialDeleteRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public Boolean execute(String uri, String materialId) 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)) { + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } else { + return true; + } + } finally { + httpPost.releaseConnection(); + } + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialNewsInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialNewsInfoRequestExecutor.java new file mode 100644 index 00000000..81fb8019 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialNewsInfoRequestExecutor.java @@ -0,0 +1,54 @@ +package me.chanjar.weixin.mp.util.http.apache; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +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.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; + +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import me.chanjar.weixin.mp.bean.material.WxMpMaterialNews; +import me.chanjar.weixin.mp.util.http.MaterialNewsInfoRequestExecutor; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class ApacheMaterialNewsInfoRequestExecutor extends MaterialNewsInfoRequestExecutor { + public ApacheMaterialNewsInfoRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public WxMpMaterialNews execute(String uri, String materialId) 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)) { + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } else { + return WxMpGsonBuilder.create().fromJson(responseContent, WxMpMaterialNews.class); + } + } finally { + httpPost.releaseConnection(); + } + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialUploadRequestExecutor.java new file mode 100644 index 00000000..af6ab10a --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialUploadRequestExecutor.java @@ -0,0 +1,75 @@ +package me.chanjar.weixin.mp.util.http.apache; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Map; + +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.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.impl.client.CloseableHttpClient; + +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.apache.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 me.chanjar.weixin.mp.util.http.MaterialUploadRequestExecutor; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class ApacheMaterialUploadRequestExecutor extends MaterialUploadRequestExecutor { + public ApacheMaterialUploadRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public WxMpMaterialUploadResult execute(String uri, WxMpMaterial material) 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(WxError.newBuilder().setErrorMsg("非法请求,material参数为空").build()); + } + + File file = material.getFile(); + if (file == null || !file.exists()) { + throw new FileNotFoundException(); + } + + MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create(); + multipartEntityBuilder + .addBinaryBody("media", file) + .setMode(HttpMultipartMode.RFC6532); + Map form = material.getForm(); + if (material.getForm() != null) { + multipartEntityBuilder.addTextBody("description", WxGsonBuilder.create().toJson(form)); + } + + httpPost.setEntity(multipartEntityBuilder.build()); + httpPost.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.toString()); + + try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpPost)) { + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } else { + return WxMpMaterialUploadResult.fromJson(responseContent); + } + } finally { + httpPost.releaseConnection(); + } + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialVideoInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialVideoInfoRequestExecutor.java new file mode 100644 index 00000000..1d1e2c57 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialVideoInfoRequestExecutor.java @@ -0,0 +1,53 @@ +package me.chanjar.weixin.mp.util.http.apache; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +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.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; + +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import me.chanjar.weixin.mp.bean.material.WxMpMaterialVideoInfoResult; +import me.chanjar.weixin.mp.util.http.MaterialVideoInfoRequestExecutor; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class ApacheMaterialVideoInfoRequestExecutor extends MaterialVideoInfoRequestExecutor { + public ApacheMaterialVideoInfoRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public WxMpMaterialVideoInfoResult execute(String uri, String materialId) 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)) { + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } else { + return WxMpMaterialVideoInfoResult.fromJson(responseContent); + } + } finally { + httpPost.releaseConnection(); + } + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialVoiceAndImageDownloadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialVoiceAndImageDownloadRequestExecutor.java new file mode 100644 index 00000000..92cf1c5a --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialVoiceAndImageDownloadRequestExecutor.java @@ -0,0 +1,64 @@ +package me.chanjar.weixin.mp.util.http.apache; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.io.IOUtils; +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.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; + +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.apache.InputStreamResponseHandler; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import me.chanjar.weixin.mp.util.http.MaterialVoiceAndImageDownloadRequestExecutor; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class ApacheMaterialVoiceAndImageDownloadRequestExecutor extends MaterialVoiceAndImageDownloadRequestExecutor { + public ApacheMaterialVoiceAndImageDownloadRequestExecutor(RequestHttp requestHttp, File tmpDirFile) { + super(requestHttp, tmpDirFile); + } + + @Override + public InputStream execute(String uri, String materialId) 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, "UTF-8"); + if (responseContentString.length() < 100) { + 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); + } finally { + httpPost.releaseConnection(); + } + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMediaImgUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMediaImgUploadRequestExecutor.java new file mode 100644 index 00000000..4aaf2f12 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMediaImgUploadRequestExecutor.java @@ -0,0 +1,61 @@ +package me.chanjar.weixin.mp.util.http.apache; + +import java.io.File; +import java.io.IOException; + +import org.apache.http.HttpEntity; +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.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.impl.client.CloseableHttpClient; + +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult; +import me.chanjar.weixin.mp.util.http.MediaImgUploadRequestExecutor; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class ApacheMediaImgUploadRequestExecutor extends MediaImgUploadRequestExecutor { + public ApacheMediaImgUploadRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public WxMediaImgUploadResult execute(String uri, File data) throws WxErrorException, IOException { + if (data == null) { + throw new WxErrorException(WxError.newBuilder().setErrorMsg("文件对象为空").build()); + } + + 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.RFC6532) + .build(); + httpPost.setEntity(entity); + httpPost.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.toString()); + + try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpPost)) { + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + WxError error = WxError.fromJson(responseContent); + 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/http/apache/ApacheQrCodeRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheQrCodeRequestExecutor.java new file mode 100644 index 00000000..dd84f293 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheQrCodeRequestExecutor.java @@ -0,0 +1,66 @@ +package me.chanjar.weixin.mp.util.http.apache; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URLEncoder; +import java.util.UUID; + +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 me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.fs.FileUtils; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.apache.InputStreamResponseHandler; +import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; +import me.chanjar.weixin.mp.util.http.QrCodeRequestExecutor; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class ApacheQrCodeRequestExecutor extends QrCodeRequestExecutor { + public ApacheQrCodeRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public File execute(String uri, WxMpQrCodeTicket ticket) 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(contentTypeHeader[0].getValue())) { + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + throw new WxErrorException(WxError.fromJson(responseContent)); + } + } + return FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), "jpg"); + } finally { + httpGet.releaseConnection(); + } + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddMaterialDeleteRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddMaterialDeleteRequestExecutor.java new file mode 100644 index 00000000..082653b2 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddMaterialDeleteRequestExecutor.java @@ -0,0 +1,40 @@ +package me.chanjar.weixin.mp.util.http.jodd; + +import java.io.IOException; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.mp.util.http.MaterialDeleteRequestExecutor; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class JoddMaterialDeleteRequestExecutor extends MaterialDeleteRequestExecutor { + public JoddMaterialDeleteRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public Boolean execute(String uri, String materialId) throws WxErrorException, IOException { + HttpRequest request = HttpRequest.post(uri); + if (requestHttp.getRequestHttpProxy() != null) { + requestHttp.getRequestHttpClient().useProxy(requestHttp.getRequestHttpProxy()); + } + request.withConnectionProvider(requestHttp.getRequestHttpClient()); + + request.query("media_id", materialId); + HttpResponse response = request.send(); + String responseContent = response.bodyText(); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } else { + return true; + } + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddMaterialNewsInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddMaterialNewsInfoRequestExecutor.java new file mode 100644 index 00000000..083cfedc --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddMaterialNewsInfoRequestExecutor.java @@ -0,0 +1,43 @@ +package me.chanjar.weixin.mp.util.http.jodd; + +import java.io.IOException; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.mp.bean.material.WxMpMaterialNews; +import me.chanjar.weixin.mp.util.http.MaterialNewsInfoRequestExecutor; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class JoddMaterialNewsInfoRequestExecutor extends MaterialNewsInfoRequestExecutor { + public JoddMaterialNewsInfoRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public WxMpMaterialNews execute(String uri, String materialId) throws WxErrorException, IOException { + HttpRequest request = HttpRequest.post(uri); + if (requestHttp.getRequestHttpProxy() != null) { + requestHttp.getRequestHttpClient().useProxy(requestHttp.getRequestHttpProxy()); + } + request.withConnectionProvider(requestHttp.getRequestHttpClient()); + + request.query("media_id", materialId); + HttpResponse response = request.send(); + + String responseContent = response.bodyText(); + WxError error = WxError.fromJson(responseContent); + 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/http/jodd/JoddMaterialUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddMaterialUploadRequestExecutor.java new file mode 100644 index 00000000..4c1fe480 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddMaterialUploadRequestExecutor.java @@ -0,0 +1,59 @@ +package me.chanjar.weixin.mp.util.http.jodd; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Map; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestHttp; +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 me.chanjar.weixin.mp.util.http.MaterialUploadRequestExecutor; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class JoddMaterialUploadRequestExecutor extends MaterialUploadRequestExecutor { + public JoddMaterialUploadRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public WxMpMaterialUploadResult execute(String uri, WxMpMaterial material) throws WxErrorException, IOException { + HttpRequest request = HttpRequest.post(uri); + if (requestHttp.getRequestHttpProxy() != null) { + requestHttp.getRequestHttpClient().useProxy(requestHttp.getRequestHttpProxy()); + } + request.withConnectionProvider(requestHttp.getRequestHttpClient()); + + if (material == null) { + throw new WxErrorException(WxError.newBuilder().setErrorMsg("非法请求,material参数为空").build()); + } + + File file = material.getFile(); + if (file == null || !file.exists()) { + throw new FileNotFoundException(); + } + request.form("media", file); + Map form = material.getForm(); + if (material.getForm() != null) { + request.form("description", WxGsonBuilder.create().toJson(form)); + } + + HttpResponse response = request.send(); + String responseContent = response.bodyText(); + WxError error = WxError.fromJson(responseContent); + 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/http/jodd/JoddMaterialVideoInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddMaterialVideoInfoRequestExecutor.java new file mode 100644 index 00000000..ed7bfc04 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddMaterialVideoInfoRequestExecutor.java @@ -0,0 +1,41 @@ +package me.chanjar.weixin.mp.util.http.jodd; + +import java.io.IOException; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.mp.bean.material.WxMpMaterialVideoInfoResult; +import me.chanjar.weixin.mp.util.http.MaterialVideoInfoRequestExecutor; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class JoddMaterialVideoInfoRequestExecutor extends MaterialVideoInfoRequestExecutor { + public JoddMaterialVideoInfoRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public WxMpMaterialVideoInfoResult execute(String uri, String materialId) throws WxErrorException, IOException { + HttpRequest request = HttpRequest.post(uri); + if (requestHttp.getRequestHttpProxy() != null) { + requestHttp.getRequestHttpClient().useProxy(requestHttp.getRequestHttpProxy()); + } + request.withConnectionProvider(requestHttp.getRequestHttpClient()); + + request.query("media_id", materialId); + HttpResponse response = request.send(); + String responseContent = response.bodyText(); + WxError error = WxError.fromJson(responseContent); + 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/http/jodd/JoddMaterialVoiceAndImageDownloadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddMaterialVoiceAndImageDownloadRequestExecutor.java new file mode 100644 index 00000000..b8da949e --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddMaterialVoiceAndImageDownloadRequestExecutor.java @@ -0,0 +1,56 @@ +package me.chanjar.weixin.mp.util.http.jodd; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import me.chanjar.weixin.mp.util.http.MaterialVoiceAndImageDownloadRequestExecutor; +import me.chanjar.weixin.mp.util.http.okhttp.OkhttpMaterialVoiceAndImageDownloadRequestExecutor; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class JoddMaterialVoiceAndImageDownloadRequestExecutor extends MaterialVoiceAndImageDownloadRequestExecutor { + public JoddMaterialVoiceAndImageDownloadRequestExecutor(RequestHttp requestHttp, File tmpDirFile) { + super(requestHttp, tmpDirFile); + } + + @Override + public InputStream execute(String uri, String materialId) throws WxErrorException, IOException { + HttpRequest request = HttpRequest.post(uri); + if (requestHttp.getRequestHttpProxy() != null) { + requestHttp.getRequestHttpClient().useProxy(requestHttp.getRequestHttpProxy()); + } + request.withConnectionProvider(requestHttp.getRequestHttpClient()); + + request.query("media_id", materialId); + HttpResponse response = request.send(); + try (InputStream inputStream = new ByteArrayInputStream(response.bodyBytes())) { + // 下载媒体文件出错 + byte[] responseContent = IOUtils.toByteArray(inputStream); + String responseContentString = new String(responseContent, "UTF-8"); + if (responseContentString.length() < 100) { + 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); + } + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddMediaImgUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddMediaImgUploadRequestExecutor.java new file mode 100644 index 00000000..82bfbf81 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddMediaImgUploadRequestExecutor.java @@ -0,0 +1,46 @@ +package me.chanjar.weixin.mp.util.http.jodd; + +import java.io.File; +import java.io.IOException; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult; +import me.chanjar.weixin.mp.util.http.MediaImgUploadRequestExecutor; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class JoddMediaImgUploadRequestExecutor extends MediaImgUploadRequestExecutor { + public JoddMediaImgUploadRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public WxMediaImgUploadResult execute(String uri, File data) throws WxErrorException, IOException { + if (data == null) { + throw new WxErrorException(WxError.newBuilder().setErrorMsg("文件对象为空").build()); + } + + HttpRequest request = HttpRequest.post(uri); + if (requestHttp.getRequestHttpProxy() != null) { + requestHttp.getRequestHttpClient().useProxy(requestHttp.getRequestHttpProxy()); + } + request.withConnectionProvider(requestHttp.getRequestHttpClient()); + + request.form("media", data); + HttpResponse response = request.send(); + String responseContent = response.bodyText(); + WxError error = WxError.fromJson(responseContent); + 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/http/jodd/JoddQrCodeRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddQrCodeRequestExecutor.java new file mode 100644 index 00000000..1191751c --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/jodd/JoddQrCodeRequestExecutor.java @@ -0,0 +1,57 @@ +package me.chanjar.weixin.mp.util.http.jodd; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URLEncoder; +import java.util.UUID; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import jodd.util.MimeTypes; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.fs.FileUtils; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; +import me.chanjar.weixin.mp.util.http.QrCodeRequestExecutor; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class JoddQrCodeRequestExecutor extends QrCodeRequestExecutor { + public JoddQrCodeRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public File execute(String uri, WxMpQrCodeTicket ticket) 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"); + } + + HttpRequest request = HttpRequest.get(uri); + if (requestHttp.getRequestHttpProxy() != null) { + requestHttp.getRequestHttpClient().useProxy(requestHttp.getRequestHttpProxy()); + } + request.withConnectionProvider(requestHttp.getRequestHttpClient()); + + HttpResponse response = request.send(); + String contentTypeHeader = response.header("Content-Type"); + if (MimeTypes.MIME_TEXT_PLAIN.equals(contentTypeHeader)) { + String responseContent = response.bodyText(); + throw new WxErrorException(WxError.fromJson(responseContent)); + } + try (InputStream inputStream = new ByteArrayInputStream(response.bodyBytes())) { + return FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), "jpg"); + } + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpMaterialDeleteRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpMaterialDeleteRequestExecutor.java new file mode 100644 index 00000000..5da55877 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpMaterialDeleteRequestExecutor.java @@ -0,0 +1,54 @@ +package me.chanjar.weixin.mp.util.http.okhttp; + +import java.io.IOException; + +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; +import me.chanjar.weixin.mp.util.http.MaterialDeleteRequestExecutor; +import okhttp3.*; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class OkhttpMaterialDeleteRequestExecutor extends MaterialDeleteRequestExecutor { + + + public OkhttpMaterialDeleteRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public Boolean execute(String uri, String materialId) throws WxErrorException, IOException { + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(requestHttp.getRequestHttpClient()); + //设置代理 + if (requestHttp.getRequestHttpProxy() != null) { + clientBuilder.proxy(requestHttp.getRequestHttpProxy().getProxy()); + } + //设置授权 + clientBuilder.authenticator(new Authenticator() { + @Override + public Request authenticate(Route route, Response response) throws IOException { + String credential = Credentials.basic(requestHttp.getRequestHttpProxy().getProxyUsername(), requestHttp.getRequestHttpProxy().getProxyPassword()); + return response.request().newBuilder() + .header("Authorization", credential) + .build(); + } + }); + //得到httpClient + OkHttpClient client = clientBuilder.build(); + + RequestBody requestBody = new FormBody.Builder().add("media_id", materialId).build(); + Request request = new Request.Builder().url(uri).post(requestBody).build(); + Response response = client.newCall(request).execute(); + String responseContent = response.body().string(); + WxError error = WxError.fromJson(responseContent); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } else { + return true; + } + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpMaterialNewsInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpMaterialNewsInfoRequestExecutor.java new file mode 100644 index 00000000..c7efbb89 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpMaterialNewsInfoRequestExecutor.java @@ -0,0 +1,55 @@ +package me.chanjar.weixin.mp.util.http.okhttp; + +import java.io.IOException; + +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; +import me.chanjar.weixin.mp.bean.material.WxMpMaterialNews; +import me.chanjar.weixin.mp.util.http.MaterialNewsInfoRequestExecutor; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; +import okhttp3.*; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class OkhttpMaterialNewsInfoRequestExecutor extends MaterialNewsInfoRequestExecutor { + public OkhttpMaterialNewsInfoRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public WxMpMaterialNews execute(String uri, String materialId) throws WxErrorException, IOException { + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(requestHttp.getRequestHttpClient()); + //设置代理 + if (requestHttp.getRequestHttpProxy() != null) { + clientBuilder.proxy(requestHttp.getRequestHttpProxy().getProxy()); + } + //设置授权 + clientBuilder.authenticator(new Authenticator() { + @Override + public Request authenticate(Route route, Response response) throws IOException { + String credential = Credentials.basic(requestHttp.getRequestHttpProxy().getProxyUsername(), requestHttp.getRequestHttpProxy().getProxyPassword()); + return response.request().newBuilder() + .header("Authorization", credential) + .build(); + } + }); + //得到httpClient + OkHttpClient client = clientBuilder.build(); + + RequestBody requestBody = new FormBody.Builder().add("media_id", materialId).build(); + Request request = new Request.Builder().url(uri).post(requestBody).build(); + + Response response = client.newCall(request).execute(); + String responseContent = response.body().string(); + + WxError error = WxError.fromJson(responseContent); + 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/http/okhttp/OkhttpMaterialUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpMaterialUploadRequestExecutor.java new file mode 100644 index 00000000..4be74cda --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpMaterialUploadRequestExecutor.java @@ -0,0 +1,80 @@ +package me.chanjar.weixin.mp.util.http.okhttp; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Map; + +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.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntityBuilder; + +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; +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 me.chanjar.weixin.mp.util.http.MaterialUploadRequestExecutor; +import okhttp3.*; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class OkhttpMaterialUploadRequestExecutor extends MaterialUploadRequestExecutor { + public OkhttpMaterialUploadRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public WxMpMaterialUploadResult execute(String uri, WxMpMaterial material) throws WxErrorException, IOException { + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(requestHttp.getRequestHttpClient()); + //设置代理 + if (requestHttp.getRequestHttpProxy() != null) { + clientBuilder.proxy(requestHttp.getRequestHttpProxy().getProxy()); + } + //设置授权 + clientBuilder.authenticator(new Authenticator() { + @Override + public Request authenticate(Route route, Response response) throws IOException { + String credential = Credentials.basic(requestHttp.getRequestHttpProxy().getProxyUsername(), requestHttp.getRequestHttpProxy().getProxyPassword()); + return response.request().newBuilder() + .header("Authorization", credential) + .build(); + } + }); + //得到httpClient + OkHttpClient client = clientBuilder.build(); + + + if (material == null) { + throw new WxErrorException(WxError.newBuilder().setErrorMsg("非法请求,material参数为空").build()); + } + + File file = material.getFile(); + if (file == null || !file.exists()) { + throw new FileNotFoundException(); + } + RequestBody fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), file); + MultipartBody.Builder bodyBuilder = new MultipartBody.Builder().addFormDataPart("media", null, fileBody); + Map form = material.getForm(); + if (material.getForm() != null) { + bodyBuilder.addFormDataPart("description", WxGsonBuilder.create().toJson(form)); + } + RequestBody body =bodyBuilder.build(); + Request request = new Request.Builder().url(uri).post(body).build(); + Response response = client.newCall(request).execute(); + String responseContent = response.body().string(); + WxError error = WxError.fromJson(responseContent); + 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/http/okhttp/OkhttpMaterialVideoInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpMaterialVideoInfoRequestExecutor.java new file mode 100644 index 00000000..c431d70a --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpMaterialVideoInfoRequestExecutor.java @@ -0,0 +1,52 @@ +package me.chanjar.weixin.mp.util.http.okhttp; + +import java.io.IOException; + +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; +import me.chanjar.weixin.mp.bean.material.WxMpMaterialVideoInfoResult; +import me.chanjar.weixin.mp.util.http.MaterialVideoInfoRequestExecutor; +import okhttp3.*; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class OkhttpMaterialVideoInfoRequestExecutor extends MaterialVideoInfoRequestExecutor { + public OkhttpMaterialVideoInfoRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public WxMpMaterialVideoInfoResult execute(String uri, String materialId) throws WxErrorException, IOException { + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(requestHttp.getRequestHttpClient()); + //设置代理 + if (requestHttp.getRequestHttpProxy() != null) { + clientBuilder.proxy(requestHttp.getRequestHttpProxy().getProxy()); + } + //设置授权 + clientBuilder.authenticator(new Authenticator() { + @Override + public Request authenticate(Route route, Response response) throws IOException { + String credential = Credentials.basic(requestHttp.getRequestHttpProxy().getProxyUsername(), requestHttp.getRequestHttpProxy().getProxyPassword()); + return response.request().newBuilder() + .header("Authorization", credential) + .build(); + } + }); + //得到httpClient + OkHttpClient client = clientBuilder.build(); + + RequestBody requestBody =new FormBody.Builder().add("media_id", materialId).build(); + Request request = new Request.Builder().url(uri).post(requestBody).build(); + Response response = client.newCall(request).execute(); + String responseContent = response.body().string(); + WxError error = WxError.fromJson(responseContent); + 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/http/okhttp/OkhttpMaterialVoiceAndImageDownloadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpMaterialVoiceAndImageDownloadRequestExecutor.java new file mode 100644 index 00000000..3cd1eb98 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpMaterialVoiceAndImageDownloadRequestExecutor.java @@ -0,0 +1,68 @@ +package me.chanjar.weixin.mp.util.http.okhttp; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; + +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import me.chanjar.weixin.mp.util.http.MaterialVoiceAndImageDownloadRequestExecutor; +import okhttp3.*; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class OkhttpMaterialVoiceAndImageDownloadRequestExecutor extends MaterialVoiceAndImageDownloadRequestExecutor { + public OkhttpMaterialVoiceAndImageDownloadRequestExecutor(RequestHttp requestHttp, File tmpDirFile) { + super(requestHttp, tmpDirFile); + } + + @Override + public InputStream execute(String uri, String materialId) throws WxErrorException, IOException { + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(requestHttp.getRequestHttpClient()); + //设置代理 + if (requestHttp.getRequestHttpProxy() != null) { + clientBuilder.proxy(requestHttp.getRequestHttpProxy().getProxy()); + } + //设置授权 + clientBuilder.authenticator(new Authenticator() { + @Override + public Request authenticate(Route route, Response response) throws IOException { + String credential = Credentials.basic(requestHttp.getRequestHttpProxy().getProxyUsername(), requestHttp.getRequestHttpProxy().getProxyPassword()); + return response.request().newBuilder() + .header("Authorization", credential) + .build(); + } + }); + //得到httpClient + OkHttpClient client = clientBuilder.build(); + + RequestBody requestBody = new FormBody.Builder().add("media_id", materialId).build(); + Request request = new Request.Builder().url(uri).get().post(requestBody).build(); + Response response = client.newCall(request).execute(); + + try (InputStream inputStream = new ByteArrayInputStream(response.body().bytes())) { + + // 下载媒体文件出错 + byte[] responseContent = IOUtils.toByteArray(inputStream); + String responseContentString = new String(responseContent, "UTF-8"); + if (responseContentString.length() < 100) { + 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); + } + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpMediaImgUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpMediaImgUploadRequestExecutor.java new file mode 100644 index 00000000..790dd17e --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpMediaImgUploadRequestExecutor.java @@ -0,0 +1,56 @@ +package me.chanjar.weixin.mp.util.http.okhttp; + +import java.io.File; +import java.io.IOException; + +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; +import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult; +import me.chanjar.weixin.mp.util.http.MediaImgUploadRequestExecutor; +import okhttp3.*; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class OkhttpMediaImgUploadRequestExecutor extends MediaImgUploadRequestExecutor { + + public OkhttpMediaImgUploadRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public WxMediaImgUploadResult execute(String uri, File data) throws WxErrorException, IOException { + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(requestHttp.getRequestHttpClient()); + //设置代理 + if (requestHttp.getRequestHttpProxy() != null) { + clientBuilder.proxy(requestHttp.getRequestHttpProxy().getProxy()); + } + //设置授权 + clientBuilder.authenticator(new Authenticator() { + @Override + public Request authenticate(Route route, Response response) throws IOException { + String credential = Credentials.basic(requestHttp.getRequestHttpProxy().getProxyUsername(), requestHttp.getRequestHttpProxy().getProxyPassword()); + return response.request().newBuilder() + .header("Authorization", credential) + .build(); + } + }); + //得到httpClient + OkHttpClient client = clientBuilder.build(); + + RequestBody fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), data); + RequestBody body = new MultipartBody.Builder().addFormDataPart("media", null, fileBody).build(); + Request request = new Request.Builder().url(uri).post(body).build(); + + Response response = client.newCall(request).execute(); + String responseContent = response.body().string(); + WxError error = WxError.fromJson(responseContent); + 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/http/okhttp/OkhttpQrCodeRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpQrCodeRequestExecutor.java new file mode 100644 index 00000000..b2cb372f --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpQrCodeRequestExecutor.java @@ -0,0 +1,58 @@ +package me.chanjar.weixin.mp.util.http.okhttp; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.UUID; + +import jodd.util.MimeTypes; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.fs.FileUtils; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; +import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; +import me.chanjar.weixin.mp.util.http.QrCodeRequestExecutor; +import okhttp3.*; + +/** + * Created by ecoolper on 2017/5/5. + */ +public class OkhttpQrCodeRequestExecutor extends QrCodeRequestExecutor { + public OkhttpQrCodeRequestExecutor(RequestHttp requestHttp) { + super(requestHttp); + } + + @Override + public File execute(String uri, WxMpQrCodeTicket data) throws WxErrorException, IOException { + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(requestHttp.getRequestHttpClient()); + //设置代理 + if (requestHttp.getRequestHttpProxy() != null) { + clientBuilder.proxy(requestHttp.getRequestHttpProxy().getProxy()); + } + //设置授权 + clientBuilder.authenticator(new Authenticator() { + @Override + public Request authenticate(Route route, Response response) throws IOException { + String credential = Credentials.basic(requestHttp.getRequestHttpProxy().getProxyUsername(), requestHttp.getRequestHttpProxy().getProxyPassword()); + return response.request().newBuilder() + .header("Authorization", credential) + .build(); + } + }); + //得到httpClient + OkHttpClient client = clientBuilder.build(); + + Request request = new Request.Builder().url(uri).get().build(); + Response response = client.newCall(request).execute(); + String contentTypeHeader = response.header("Content-Type"); + if (MimeTypes.MIME_TEXT_PLAIN.equals(contentTypeHeader)) { + String responseContent = response.body().string(); + throw new WxErrorException(WxError.fromJson(responseContent)); + } + try (InputStream inputStream = new ByteArrayInputStream(response.body().bytes())) { + return FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), "jpg"); + } + } +} From adcff4ec7af577ff533080f6ede35d575d66a2be Mon Sep 17 00:00:00 2001 From: ecoolper Date: Mon, 8 May 2017 18:35:54 +0800 Subject: [PATCH 25/27] =?UTF-8?q?pom=E6=B7=BBdeveloper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pom.xml b/pom.xml index 5e219eb6..3e915cfc 100644 --- a/pom.xml +++ b/pom.xml @@ -74,6 +74,11 @@ aimilin@yeah.net https://github.com/aimilin6688 + + ecoolper + crskyp@gmail.com + https://github.com/crskyp + From 16dea387f2f9a2941876f9f80c7bba6af8d2187d Mon Sep 17 00:00:00 2001 From: ecoolper Date: Fri, 19 May 2017 23:48:47 +0800 Subject: [PATCH 26/27] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=A4=E4=B8=AA?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MaterialVideoInfoRequestExecutor.java | 44 +++++++++++-------- .../okhttp/OkhttpQrCodeRequestExecutor.java | 3 +- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVideoInfoRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVideoInfoRequestExecutor.java index 4d18379c..49c984dd 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVideoInfoRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVideoInfoRequestExecutor.java @@ -1,25 +1,33 @@ package me.chanjar.weixin.mp.util.http; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.http.RequestHttp; -import me.chanjar.weixin.mp.bean.material.WxMpMaterialVideoInfoResult; -import me.chanjar.weixin.mp.util.http.apache.ApacheMaterialVideoInfoRequestExecutor; -import me.chanjar.weixin.mp.util.http.jodd.JoddMaterialVideoInfoRequestExecutor; -import me.chanjar.weixin.mp.util.http.okhttp.OkhttpMaterialVideoInfoRequestExecutor; + + import me.chanjar.weixin.common.util.http.RequestExecutor; + import me.chanjar.weixin.common.util.http.RequestHttp; + + import me.chanjar.weixin.mp.bean.material.WxMpMaterialVideoInfoResult; + import me.chanjar.weixin.mp.util.http.apache.ApacheMaterialVideoInfoRequestExecutor; + import me.chanjar.weixin.mp.util.http.jodd.JoddMaterialVideoInfoRequestExecutor; + import me.chanjar.weixin.mp.util.http.okhttp.OkhttpMaterialVideoInfoRequestExecutor; + public abstract class MaterialVideoInfoRequestExecutor implements RequestExecutor { protected RequestHttp requestHttp; public MaterialVideoInfoRequestExecutor(RequestHttp requestHttp) { - this.requestHttp = requestHttp; - } - - @Override - public WxMpMaterialVideoInfoResult executeJodd(HttpConnectionProvider provider, ProxyInfo proxyInfo, String uri, String materialId) throws WxErrorException, IOException { - HttpRequest request = HttpRequest.post(uri); - if (proxyInfo != null) { - provider.useProxy(proxyInfo); - } - } - -} + this.requestHttp = requestHttp; + } + + public static RequestExecutor create(RequestHttp requestHttp) { + switch (requestHttp.getRequestType()) { + case apacheHttp: + return new ApacheMaterialVideoInfoRequestExecutor(requestHttp); + case joddHttp: + return new JoddMaterialVideoInfoRequestExecutor(requestHttp); + case okHttp: + return new OkhttpMaterialVideoInfoRequestExecutor(requestHttp); + default: + return null; + } + } + + } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpQrCodeRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpQrCodeRequestExecutor.java index 6bc83cd3..5d75c74d 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpQrCodeRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/okhttp/OkhttpQrCodeRequestExecutor.java @@ -7,6 +7,7 @@ import me.chanjar.weixin.common.util.http.RequestHttp; import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; import me.chanjar.weixin.mp.util.http.QrCodeRequestExecutor; + import okhttp3.*; import java.io.ByteArrayInputStream; @@ -46,7 +47,7 @@ public class OkhttpQrCodeRequestExecutor extends QrCodeRequestExecutor Date: Sat, 3 Jun 2017 23:10:30 +0800 Subject: [PATCH 27/27] =?UTF-8?q?jodd=20response=20=E7=BC=96=E7=A0=81?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E4=B8=BAUTF-8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../http/jodd/JoddMediaDownloadRequestExecutor.java | 4 ++++ .../util/http/jodd/JoddMediaUploadRequestExecutor.java | 4 ++++ .../util/http/jodd/JoddSimpleGetRequestExecutor.java | 10 ++++++---- .../util/http/jodd/JoddSimplePostRequestExecutor.java | 3 +++ .../http/jodd/JoddMaterialDeleteRequestExecutor.java | 3 +++ .../http/jodd/JoddMaterialNewsInfoRequestExecutor.java | 3 +++ .../http/jodd/JoddMaterialUploadRequestExecutor.java | 3 +++ .../jodd/JoddMaterialVideoInfoRequestExecutor.java | 3 +++ ...ddMaterialVoiceAndImageDownloadRequestExecutor.java | 3 +++ .../http/jodd/JoddMediaImgUploadRequestExecutor.java | 3 +++ .../mp/util/http/jodd/JoddQrCodeRequestExecutor.java | 3 +++ 11 files changed, 38 insertions(+), 4 deletions(-) diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddMediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddMediaDownloadRequestExecutor.java index 230b3ca6..a15272bc 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddMediaDownloadRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddMediaDownloadRequestExecutor.java @@ -4,6 +4,8 @@ import jodd.http.HttpConnectionProvider; import jodd.http.HttpRequest; import jodd.http.HttpResponse; import jodd.http.ProxyInfo; +import jodd.util.StringPool; + import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.fs.FileUtils; @@ -44,6 +46,8 @@ public class JoddMediaDownloadRequestExecutor extends MediaDownloadRequestExecut request.withConnectionProvider(requestHttp.getRequestHttpClient()); HttpResponse response = request.send(); + response.charset(StringPool.UTF_8); + String contentType = response.header("Content-Type"); if (contentType != null && contentType.startsWith("application/json")) { // application/json; encoding=utf-8 下载媒体文件出错 diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddMediaUploadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddMediaUploadRequestExecutor.java index 43f17fbc..8466eead 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddMediaUploadRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/jodd/JoddMediaUploadRequestExecutor.java @@ -4,6 +4,8 @@ import jodd.http.HttpConnectionProvider; import jodd.http.HttpRequest; import jodd.http.HttpResponse; import jodd.http.ProxyInfo; +import jodd.util.StringPool; + import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.exception.WxErrorException; @@ -30,6 +32,8 @@ public class JoddMediaUploadRequestExecutor extends MediaUploadRequestExecutor