@@ -5,6 +5,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringReader;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Date;
import java.util.Date;
import java.util.HashMap;
import java.util.HashMap;
import java.util.List;
import java.util.List;
@@ -14,8 +15,10 @@ import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeMap;
import java.util.UUID;
import java.util.UUID;
import com.google.gson.JsonPrimitive;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.bean.WxCardApiSignature;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.bean.WxMenu;
import me.chanjar.weixin.common.bean.WxMenu;
import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.bean.result.WxError;
@@ -28,13 +31,7 @@ import me.chanjar.weixin.common.util.StringUtils;
import me.chanjar.weixin.common.util.crypto.SHA1;
import me.chanjar.weixin.common.util.crypto.SHA1;
import me.chanjar.weixin.common.util.crypto.WxCryptUtil;
import me.chanjar.weixin.common.util.crypto.WxCryptUtil;
import me.chanjar.weixin.common.util.fs.FileUtils;
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.RequestExecutor;
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
import me.chanjar.weixin.common.util.http.URIUtil;
import me.chanjar.weixin.common.util.http.Utf8ResponseHandler;
import me.chanjar.weixin.common.util.http.*;
import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
@@ -49,6 +46,7 @@ import me.chanjar.weixin.mp.bean.WxMpMaterialArticleUpdate;
import me.chanjar.weixin.mp.bean.WxMpMaterialNews;
import me.chanjar.weixin.mp.bean.WxMpMaterialNews;
import me.chanjar.weixin.mp.bean.WxMpSemanticQuery;
import me.chanjar.weixin.mp.bean.WxMpSemanticQuery;
import me.chanjar.weixin.mp.bean.WxMpTemplateMessage;
import me.chanjar.weixin.mp.bean.WxMpTemplateMessage;
import me.chanjar.weixin.mp.bean.result.WxMpCardResult;
import me.chanjar.weixin.mp.bean.result.WxMpMassSendResult;
import me.chanjar.weixin.mp.bean.result.WxMpMassSendResult;
import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult;
import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult;
import me.chanjar.weixin.mp.bean.result.WxMpMaterialCountResult;
import me.chanjar.weixin.mp.bean.result.WxMpMaterialCountResult;
@@ -58,6 +56,7 @@ import me.chanjar.weixin.mp.bean.result.WxMpMaterialUploadResult;
import me.chanjar.weixin.mp.bean.result.WxMpMaterialVideoInfoResult;
import me.chanjar.weixin.mp.bean.result.WxMpMaterialVideoInfoResult;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpPayCallback;
import me.chanjar.weixin.mp.bean.result.WxMpPayCallback;
import me.chanjar.weixin.mp.bean.result.WxMpPayRefundResult;
import me.chanjar.weixin.mp.bean.result.WxMpPayResult;
import me.chanjar.weixin.mp.bean.result.WxMpPayResult;
import me.chanjar.weixin.mp.bean.result.WxMpPrepayIdResult;
import me.chanjar.weixin.mp.bean.result.WxMpPrepayIdResult;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
@@ -99,6 +98,7 @@ import org.slf4j.helpers.MessageFormatter;
import com.google.gson.JsonArray;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.internal.Streams;
import com.google.gson.internal.Streams;
import com.google.gson.reflect.TypeToken;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonReader;
@@ -118,6 +118,11 @@ public class WxMpServiceImpl implements WxMpService {
*/
*/
protected final Object globalJsapiTicketRefreshLock = new Object();
protected final Object globalJsapiTicketRefreshLock = new Object();
/**
* 全局的是否正在刷新卡券api_ticket的锁
*/
protected final Object globalCardApiTicketRefreshLock = new Object();
protected WxMpConfigStorage wxMpConfigStorage;
protected WxMpConfigStorage wxMpConfigStorage;
protected CloseableHttpClient httpClient;
protected CloseableHttpClient httpClient;
@@ -158,14 +163,15 @@ public class WxMpServiceImpl implements WxMpService {
RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build();
RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build();
httpGet.setConfig(config);
httpGet.setConfig(config);
}
}
CloseableHttpResponse response = getHttpclient().execute(httpGet);
String resultContent = new BasicResponseHandler().handleResponse(response);
WxError error = WxError.fromJson(resultContent);
if (error.getErrorCode() != 0) {
throw new WxErrorException(error);
try (CloseableHttpResponse response = getHttpclient().execute(httpGet)) {
String resultContent = new BasicResponseHandler().handleResponse(response);
WxError error = WxError.fromJson(resultContent);
if (error.getErrorCode() != 0) {
throw new WxErrorException(error);
}
WxAccessToken accessToken = WxAccessToken.fromJson(resultContent);
wxMpConfigStorage.updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
}
}
WxAccessToken accessToken = WxAccessToken.fromJson(resultContent);
wxMpConfigStorage.updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
} catch (ClientProtocolException e) {
} catch (ClientProtocolException e) {
throw new RuntimeException(e);
throw new RuntimeException(e);
} catch (IOException e) {
} catch (IOException e) {
@@ -189,7 +195,7 @@ public class WxMpServiceImpl implements WxMpService {
synchronized (globalJsapiTicketRefreshLock) {
synchronized (globalJsapiTicketRefreshLock) {
if (wxMpConfigStorage.isJsapiTicketExpired()) {
if (wxMpConfigStorage.isJsapiTicketExpired()) {
String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi";
String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi";
String responseContent = execute(new Simple GetRequestExecutor(), url, null);
String responseContent = execute(new Jodd GetRequestExecutor(), url, null);
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject();
JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject();
String jsapiTicket = tmpJsonObject.get("ticket").getAsString();
String jsapiTicket = tmpJsonObject.get("ticket").getAsString();
@@ -226,33 +232,33 @@ public class WxMpServiceImpl implements WxMpService {
public void customMessageSend(WxMpCustomMessage message) throws WxErrorException {
public void customMessageSend(WxMpCustomMessage message) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send";
String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send";
execute(new Simple PostRequestExecutor(), url, message.toJson());
execute(new Jodd PostRequestExecutor(), url, message.toJson());
}
}
public void menuCreate(WxMenu menu) throws WxErrorException {
public void menuCreate(WxMenu menu) throws WxErrorException {
if (menu.getMatchRule() != null) {
if (menu.getMatchRule() != null) {
String url = "https://api.weixin.qq.com/cgi-bin/menu/addconditional";
String url = "https://api.weixin.qq.com/cgi-bin/menu/addconditional";
execute(new Simple PostRequestExecutor(), url, menu.toJson());
execute(new Jodd PostRequestExecutor(), url, menu.toJson());
} else {
} else {
String url = "https://api.weixin.qq.com/cgi-bin/menu/create";
String url = "https://api.weixin.qq.com/cgi-bin/menu/create";
execute(new Simple PostRequestExecutor(), url, menu.toJson());
execute(new Jodd PostRequestExecutor(), url, menu.toJson());
}
}
}
}
public void menuDelete() throws WxErrorException {
public void menuDelete() throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/menu/delete";
String url = "https://api.weixin.qq.com/cgi-bin/menu/delete";
execute(new Simple GetRequestExecutor(), url, null);
execute(new Jodd GetRequestExecutor(), url, null);
}
}
public void menuDelete(String menuid) throws WxErrorException {
public void menuDelete(String menuid) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/menu/delconditional";
String url = "https://api.weixin.qq.com/cgi-bin/menu/delconditional";
execute(new Simple GetRequestExecutor(), url, "menuid=" + menuid);
execute(new Jodd GetRequestExecutor(), url, "menuid=" + menuid);
}
}
public WxMenu menuGet() throws WxErrorException {
public WxMenu menuGet() throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/menu/get";
String url = "https://api.weixin.qq.com/cgi-bin/menu/get";
try {
try {
String resultContent = execute(new Simple GetRequestExecutor(), url, null);
String resultContent = execute(new Jodd GetRequestExecutor(), url, null);
return WxMenu.fromJson(resultContent);
return WxMenu.fromJson(resultContent);
} catch (WxErrorException e) {
} catch (WxErrorException e) {
// 46003 不存在的菜单数据
// 46003 不存在的菜单数据
@@ -266,7 +272,7 @@ public class WxMpServiceImpl implements WxMpService {
public WxMenu menuTryMatch(String userid) throws WxErrorException {
public WxMenu menuTryMatch(String userid) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/menu/trymatch";
String url = "https://api.weixin.qq.com/cgi-bin/menu/trymatch";
try {
try {
String resultContent = execute(new Simple GetRequestExecutor(), url, "user_id=" + userid);
String resultContent = execute(new Jodd GetRequestExecutor(), url, "user_id=" + userid);
return WxMenu.fromJson(resultContent);
return WxMenu.fromJson(resultContent);
} catch (WxErrorException e) {
} catch (WxErrorException e) {
// 46003 不存在的菜单数据 46002 不存在的菜单版本
// 46003 不存在的菜单数据 46002 不存在的菜单版本
@@ -379,25 +385,25 @@ public class WxMpServiceImpl implements WxMpService {
public WxMpMassUploadResult massNewsUpload(WxMpMassNews news) throws WxErrorException {
public WxMpMassUploadResult massNewsUpload(WxMpMassNews news) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/media/uploadnews";
String url = "https://api.weixin.qq.com/cgi-bin/media/uploadnews";
String responseContent = execute(new Simple PostRequestExecutor(), url, news.toJson());
String responseContent = execute(new Jodd PostRequestExecutor(), url, news.toJson());
return WxMpMassUploadResult.fromJson(responseContent);
return WxMpMassUploadResult.fromJson(responseContent);
}
}
public WxMpMassUploadResult massVideoUpload(WxMpMassVideo video) throws WxErrorException {
public WxMpMassUploadResult massVideoUpload(WxMpMassVideo video) throws WxErrorException {
String url = "http://file.api.weixin.qq.com/cgi-bin/media/uploadvideo";
String url = "http://file.api.weixin.qq.com/cgi-bin/media/uploadvideo";
String responseContent = execute(new Simple PostRequestExecutor(), url, video.toJson());
String responseContent = execute(new Jodd PostRequestExecutor(), url, video.toJson());
return WxMpMassUploadResult.fromJson(responseContent);
return WxMpMassUploadResult.fromJson(responseContent);
}
}
public WxMpMassSendResult massGroupMessageSend(WxMpMassGroupMessage message) throws WxErrorException {
public WxMpMassSendResult massGroupMessageSend(WxMpMassGroupMessage message) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall";
String url = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall";
String responseContent = execute(new Simple PostRequestExecutor(), url, message.toJson());
String responseContent = execute(new Jodd PostRequestExecutor(), url, message.toJson());
return WxMpMassSendResult.fromJson(responseContent);
return WxMpMassSendResult.fromJson(responseContent);
}
}
public WxMpMassSendResult massOpenIdsMessageSend(WxMpMassOpenIdsMessage message) throws WxErrorException {
public WxMpMassSendResult massOpenIdsMessageSend(WxMpMassOpenIdsMessage message) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/message/mass/send";
String url = "https://api.weixin.qq.com/cgi-bin/message/mass/send";
String responseContent = execute(new Simple PostRequestExecutor(), url, message.toJson());
String responseContent = execute(new Jodd PostRequestExecutor(), url, message.toJson());
return WxMpMassSendResult.fromJson(responseContent);
return WxMpMassSendResult.fromJson(responseContent);
}
}
@@ -409,7 +415,7 @@ public class WxMpServiceImpl implements WxMpService {
groupJson.addProperty("name", name);
groupJson.addProperty("name", name);
String responseContent = execute(
String responseContent = execute(
new Simple PostRequestExecutor(),
new Jodd PostRequestExecutor(),
url,
url,
json.toString());
json.toString());
return WxMpGroup.fromJson(responseContent);
return WxMpGroup.fromJson(responseContent);
@@ -417,7 +423,7 @@ public class WxMpServiceImpl implements WxMpService {
public List<WxMpGroup> groupGet() throws WxErrorException {
public List<WxMpGroup> groupGet() throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/groups/get";
String url = "https://api.weixin.qq.com/cgi-bin/groups/get";
String responseContent = execute(new Simple GetRequestExecutor(), url, null);
String responseContent = execute(new Jodd GetRequestExecutor(), url, null);
/*
/*
* 操蛋的微信API,创建时返回的是 { group : { id : ..., name : ...} }
* 操蛋的微信API,创建时返回的是 { group : { id : ..., name : ...} }
* 查询时返回的是 { groups : [ { id : ..., name : ..., count : ... }, ... ] }
* 查询时返回的是 { groups : [ { id : ..., name : ..., count : ... }, ... ] }
@@ -432,14 +438,14 @@ public class WxMpServiceImpl implements WxMpService {
String url = "https://api.weixin.qq.com/cgi-bin/groups/getid";
String url = "https://api.weixin.qq.com/cgi-bin/groups/getid";
JsonObject o = new JsonObject();
JsonObject o = new JsonObject();
o.addProperty("openid", openid);
o.addProperty("openid", openid);
String responseContent = execute(new Simple PostRequestExecutor(), url, o.toString());
String responseContent = execute(new Jodd PostRequestExecutor(), url, o.toString());
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
return GsonHelper.getAsLong(tmpJsonElement.getAsJsonObject().get("groupid"));
return GsonHelper.getAsLong(tmpJsonElement.getAsJsonObject().get("groupid"));
}
}
public void groupUpdate(WxMpGroup group) throws WxErrorException {
public void groupUpdate(WxMpGroup group) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/groups/update";
String url = "https://api.weixin.qq.com/cgi-bin/groups/update";
execute(new Simple PostRequestExecutor(), url, group.toJson());
execute(new Jodd PostRequestExecutor(), url, group.toJson());
}
}
public void userUpdateGroup(String openid, long to_groupid) throws WxErrorException {
public void userUpdateGroup(String openid, long to_groupid) throws WxErrorException {
@@ -447,7 +453,7 @@ public class WxMpServiceImpl implements WxMpService {
JsonObject json = new JsonObject();
JsonObject json = new JsonObject();
json.addProperty("openid", openid);
json.addProperty("openid", openid);
json.addProperty("to_groupid", to_groupid);
json.addProperty("to_groupid", to_groupid);
execute(new Simple PostRequestExecutor(), url, json.toString());
execute(new Jodd PostRequestExecutor(), url, json.toString());
}
}
public void userUpdateRemark(String openid, String remark) throws WxErrorException {
public void userUpdateRemark(String openid, String remark) throws WxErrorException {
@@ -455,19 +461,19 @@ public class WxMpServiceImpl implements WxMpService {
JsonObject json = new JsonObject();
JsonObject json = new JsonObject();
json.addProperty("openid", openid);
json.addProperty("openid", openid);
json.addProperty("remark", remark);
json.addProperty("remark", remark);
execute(new Simple PostRequestExecutor(), url, json.toString());
execute(new Jodd PostRequestExecutor(), url, json.toString());
}
}
public WxMpUser userInfo(String openid, String lang) throws WxErrorException {
public WxMpUser userInfo(String openid, String lang) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/user/info";
String url = "https://api.weixin.qq.com/cgi-bin/user/info";
lang = lang == null ? "zh_CN" : lang;
lang = lang == null ? "zh_CN" : lang;
String responseContent = execute(new Simple GetRequestExecutor(), url, "openid=" + openid + "&lang=" + lang);
String responseContent = execute(new Jodd GetRequestExecutor(), url, "openid=" + openid + "&lang=" + lang);
return WxMpUser.fromJson(responseContent);
return WxMpUser.fromJson(responseContent);
}
}
public WxMpUserList userList(String next_openid) throws WxErrorException {
public WxMpUserList userList(String next_openid) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/user/get";
String url = "https://api.weixin.qq.com/cgi-bin/user/get";
String responseContent = execute(new Simple GetRequestExecutor(), url, next_openid == null ? null : "next_openid=" + next_openid);
String responseContent = execute(new Jodd GetRequestExecutor(), url, next_openid == null ? null : "next_openid=" + next_openid);
return WxMpUserList.fromJson(responseContent);
return WxMpUserList.fromJson(responseContent);
}
}
@@ -483,7 +489,7 @@ public class WxMpServiceImpl implements WxMpService {
scene.addProperty("scene_id", scene_id);
scene.addProperty("scene_id", scene_id);
actionInfo.add("scene", scene);
actionInfo.add("scene", scene);
json.add("action_info", actionInfo);
json.add("action_info", actionInfo);
String responseContent = execute(new Simple PostRequestExecutor(), url, json.toString());
String responseContent = execute(new Jodd PostRequestExecutor(), url, json.toString());
return WxMpQrCodeTicket.fromJson(responseContent);
return WxMpQrCodeTicket.fromJson(responseContent);
}
}
@@ -496,7 +502,7 @@ public class WxMpServiceImpl implements WxMpService {
scene.addProperty("scene_id", scene_id);
scene.addProperty("scene_id", scene_id);
actionInfo.add("scene", scene);
actionInfo.add("scene", scene);
json.add("action_info", actionInfo);
json.add("action_info", actionInfo);
String responseContent = execute(new Simple PostRequestExecutor(), url, json.toString());
String responseContent = execute(new Jodd PostRequestExecutor(), url, json.toString());
return WxMpQrCodeTicket.fromJson(responseContent);
return WxMpQrCodeTicket.fromJson(responseContent);
}
}
@@ -509,7 +515,7 @@ public class WxMpServiceImpl implements WxMpService {
scene.addProperty("scene_str", scene_str);
scene.addProperty("scene_str", scene_str);
actionInfo.add("scene", scene);
actionInfo.add("scene", scene);
json.add("action_info", actionInfo);
json.add("action_info", actionInfo);
String responseContent = execute(new Simple PostRequestExecutor(), url, json.toString());
String responseContent = execute(new Jodd PostRequestExecutor(), url, json.toString());
return WxMpQrCodeTicket.fromJson(responseContent);
return WxMpQrCodeTicket.fromJson(responseContent);
}
}
@@ -523,14 +529,14 @@ public class WxMpServiceImpl implements WxMpService {
JsonObject o = new JsonObject();
JsonObject o = new JsonObject();
o.addProperty("action", "long2short");
o.addProperty("action", "long2short");
o.addProperty("long_url", long_url);
o.addProperty("long_url", long_url);
String responseContent = execute(new Simple PostRequestExecutor(), url, o.toString());
String responseContent = execute(new Jodd PostRequestExecutor(), url, o.toString());
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
return tmpJsonElement.getAsJsonObject().get("short_url").getAsString();
return tmpJsonElement.getAsJsonObject().get("short_url").getAsString();
}
}
public String templateSend(WxMpTemplateMessage templateMessage) throws WxErrorException {
public String templateSend(WxMpTemplateMessage templateMessage) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/message/template/send";
String url = "https://api.weixin.qq.com/cgi-bin/message/template/send";
String responseContent = execute(new Simple PostRequestExecutor(), url, templateMessage.toJson());
String responseContent = execute(new Jodd PostRequestExecutor(), url, templateMessage.toJson());
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
final JsonObject jsonObject = tmpJsonElement.getAsJsonObject();
final JsonObject jsonObject = tmpJsonElement.getAsJsonObject();
if (jsonObject.get("errcode").getAsInt() == 0)
if (jsonObject.get("errcode").getAsInt() == 0)
@@ -540,7 +546,7 @@ public class WxMpServiceImpl implements WxMpService {
public WxMpSemanticQueryResult semanticQuery(WxMpSemanticQuery semanticQuery) throws WxErrorException {
public WxMpSemanticQueryResult semanticQuery(WxMpSemanticQuery semanticQuery) throws WxErrorException {
String url = "https://api.weixin.qq.com/semantic/semproxy/search";
String url = "https://api.weixin.qq.com/semantic/semproxy/search";
String responseContent = execute(new Simple PostRequestExecutor(), url, semanticQuery.toJson());
String responseContent = execute(new Jodd PostRequestExecutor(), url, semanticQuery.toJson());
return WxMpSemanticQueryResult.fromJson(responseContent);
return WxMpSemanticQueryResult.fromJson(responseContent);
}
}
@@ -572,7 +578,7 @@ public class WxMpServiceImpl implements WxMpService {
url += "&grant_type=authorization_code";
url += "&grant_type=authorization_code";
try {
try {
RequestExecutor<String, String> executor = new Simple GetRequestExecutor();
RequestExecutor<String, String> executor = new Jodd GetRequestExecutor();
String responseText = executor.execute(getHttpclient(), httpProxy, url, null);
String responseText = executor.execute(getHttpclient(), httpProxy, url, null);
return WxMpOAuth2AccessToken.fromJson(responseText);
return WxMpOAuth2AccessToken.fromJson(responseText);
} catch (ClientProtocolException e) {
} catch (ClientProtocolException e) {
@@ -590,7 +596,7 @@ public class WxMpServiceImpl implements WxMpService {
url += "&refresh_token=" + refreshToken;
url += "&refresh_token=" + refreshToken;
try {
try {
RequestExecutor<String, String> executor = new Simple GetRequestExecutor();
RequestExecutor<String, String> executor = new Jodd GetRequestExecutor();
String responseText = executor.execute(getHttpclient(), httpProxy, url, null);
String responseText = executor.execute(getHttpclient(), httpProxy, url, null);
return WxMpOAuth2AccessToken.fromJson(responseText);
return WxMpOAuth2AccessToken.fromJson(responseText);
} catch (ClientProtocolException e) {
} catch (ClientProtocolException e) {
@@ -612,7 +618,7 @@ public class WxMpServiceImpl implements WxMpService {
}
}
try {
try {
RequestExecutor<String, String> executor = new Simple GetRequestExecutor();
RequestExecutor<String, String> executor = new Jodd GetRequestExecutor();
String responseText = executor.execute(getHttpclient(), httpProxy, url, null);
String responseText = executor.execute(getHttpclient(), httpProxy, url, null);
return WxMpUser.fromJson(responseText);
return WxMpUser.fromJson(responseText);
} catch (ClientProtocolException e) {
} catch (ClientProtocolException e) {
@@ -629,7 +635,7 @@ public class WxMpServiceImpl implements WxMpService {
url += "&openid=" + oAuth2AccessToken.getOpenId();
url += "&openid=" + oAuth2AccessToken.getOpenId();
try {
try {
RequestExecutor<String, String> executor = new Simple GetRequestExecutor();
RequestExecutor<String, String> executor = new Jodd GetRequestExecutor();
executor.execute(getHttpclient(), httpProxy, url, null);
executor.execute(getHttpclient(), httpProxy, url, null);
} catch (ClientProtocolException e) {
} catch (ClientProtocolException e) {
throw new RuntimeException(e);
throw new RuntimeException(e);
@@ -682,11 +688,11 @@ public class WxMpServiceImpl implements WxMpService {
}
}
public String get(String url, String queryParam) throws WxErrorException {
public String get(String url, String queryParam) throws WxErrorException {
return execute(new Simple GetRequestExecutor(), url, queryParam);
return execute(new Jodd GetRequestExecutor(), url, queryParam);
}
}
public String post(String url, String postData) throws WxErrorException {
public String post(String url, String postData) throws WxErrorException {
return execute(new Simple PostRequestExecutor(), url, postData);
return execute(new Jodd PostRequestExecutor(), url, postData);
}
}
/**
/**
@@ -851,8 +857,7 @@ public class WxMpServiceImpl implements WxMpService {
StringEntity entity = new StringEntity(request.toString(), Consts.UTF_8);
StringEntity entity = new StringEntity(request.toString(), Consts.UTF_8);
httpPost.setEntity(entity);
httpPost.setEntity(entity);
try {
CloseableHttpResponse response = getHttpclient().execute(httpPost);
try(CloseableHttpResponse response = getHttpclient().execute(httpPost)) {
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
XStream xstream = XStreamInitializer.getInstance();
XStream xstream = XStreamInitializer.getInstance();
xstream.alias("xml", WxMpPrepayIdResult.class);
xstream.alias("xml", WxMpPrepayIdResult.class);
@@ -878,13 +883,14 @@ public class WxMpServiceImpl implements WxMpService {
}
}
@Override
@Override
public Map<String, String> getJSSDKPayInfo(String openId, String outTradeNo, double amt, String body, String tradeType, String ip, String callbackUrl) {
public Map<String, String> getJSSDKPayInfo(String openId, String outTradeNo, double amt, String body, String tradeType, String ip, String callbackUrl)
throws WxErrorException {
Map<String, String> packageParams = new HashMap<String, String>();
Map<String, String> packageParams = new HashMap<String, String>();
packageParams.put("appid", wxMpConfigStorage.getAppId());
packageParams.put("appid", wxMpConfigStorage.getAppId());
packageParams.put("mch_id", wxMpConfigStorage.getPartnerId());
packageParams.put("mch_id", wxMpConfigStorage.getPartnerId());
packageParams.put("body", body);
packageParams.put("body", body);
packageParams.put("out_trade_no", outTradeNo);
packageParams.put("out_trade_no", outTradeNo);
packageParams.put("total_fee", (int) (amt * 100) + "" );
packageParams.put("total_fee", String.format("%.0f", amt * 100) );
packageParams.put("spbill_create_ip", ip);
packageParams.put("spbill_create_ip", ip);
packageParams.put("notify_url", callbackUrl);
packageParams.put("notify_url", callbackUrl);
packageParams.put("trade_type", tradeType);
packageParams.put("trade_type", tradeType);
@@ -894,8 +900,21 @@ public class WxMpServiceImpl implements WxMpService {
}
}
@Override
@Override
public Map<String, String> getJSSDKPayInfo(Map<String, String> parameters) {
public Map<String, String> getJSSDKPayInfo(Map<String, String> parameters) throws WxErrorException {
WxMpPrepayIdResult wxMpPrepayIdResult = getPrepayId(parameters);
WxMpPrepayIdResult wxMpPrepayIdResult = getPrepayId(parameters);
if (!"SUCCESS".equalsIgnoreCase(wxMpPrepayIdResult.getReturn_code())
||!"SUCCESS".equalsIgnoreCase(wxMpPrepayIdResult.getResult_code())) {
WxError error = new WxError();
error.setErrorCode(-1);
error.setErrorMsg("return_code:" + wxMpPrepayIdResult.getReturn_code() +
";return_msg:" + wxMpPrepayIdResult.getReturn_msg() +
";result_code:" + wxMpPrepayIdResult.getResult_code() +
";err_code" + wxMpPrepayIdResult.getErr_code() +
";err_code_des" + wxMpPrepayIdResult.getErr_code_des());
throw new WxErrorException(error);
}
String prepayId = wxMpPrepayIdResult.getPrepay_id();
String prepayId = wxMpPrepayIdResult.getPrepay_id();
if (prepayId == null || prepayId.equals("")) {
if (prepayId == null || prepayId.equals("")) {
throw new RuntimeException(String.format("Failed to get prepay id due to error code '%s'(%s).", wxMpPrepayIdResult.getErr_code(), wxMpPrepayIdResult.getErr_code_des()));
throw new RuntimeException(String.format("Failed to get prepay id due to error code '%s'(%s).", wxMpPrepayIdResult.getErr_code(), wxMpPrepayIdResult.getErr_code_des()));
@@ -944,8 +963,7 @@ public class WxMpServiceImpl implements WxMpService {
StringEntity entity = new StringEntity(request.toString(), Consts.UTF_8);
StringEntity entity = new StringEntity(request.toString(), Consts.UTF_8);
httpPost.setEntity(entity);
httpPost.setEntity(entity);
try {
CloseableHttpResponse response = httpClient.execute(httpPost);
try(CloseableHttpResponse response = httpClient.execute(httpPost)) {
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
XStream xstream = XStreamInitializer.getInstance();
XStream xstream = XStreamInitializer.getInstance();
xstream.alias("xml", WxMpPayResult.class);
xstream.alias("xml", WxMpPayResult.class);
@@ -969,6 +987,59 @@ public class WxMpServiceImpl implements WxMpService {
return new WxMpPayCallback();
return new WxMpPayCallback();
}
}
@Override
public WxMpPayRefundResult refundPay(Map<String, String> parameters) throws WxErrorException {
SortedMap<String, String> refundParams = new TreeMap<String, String>(parameters);
refundParams.put("appid", wxMpConfigStorage.getAppId());
refundParams.put("mch_id", wxMpConfigStorage.getPartnerId());
refundParams.put("nonce_str", System.currentTimeMillis() + "");
refundParams.put("op_user_id", wxMpConfigStorage.getPartnerId());
String sign = WxCryptUtil.createSign(refundParams, wxMpConfigStorage.getPartnerKey());
refundParams.put("sign", sign);
StringBuilder request = new StringBuilder("<xml>");
for (Entry<String, String> para : refundParams.entrySet()) {
request.append(String.format("<%s>%s</%s>", para.getKey(), para.getValue(), para.getKey()));
}
request.append("</xml>");
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund");
if (httpProxy != null) {
RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build();
httpPost.setConfig(config);
}
StringEntity entity = new StringEntity(request.toString(), Consts.UTF_8);
httpPost.setEntity(entity);
try(
CloseableHttpResponse response = getHttpclient().execute(httpPost)) {
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxMpPayRefundResult.class);
WxMpPayRefundResult wxMpPayRefundResult = (WxMpPayRefundResult) xstream.fromXML(responseContent);
if (!"SUCCESS".equalsIgnoreCase(wxMpPayRefundResult.getResultCode())
||!"SUCCESS".equalsIgnoreCase(wxMpPayRefundResult.getReturnCode())) {
WxError error = new WxError();
error.setErrorCode(-1);
error.setErrorMsg("return_code:" + wxMpPayRefundResult.getReturnCode() +
";return_msg:" + wxMpPayRefundResult.getReturnMsg() +
";result_code:" + wxMpPayRefundResult.getResultCode() +
";err_code" + wxMpPayRefundResult.getErrCode() +
";err_code_des" + wxMpPayRefundResult.getErrCodeDes());
throw new WxErrorException(error);
}
return wxMpPayRefundResult;
} catch (IOException e) {
log.error(MessageFormatter.format("The exception was happened when sending refund '{}'.", request.toString()).getMessage(), e);
WxError error = new WxError();
error.setErrorCode(-1);
error.setErrorMsg("incorrect response.");
throw new WxErrorException(error);
}
}
@Override
@Override
public boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm, String signature) {
public boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm, String signature) {
return signature.equals(WxCryptUtil.createSign(kvm, wxMpConfigStorage.getPartnerKey()));
return signature.equals(WxCryptUtil.createSign(kvm, wxMpConfigStorage.getPartnerKey()));
@@ -1000,8 +1071,7 @@ public class WxMpServiceImpl implements WxMpService {
StringEntity entity = new StringEntity(request.toString(), Consts.UTF_8);
StringEntity entity = new StringEntity(request.toString(), Consts.UTF_8);
httpPost.setEntity(entity);
httpPost.setEntity(entity);
try {
CloseableHttpResponse response = getHttpclient().execute(httpPost);
try(CloseableHttpResponse response = getHttpclient().execute(httpPost)) {
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
XStream xstream = XStreamInitializer.getInstance();
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxRedpackResult.class);
xstream.processAnnotations(WxRedpackResult.class);
@@ -1014,4 +1084,201 @@ public class WxMpServiceImpl implements WxMpService {
throw new WxErrorException(error);
throw new WxErrorException(error);
}
}
}
}
/**
* 获得卡券api_ticket,不强制刷新卡券api_ticket
*
* @return 卡券api_ticket
* @throws WxErrorException
* @see #getCardApiTicket(boolean)
*/
@Override
public String getCardApiTicket() throws WxErrorException {
return getCardApiTicket(false);
}
/**
* <pre>
* 获得卡券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
* </pre>
*
* @param forceRefresh 强制刷新
* @return 卡券api_ticket
* @throws WxErrorException
*/
@Override
public String getCardApiTicket(boolean forceRefresh) throws WxErrorException {
if (forceRefresh) {
wxMpConfigStorage.expireCardApiTicket();
}
if (wxMpConfigStorage.isCardApiTicketExpired()) {
synchronized (globalCardApiTicketRefreshLock) {
if (wxMpConfigStorage.isCardApiTicketExpired()) {
String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=wx_card";
String responseContent = execute(new JoddGetRequestExecutor(), url, null);
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject();
String cardApiTicket = tmpJsonObject.get("ticket").getAsString();
int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt();
wxMpConfigStorage.updateCardApiTicket(cardApiTicket, expiresInSeconds);
}
}
}
return wxMpConfigStorage.getCardApiTicket();
}
/**
* <pre>
* 创建调用卡券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
* </pre>
*
* @param optionalSignParam 参与签名的参数数组。
* 可以为下列字段:app_id, card_id, card_type, code, openid, location_id
* </br>注意:当做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;
try {
String signature = SHA1.gen(signParam);
WxCardApiSignature cardApiSignature = new WxCardApiSignature();
cardApiSignature.setTimestamp(timestamp);
cardApiSignature.setNonceStr(nonceStr);
cardApiSignature.setSignature(signature);
return cardApiSignature;
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
/**
* 卡券Code解码
*
* @param encryptCode 加密Code,通过JSSDK的chooseCard接口获得
* @return 解密后的Code
* @throws WxErrorException
*/
@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 = post(url, param.toString());
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(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对象
* @throws WxErrorException
*/
@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 = post(url, param.toString());
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
return WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement,
new TypeToken<WxMpCardResult>() {
}.getType());
}
/**
* 卡券Code核销。核销失败会抛出异常
*
* @param code 单张卡券的唯一标准
* @throws WxErrorException
*/
@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);
}
String responseContent = post(url, param.toString());
return responseContent;
}
/**
* 卡券Mark接口。
* 开发者在帮助消费者核销卡券之前,必须帮助先将此code(卡券串码)与一个openid绑定(即mark住),
* 才能进一步调用核销接口,否则报错。
*
* @param code 卡券的code码
* @param cardId 卡券的ID
* @param openId 用券用户的openid
* @param isMark 是否要mark(占用)这个code,填写true或者false,表示占用或解除占用
* @throws WxErrorException
*/
@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 = post(url, param.toString());
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
WxMpCardResult cardResult = WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement,
new TypeToken<WxMpCardResult>() { }.getType());
if (!cardResult.getErrorCode().equals("0")) {
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 = 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;
}
}
}