();
+ protected CloseableHttpClient httpClient;
+
+ protected HttpHost httpProxy;
+
public boolean checkSignature(String msgSignature, String timestamp, String nonce, String data) {
try {
return SHA1.gen(wxCpConfigStorage.getToken(), timestamp, nonce, data).equals(msgSignature);
@@ -78,6 +86,11 @@ public class WxCpServiceImpl implements WxCpService {
+ "&corpsecret=" + wxCpConfigStorage.getCorpSecret();
try {
HttpGet httpGet = new HttpGet(url);
+ if (httpProxy != null) {
+ RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build();
+ httpGet.setConfig(config);
+ }
+ CloseableHttpClient httpclient = getHttpclient();
CloseableHttpResponse response = httpclient.execute(httpGet);
String resultContent = new BasicResponseHandler().handleResponse(response);
WxError error = WxError.fromJson(resultContent);
@@ -308,6 +321,14 @@ public class WxCpServiceImpl implements WxCpService {
execute(new SimplePostRequestExecutor(), url, jsonObject.toString());
}
+ public String get(String url, String queryParam) throws WxErrorException {
+ return execute(new SimpleGetRequestExecutor(), url, queryParam);
+ }
+
+ public String post(String url, String postData) throws WxErrorException {
+ return execute(new SimplePostRequestExecutor(), url, postData);
+ }
+
/**
* 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求
*
@@ -327,7 +348,7 @@ public class WxCpServiceImpl implements WxCpService {
uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken;
try {
- return executor.execute(uriWithAccessToken, data);
+ return executor.execute(getHttpclient(), httpProxy, uriWithAccessToken, data);
} catch (WxErrorException e) {
WxError error = e.getError();
/*
@@ -371,8 +392,38 @@ public class WxCpServiceImpl implements WxCpService {
}
}
+ protected CloseableHttpClient getHttpclient() {
+ return httpClient;
+ }
+
public void setWxCpConfigStorage(WxCpConfigStorage wxConfigProvider) {
this.wxCpConfigStorage = wxConfigProvider;
+
+ String http_proxy_host = wxCpConfigStorage.getHttp_proxy_host();
+ int http_proxy_port = wxCpConfigStorage.getHttp_proxy_port();
+ String http_proxy_username = wxCpConfigStorage.getHttp_proxy_username();
+ String http_proxy_password = wxCpConfigStorage.getHttp_proxy_password();
+
+ if(StringUtils.isNotBlank(http_proxy_host)) {
+ // 使用代理服务器
+ if(StringUtils.isNotBlank(http_proxy_username)) {
+ // 需要用户认证的代理服务器
+ CredentialsProvider credsProvider = new BasicCredentialsProvider();
+ credsProvider.setCredentials(
+ new AuthScope(http_proxy_host, http_proxy_port),
+ new UsernamePasswordCredentials(http_proxy_username, http_proxy_password));
+ httpClient = HttpClients
+ .custom()
+ .setDefaultCredentialsProvider(credsProvider)
+ .build();
+ } else {
+ // 无需用户认证的代理服务器
+ httpClient = HttpClients.createDefault();
+ }
+ httpProxy = new HttpHost(http_proxy_host, http_proxy_port);
+ } else {
+ httpClient = HttpClients.createDefault();
+ }
}
}
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 7c47ee2f..f04b1fd4 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.common.api.WxConsts;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
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/WxCpMessageAPITest.java
index 08966280..1672faaa 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/WxCpMessageAPITest.java
@@ -1,5 +1,6 @@
package me.chanjar.weixin.cp.api;
+import me.chanjar.weixin.common.api.WxConsts;
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/api/WxCpMessageRouterTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMessageRouterTest.java
index 7542a951..59962c6f 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMessageRouterTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMessageRouterTest.java
@@ -2,6 +2,7 @@ package me.chanjar.weixin.cp.api;
import java.util.Map;
+import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.cp.bean.WxCpXmlMessage;
import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage;
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 7ed9caa8..c00d73e2 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
@@ -2,6 +2,7 @@ package me.chanjar.weixin.cp.api;
import javax.xml.bind.JAXBException;
+import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.WxMenu;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
diff --git a/weixin-java-mp/pom.xml b/weixin-java-mp/pom.xml
index 570540f3..940e79f3 100644
--- a/weixin-java-mp/pom.xml
+++ b/weixin-java-mp/pom.xml
@@ -6,7 +6,7 @@
me.chanjar
weixin-java-parent
- 1.0.3
+ 1.0.4
weixin-java-mp
WeiXin Java Tools - MP
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 e90013ff..e7ee779c 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
@@ -25,4 +25,12 @@ public interface WxMpConfigStorage {
public int getExpiresIn();
+ public String getHttp_proxy_host();
+
+ public int getHttp_proxy_port();
+
+ public String getHttp_proxy_username();
+
+ public String getHttp_proxy_password();
+
}
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 0218067b..d0f9c33d 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
@@ -16,6 +16,11 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
protected String aesKey;
protected int expiresIn;
+ protected String http_proxy_host;
+ protected int http_proxy_port;
+ protected String http_proxy_username;
+ protected String http_proxy_password;
+
public void updateAccessToken(WxAccessToken accessToken) {
updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
}
@@ -73,5 +78,52 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
this.expiresIn = expiresIn;
}
+ public String getHttp_proxy_host() {
+ return http_proxy_host;
+ }
+
+ public void setHttp_proxy_host(String http_proxy_host) {
+ this.http_proxy_host = http_proxy_host;
+ }
+
+ public int getHttp_proxy_port() {
+ return http_proxy_port;
+ }
+
+ public void setHttp_proxy_port(int http_proxy_port) {
+ this.http_proxy_port = http_proxy_port;
+ }
+
+ public String getHttp_proxy_username() {
+ return http_proxy_username;
+ }
+
+ public void setHttp_proxy_username(String http_proxy_username) {
+ this.http_proxy_username = http_proxy_username;
+ }
+
+ public String getHttp_proxy_password() {
+ return http_proxy_password;
+ }
+
+ public void setHttp_proxy_password(String http_proxy_password) {
+ this.http_proxy_password = http_proxy_password;
+ }
+
+ @Override
+ public String toString() {
+ return "WxMpInMemoryConfigStorage{" +
+ "appId='" + appId + '\'' +
+ ", secret='" + secret + '\'' +
+ ", token='" + token + '\'' +
+ ", accessToken='" + accessToken + '\'' +
+ ", aesKey='" + aesKey + '\'' +
+ ", expiresIn=" + expiresIn +
+ ", http_proxy_host='" + http_proxy_host + '\'' +
+ ", http_proxy_port=" + http_proxy_port +
+ ", http_proxy_username='" + http_proxy_username + '\'' +
+ ", http_proxy_password='" + http_proxy_password + '\'' +
+ '}';
+ }
}
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 4b3a20fc..daaa062f 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,6 +2,7 @@ package me.chanjar.weixin.mp.api;
import me.chanjar.weixin.common.bean.WxMenu;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
+import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.mp.bean.*;
import me.chanjar.weixin.mp.bean.result.*;
import me.chanjar.weixin.common.exception.WxErrorException;
@@ -306,10 +307,65 @@ public interface WxMpService {
* @throws WxErrorException
*/
public String shortUrl(String long_url) throws WxErrorException;
-
+
+ /**
+ *
+ * 发送模板消息
+ * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=模板消息接口
+ *
+ * @param templateMessage
+ * @throws WxErrorException
+ */
+ public void templateSend(WxMpTemplateMessage templateMessage) throws WxErrorException;
+
+ /**
+ *
+ * 语义查询接口
+ * 详情请见:http://mp.weixin.qq.com/wiki/index.php?title=语义理解
+ *
+ * @param semanticQuery
+ * @return
+ * @throws WxErrorException
+ */
+ WxMpSemanticQueryResult semanticQuery(WxMpSemanticQuery semanticQuery) throws WxErrorException;
+
/**
- * 注入 {@link WxMpConfigStorage} 的实现
- * @param wxConfigProvider
+ * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的GET请求
+ * @param url
+ * @param queryParam
+ * @return
+ * @throws WxErrorException
+ */
+ String get(String url, String queryParam) throws WxErrorException;
+
+ /**
+ * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的POST请求
+ * @param url
+ * @param postData
+ * @return
+ * @throws WxErrorException
*/
+ String post(String url, String postData) throws WxErrorException;
+
+ /**
+ *
+ * Service没有实现某个API的时候,可以用这个,
+ * 比{@link #get}和{@link #post}方法更灵活,可以自己构造RequestExecutor用来处理不同的参数和不同的返回类型。
+ * 可以参考,{@link me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor}的实现方法
+ *
+ * @param executor
+ * @param uri
+ * @param data
+ * @param
+ * @param
+ * @return
+ * @throws WxErrorException
+ */
+ public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException;
+
+ /**
+ * 注入 {@link WxMpConfigStorage} 的实现
+ * @param wxConfigProvider
+ */
public void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider);
}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java
index c40af33d..a4b4cc37 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java
@@ -19,9 +19,16 @@ import me.chanjar.weixin.mp.bean.result.*;
import me.chanjar.weixin.mp.util.http.QrCodeRequestExecutor;
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
import org.apache.commons.lang3.StringUtils;
+import org.apache.http.HttpHost;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.CredentialsProvider;
+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.client.methods.HttpPost;
+import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
@@ -31,6 +38,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.List;
+import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -43,12 +51,14 @@ public class WxMpServiceImpl implements WxMpService {
*/
protected static final AtomicBoolean GLOBAL_ACCESS_TOKEN_REFRESH_FLAG = new AtomicBoolean(false);
- protected static final CloseableHttpClient httpclient = HttpClients.createDefault();
-
protected WxMpConfigStorage wxMpConfigStorage;
protected final ThreadLocal retryTimes = new ThreadLocal();
+ protected CloseableHttpClient httpClient;
+
+ protected HttpHost httpProxy;
+
public boolean checkSignature(String timestamp, String nonce, String signature) {
try {
return SHA1.gen(wxMpConfigStorage.getToken(), timestamp, nonce).equals(signature);
@@ -66,6 +76,11 @@ public class WxMpServiceImpl implements WxMpService {
;
try {
HttpGet httpGet = new HttpGet(url);
+ if (httpProxy != null) {
+ RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build();
+ httpGet.setConfig(config);
+ }
+ CloseableHttpClient httpclient = getHttpclient();
CloseableHttpResponse response = httpclient.execute(httpGet);
String resultContent = new BasicResponseHandler().handleResponse(response);
WxError error = WxError.fromJson(resultContent);
@@ -272,8 +287,27 @@ public class WxMpServiceImpl implements WxMpService {
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
return tmpJsonElement.getAsJsonObject().get("short_url").getAsString();
}
-
- /**
+
+ public void templateSend(WxMpTemplateMessage templateMessage) throws WxErrorException {
+ String url = "https://api.weixin.qq.com/cgi-bin/message/template/send";
+ execute(new SimplePostRequestExecutor(), url, templateMessage.toJson());
+ }
+
+ public WxMpSemanticQueryResult semanticQuery(WxMpSemanticQuery semanticQuery) throws WxErrorException {
+ String url = "https://api.weixin.qq.com/semantic/semproxy/search";
+ String responseContent = execute(new SimplePostRequestExecutor(), url, semanticQuery.toJson());
+ return WxMpSemanticQueryResult.fromJson(responseContent);
+ }
+
+ public String get(String url, String queryParam) throws WxErrorException {
+ return execute(new SimpleGetRequestExecutor(), url, queryParam);
+ }
+
+ public String post(String url, String postData) throws WxErrorException {
+ return execute(new SimplePostRequestExecutor(), url, postData);
+ }
+
+ /**
* 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求
* @param executor
* @param uri
@@ -291,7 +325,7 @@ public class WxMpServiceImpl implements WxMpService {
uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken;
try {
- return executor.execute(uriWithAccessToken, data);
+ return executor.execute(getHttpclient(), httpProxy, uriWithAccessToken, data);
} catch (WxErrorException e) {
WxError error = e.getError();
/*
@@ -334,9 +368,39 @@ public class WxMpServiceImpl implements WxMpService {
throw new RuntimeException(e);
}
}
-
+
+ protected CloseableHttpClient getHttpclient() {
+ return httpClient;
+ }
+
public void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider) {
this.wxMpConfigStorage = wxConfigProvider;
+
+ String http_proxy_host = wxMpConfigStorage.getHttp_proxy_host();
+ int http_proxy_port = wxMpConfigStorage.getHttp_proxy_port();
+ String http_proxy_username = wxMpConfigStorage.getHttp_proxy_username();
+ String http_proxy_password = wxMpConfigStorage.getHttp_proxy_password();
+
+ if(StringUtils.isNotBlank(http_proxy_host)) {
+ // 使用代理服务器
+ if(StringUtils.isNotBlank(http_proxy_username)) {
+ // 需要用户认证的代理服务器
+ CredentialsProvider credsProvider = new BasicCredentialsProvider();
+ credsProvider.setCredentials(
+ new AuthScope(http_proxy_host, http_proxy_port),
+ new UsernamePasswordCredentials(http_proxy_username, http_proxy_password));
+ httpClient = HttpClients
+ .custom()
+ .setDefaultCredentialsProvider(credsProvider)
+ .build();
+ } else {
+ // 无需用户认证的代理服务器
+ httpClient = HttpClients.createDefault();
+ }
+ httpProxy = new HttpHost(http_proxy_host, http_proxy_port);
+ } else {
+ httpClient = HttpClients.createDefault();
+ }
}
}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpSemanticQuery.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpSemanticQuery.java
new file mode 100644
index 00000000..aac3bd10
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpSemanticQuery.java
@@ -0,0 +1,91 @@
+package me.chanjar.weixin.mp.bean;
+
+import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
+
+/**
+ * 语义理解查询用对象
+ *
+ * http://mp.weixin.qq.com/wiki/index.php?title=语义理解
+ *
+ * @author Daniel Qian
+ */
+public class WxMpSemanticQuery {
+
+ private String query;
+ private String category;
+ private Float latitude;
+ private Float longitude;
+ private String city;
+ private String region;
+ private String appid;
+ private String uid;
+
+ public String getQuery() {
+ return query;
+ }
+
+ public void setQuery(String query) {
+ this.query = query;
+ }
+
+ public String getCategory() {
+ return category;
+ }
+
+ public void setCategory(String category) {
+ this.category = category;
+ }
+
+ public Float getLatitude() {
+ return latitude;
+ }
+
+ public void setLatitude(Float latitude) {
+ this.latitude = latitude;
+ }
+
+ public Float getLongitude() {
+ return longitude;
+ }
+
+ public void setLongitude(Float longitude) {
+ this.longitude = longitude;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getRegion() {
+ return region;
+ }
+
+ public void setRegion(String region) {
+ this.region = region;
+ }
+
+ public String getAppid() {
+ return appid;
+ }
+
+ public void setAppid(String appid) {
+ this.appid = appid;
+ }
+
+ public String getUid() {
+ return uid;
+ }
+
+ public void setUid(String uid) {
+ this.uid = uid;
+ }
+
+ public String toJson() {
+ return WxMpGsonBuilder.create().toJson(this);
+ }
+
+}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpTemplateData.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpTemplateData.java
new file mode 100644
index 00000000..e328fe85
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpTemplateData.java
@@ -0,0 +1,49 @@
+package me.chanjar.weixin.mp.bean;
+
+/**
+ * @author Daniel Qian
+ */
+public class WxMpTemplateData {
+
+ private String name;
+ private String value;
+ private String color;
+
+ public WxMpTemplateData() {
+ }
+
+ public WxMpTemplateData(String name, String value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ public WxMpTemplateData(String name, String value, String color) {
+ this.name = name;
+ this.value = value;
+ this.color = color;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public String getColor() {
+ return color;
+ }
+ public void setColor(String color) {
+ this.color = color;
+ }
+
+}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpTemplateMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpTemplateMessage.java
new file mode 100644
index 00000000..cd6ac5f7
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpTemplateMessage.java
@@ -0,0 +1,62 @@
+package me.chanjar.weixin.mp.bean;
+
+import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by qianjia on 14/11/1.
+ */
+public class WxMpTemplateMessage {
+
+ private String toUser;
+ private String templateId;
+ private String url;
+ private String topColor;
+ private List datas = new ArrayList();
+
+ public String getToUser() {
+ return toUser;
+ }
+
+ public void setToUser(String toUser) {
+ this.toUser = toUser;
+ }
+
+ public String getTemplateId() {
+ return templateId;
+ }
+
+ public void setTemplateId(String templateId) {
+ this.templateId = templateId;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public String getTopColor() {
+ return topColor;
+ }
+
+ public void setTopColor(String topColor) {
+ this.topColor = topColor;
+ }
+
+ public List getDatas() {
+ return datas;
+ }
+
+ public void setDatas(List datas) {
+ this.datas = datas;
+ }
+
+ public String toJson() {
+ return WxMpGsonBuilder.INSTANCE.create().toJson(this);
+ }
+}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpSemanticQueryResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpSemanticQueryResult.java
new file mode 100644
index 00000000..a0972c35
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpSemanticQueryResult.java
@@ -0,0 +1,73 @@
+package me.chanjar.weixin.mp.bean.result;
+
+import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
+
+/**
+ * 语义理解查询结果对象
+ *
+ * http://mp.weixin.qq.com/wiki/index.php?title=语义理解
+ *
+ * @author Daniel Qian
+ */
+public class WxMpSemanticQueryResult {
+
+ private String query;
+ private String type;
+ private String semantic;
+ private String result;
+ private String answer;
+ private String text;
+
+ public String getQuery() {
+ return query;
+ }
+
+ public void setQuery(String query) {
+ this.query = query;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getSemantic() {
+ return semantic;
+ }
+
+ public void setSemantic(String semantic) {
+ this.semantic = semantic;
+ }
+
+ public String getResult() {
+ return result;
+ }
+
+ public void setResult(String result) {
+ this.result = result;
+ }
+
+ public String getAnswer() {
+ return answer;
+ }
+
+ public void setAnswer(String answer) {
+ this.answer = answer;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ public static WxMpSemanticQueryResult fromJson(String json) {
+ return WxMpGsonBuilder.create().fromJson(json, WxMpSemanticQueryResult.class);
+ }
+
+}
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 554c9b8f..593bdb05 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
@@ -8,10 +8,13 @@ import me.chanjar.weixin.common.util.http.Utf8ResponseHandler;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import me.chanjar.weixin.common.exception.WxErrorException;
import org.apache.http.Header;
+import org.apache.http.HttpHost;
import org.apache.http.client.ClientProtocolException;
+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;
@@ -27,7 +30,7 @@ import java.util.UUID;
public class QrCodeRequestExecutor implements RequestExecutor {
@Override
- public File execute(String uri, WxMpQrCodeTicket ticket) throws WxErrorException, ClientProtocolException, IOException {
+ public File execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, WxMpQrCodeTicket ticket) throws WxErrorException, ClientProtocolException, IOException {
if (ticket != null) {
if (uri.indexOf('?') == -1) {
uri += '?';
@@ -39,6 +42,11 @@ public class QrCodeRequestExecutor implements RequestExecutor {
+
+ public WxMpSemanticQueryResult deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
+ WxMpSemanticQueryResult result = new WxMpSemanticQueryResult();
+ JsonObject resultJsonObject = json.getAsJsonObject();
+
+ if (GsonHelper.getString(resultJsonObject, "query") != null) {
+ result.setQuery(GsonHelper.getString(resultJsonObject, "query"));
+ }
+ if (GsonHelper.getString(resultJsonObject, "type") != null) {
+ result.setType(GsonHelper.getString(resultJsonObject, "type"));
+ }
+ if (resultJsonObject.get("semantic") != null) {
+ result.setSemantic(resultJsonObject.get("semantic").toString());
+ }
+ if (resultJsonObject.get("result") != null) {
+ result.setResult(resultJsonObject.get("result").toString());
+ }
+ if (GsonHelper.getString(resultJsonObject, "answer") != null) {
+ result.setAnswer(GsonHelper.getString(resultJsonObject, "answer"));
+ }
+ if (GsonHelper.getString(resultJsonObject, "text") != null) {
+ result.setText(GsonHelper.getString(resultJsonObject, "text"));
+ }
+ return result;
+ }
+
+}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpTemplateMessageGsonAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpTemplateMessageGsonAdapter.java
new file mode 100644
index 00000000..ad603d3b
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpTemplateMessageGsonAdapter.java
@@ -0,0 +1,50 @@
+/*
+ * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved.
+ *
+ * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended
+ * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction
+ * arose from modification of the original source, or other redistribution of this source
+ * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD.
+ */
+package me.chanjar.weixin.mp.util.json;
+
+import com.google.gson.*;
+import me.chanjar.weixin.common.api.WxConsts;
+import me.chanjar.weixin.mp.bean.WxMpCustomMessage;
+import me.chanjar.weixin.mp.bean.WxMpTemplateData;
+import me.chanjar.weixin.mp.bean.WxMpTemplateMessage;
+
+import java.lang.reflect.Type;
+
+/**
+ * @author qianjia
+ */
+public class WxMpTemplateMessageGsonAdapter implements JsonSerializer {
+
+ public JsonElement serialize(WxMpTemplateMessage message, Type typeOfSrc, JsonSerializationContext context) {
+ JsonObject messageJson = new JsonObject();
+ messageJson.addProperty("touser", message.getToUser());
+ messageJson.addProperty("template_id", message.getTemplateId());
+ if (message.getUrl() != null) {
+ messageJson.addProperty("url", message.getUrl());
+ }
+ if (message.getTopColor() != null) {
+ messageJson.addProperty("topcolor", message.getTopColor());
+ }
+
+ JsonObject datas = new JsonObject();
+ messageJson.add("data", datas);
+
+ for (WxMpTemplateData data : message.getDatas()) {
+ JsonObject dataJson = new JsonObject();
+ dataJson.addProperty("value", data.getValue());
+ if (data.getColor() != null) {
+ dataJson.addProperty("color", data.getColor());
+ }
+ datas.add(data.getName(), dataJson);
+ }
+
+ return messageJson;
+ }
+
+}