|
@@ -1,12 +1,28 @@ |
|
|
package me.chanjar.weixin.cp.api; |
|
|
package me.chanjar.weixin.cp.api; |
|
|
|
|
|
|
|
|
|
|
|
import java.io.File; |
|
|
|
|
|
import java.io.IOException; |
|
|
|
|
|
import java.io.InputStream; |
|
|
|
|
|
import java.util.List; |
|
|
|
|
|
import java.util.UUID; |
|
|
|
|
|
|
|
|
|
|
|
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.impl.client.BasicResponseHandler; |
|
|
|
|
|
import org.apache.http.impl.client.CloseableHttpClient; |
|
|
|
|
|
import org.slf4j.Logger; |
|
|
|
|
|
import org.slf4j.LoggerFactory; |
|
|
|
|
|
|
|
|
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.JsonPrimitive; |
|
|
import com.google.gson.JsonPrimitive; |
|
|
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 me.chanjar.weixin.common.bean.WxAccessToken; |
|
|
import me.chanjar.weixin.common.bean.WxAccessToken; |
|
|
import me.chanjar.weixin.common.bean.WxJsapiSignature; |
|
|
import me.chanjar.weixin.common.bean.WxJsapiSignature; |
|
|
import me.chanjar.weixin.common.bean.menu.WxMenu; |
|
|
import me.chanjar.weixin.common.bean.menu.WxMenu; |
|
@@ -20,30 +36,20 @@ import me.chanjar.weixin.common.util.RandomUtils; |
|
|
import me.chanjar.weixin.common.util.StringUtils; |
|
|
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.fs.FileUtils; |
|
|
import me.chanjar.weixin.common.util.fs.FileUtils; |
|
|
import me.chanjar.weixin.common.util.http.*; |
|
|
|
|
|
|
|
|
import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder; |
|
|
|
|
|
import me.chanjar.weixin.common.util.http.DefaultApacheHttpClientBuilder; |
|
|
|
|
|
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.json.GsonHelper; |
|
|
import me.chanjar.weixin.common.util.json.GsonHelper; |
|
|
import me.chanjar.weixin.cp.bean.WxCpDepart; |
|
|
import me.chanjar.weixin.cp.bean.WxCpDepart; |
|
|
import me.chanjar.weixin.cp.bean.WxCpMessage; |
|
|
import me.chanjar.weixin.cp.bean.WxCpMessage; |
|
|
import me.chanjar.weixin.cp.bean.WxCpTag; |
|
|
import me.chanjar.weixin.cp.bean.WxCpTag; |
|
|
import me.chanjar.weixin.cp.bean.WxCpUser; |
|
|
import me.chanjar.weixin.cp.bean.WxCpUser; |
|
|
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; |
|
|
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; |
|
|
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.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.io.StringReader; |
|
|
|
|
|
import java.security.NoSuchAlgorithmException; |
|
|
|
|
|
import java.util.List; |
|
|
|
|
|
import java.util.UUID; |
|
|
|
|
|
|
|
|
|
|
|
public class WxCpServiceImpl implements WxCpService { |
|
|
public class WxCpServiceImpl implements WxCpService { |
|
|
|
|
|
|
|
@@ -72,42 +78,48 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
private int retrySleepMillis = 1000; |
|
|
private int retrySleepMillis = 1000; |
|
|
private int maxRetryTimes = 5; |
|
|
private int maxRetryTimes = 5; |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
public boolean checkSignature(String msgSignature, String timestamp, String nonce, String data) { |
|
|
public boolean checkSignature(String msgSignature, String timestamp, String nonce, String data) { |
|
|
try { |
|
|
try { |
|
|
return SHA1.gen(wxCpConfigStorage.getToken(), timestamp, nonce, data).equals(msgSignature); |
|
|
|
|
|
|
|
|
return SHA1.gen(this.wxCpConfigStorage.getToken(), timestamp, nonce, data) |
|
|
|
|
|
.equals(msgSignature); |
|
|
} catch (Exception e) { |
|
|
} catch (Exception e) { |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
public void userAuthenticated(String userId) throws WxErrorException { |
|
|
public void userAuthenticated(String userId) throws WxErrorException { |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/user/authsucc?userid=" + userId; |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/user/authsucc?userid=" + userId; |
|
|
get(url, null); |
|
|
get(url, null); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
public String getAccessToken() throws WxErrorException { |
|
|
public String getAccessToken() throws WxErrorException { |
|
|
return getAccessToken(false); |
|
|
return getAccessToken(false); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
public String getAccessToken(boolean forceRefresh) throws WxErrorException { |
|
|
public String getAccessToken(boolean forceRefresh) throws WxErrorException { |
|
|
if (forceRefresh) { |
|
|
if (forceRefresh) { |
|
|
wxCpConfigStorage.expireAccessToken(); |
|
|
|
|
|
|
|
|
this.wxCpConfigStorage.expireAccessToken(); |
|
|
} |
|
|
} |
|
|
if (wxCpConfigStorage.isAccessTokenExpired()) { |
|
|
|
|
|
synchronized (globalAccessTokenRefreshLock) { |
|
|
|
|
|
if (wxCpConfigStorage.isAccessTokenExpired()) { |
|
|
|
|
|
|
|
|
if (this.wxCpConfigStorage.isAccessTokenExpired()) { |
|
|
|
|
|
synchronized (this.globalAccessTokenRefreshLock) { |
|
|
|
|
|
if (this.wxCpConfigStorage.isAccessTokenExpired()) { |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?" |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?" |
|
|
+ "&corpid=" + wxCpConfigStorage.getCorpId() |
|
|
|
|
|
+ "&corpsecret=" + wxCpConfigStorage.getCorpSecret(); |
|
|
|
|
|
|
|
|
+ "&corpid=" + this.wxCpConfigStorage.getCorpId() + "&corpsecret=" |
|
|
|
|
|
+ this.wxCpConfigStorage.getCorpSecret(); |
|
|
try { |
|
|
try { |
|
|
HttpGet httpGet = new HttpGet(url); |
|
|
HttpGet httpGet = new HttpGet(url); |
|
|
if (httpProxy != null) { |
|
|
|
|
|
RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); |
|
|
|
|
|
|
|
|
if (this.httpProxy != null) { |
|
|
|
|
|
RequestConfig config = RequestConfig.custom() |
|
|
|
|
|
.setProxy(this.httpProxy).build(); |
|
|
httpGet.setConfig(config); |
|
|
httpGet.setConfig(config); |
|
|
} |
|
|
} |
|
|
CloseableHttpClient httpclient = getHttpclient(); |
|
|
|
|
|
String resultContent = null; |
|
|
String resultContent = null; |
|
|
try (CloseableHttpResponse response = httpclient.execute(httpGet)) { |
|
|
|
|
|
|
|
|
try (CloseableHttpClient httpclient = getHttpclient(); |
|
|
|
|
|
CloseableHttpResponse response = httpclient.execute(httpGet)) { |
|
|
resultContent = new BasicResponseHandler().handleResponse(response); |
|
|
resultContent = new BasicResponseHandler().handleResponse(response); |
|
|
} finally { |
|
|
} finally { |
|
|
httpGet.releaseConnection(); |
|
|
httpGet.releaseConnection(); |
|
@@ -117,7 +129,8 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
throw new WxErrorException(error); |
|
|
throw new WxErrorException(error); |
|
|
} |
|
|
} |
|
|
WxAccessToken accessToken = WxAccessToken.fromJson(resultContent); |
|
|
WxAccessToken accessToken = WxAccessToken.fromJson(resultContent); |
|
|
wxCpConfigStorage.updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn()); |
|
|
|
|
|
|
|
|
this.wxCpConfigStorage.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) { |
|
@@ -126,33 +139,37 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
return wxCpConfigStorage.getAccessToken(); |
|
|
|
|
|
|
|
|
return this.wxCpConfigStorage.getAccessToken(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
public String getJsapiTicket() throws WxErrorException { |
|
|
public String getJsapiTicket() throws WxErrorException { |
|
|
return getJsapiTicket(false); |
|
|
return getJsapiTicket(false); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
public String getJsapiTicket(boolean forceRefresh) throws WxErrorException { |
|
|
public String getJsapiTicket(boolean forceRefresh) throws WxErrorException { |
|
|
if (forceRefresh) { |
|
|
if (forceRefresh) { |
|
|
wxCpConfigStorage.expireJsapiTicket(); |
|
|
|
|
|
|
|
|
this.wxCpConfigStorage.expireJsapiTicket(); |
|
|
} |
|
|
} |
|
|
if (wxCpConfigStorage.isJsapiTicketExpired()) { |
|
|
|
|
|
synchronized (globalJsapiTicketRefreshLock) { |
|
|
|
|
|
if (wxCpConfigStorage.isJsapiTicketExpired()) { |
|
|
|
|
|
|
|
|
if (this.wxCpConfigStorage.isJsapiTicketExpired()) { |
|
|
|
|
|
synchronized (this.globalJsapiTicketRefreshLock) { |
|
|
|
|
|
if (this.wxCpConfigStorage.isJsapiTicketExpired()) { |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket"; |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket"; |
|
|
String responseContent = execute(new SimpleGetRequestExecutor(), url, null); |
|
|
String responseContent = execute(new SimpleGetRequestExecutor(), url, null); |
|
|
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); |
|
|
|
|
|
|
|
|
JsonElement tmpJsonElement = new JsonParser().parse(responseContent); |
|
|
JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); |
|
|
JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); |
|
|
String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); |
|
|
String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); |
|
|
int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); |
|
|
int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); |
|
|
wxCpConfigStorage.updateJsapiTicket(jsapiTicket, expiresInSeconds); |
|
|
|
|
|
|
|
|
this.wxCpConfigStorage.updateJsapiTicket(jsapiTicket, |
|
|
|
|
|
expiresInSeconds); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
return wxCpConfigStorage.getJsapiTicket(); |
|
|
|
|
|
|
|
|
return this.wxCpConfigStorage.getJsapiTicket(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
public WxJsapiSignature createJsapiSignature(String url) throws WxErrorException { |
|
|
public WxJsapiSignature createJsapiSignature(String url) throws WxErrorException { |
|
|
long timestamp = System.currentTimeMillis() / 1000; |
|
|
long timestamp = System.currentTimeMillis() / 1000; |
|
|
String noncestr = RandomUtils.getRandomStr(); |
|
|
String noncestr = RandomUtils.getRandomStr(); |
|
@@ -175,6 +192,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
return jsapiSignature; |
|
|
return jsapiSignature; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
public void messageSend(WxCpMessage message) throws WxErrorException { |
|
|
public void messageSend(WxCpMessage message) throws WxErrorException { |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/message/send"; |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/message/send"; |
|
|
post(url, message.toJson()); |
|
|
post(url, message.toJson()); |
|
@@ -182,18 +200,19 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public void menuCreate(WxMenu menu) throws WxErrorException { |
|
|
public void menuCreate(WxMenu menu) throws WxErrorException { |
|
|
menuCreate(wxCpConfigStorage.getAgentId(), menu); |
|
|
|
|
|
|
|
|
menuCreate(this.wxCpConfigStorage.getAgentId(), menu); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public void menuCreate(String agentId, WxMenu menu) throws WxErrorException { |
|
|
public void menuCreate(String agentId, WxMenu menu) throws WxErrorException { |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/create?agentid=" + wxCpConfigStorage.getAgentId(); |
|
|
|
|
|
|
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/create?agentid=" |
|
|
|
|
|
+ this.wxCpConfigStorage.getAgentId(); |
|
|
post(url, menu.toJson()); |
|
|
post(url, menu.toJson()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public void menuDelete() throws WxErrorException { |
|
|
public void menuDelete() throws WxErrorException { |
|
|
menuDelete(wxCpConfigStorage.getAgentId()); |
|
|
|
|
|
|
|
|
menuDelete(this.wxCpConfigStorage.getAgentId()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
@@ -204,7 +223,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public WxMenu menuGet() throws WxErrorException { |
|
|
public WxMenu menuGet() throws WxErrorException { |
|
|
return menuGet(wxCpConfigStorage.getAgentId()); |
|
|
|
|
|
|
|
|
return menuGet(this.wxCpConfigStorage.getAgentId()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
@@ -222,42 +241,52 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) |
|
|
public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) |
|
|
throws WxErrorException, IOException { |
|
|
throws WxErrorException, IOException { |
|
|
return mediaUpload(mediaType, FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType)); |
|
|
return mediaUpload(mediaType, FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException { |
|
|
public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException { |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?type=" + mediaType; |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?type=" + mediaType; |
|
|
return execute(new MediaUploadRequestExecutor(), url, file); |
|
|
return execute(new MediaUploadRequestExecutor(), url, file); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
public File mediaDownload(String media_id) throws WxErrorException { |
|
|
public File mediaDownload(String media_id) throws WxErrorException { |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/media/get"; |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/media/get"; |
|
|
return execute(new MediaDownloadRequestExecutor(wxCpConfigStorage.getTmpDirFile()), url, "media_id=" + media_id); |
|
|
|
|
|
|
|
|
return execute( |
|
|
|
|
|
new MediaDownloadRequestExecutor( |
|
|
|
|
|
this.wxCpConfigStorage.getTmpDirFile()), |
|
|
|
|
|
url, "media_id=" + media_id); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
public Integer departCreate(WxCpDepart depart) throws WxErrorException { |
|
|
public Integer departCreate(WxCpDepart depart) throws WxErrorException { |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/department/create"; |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/department/create"; |
|
|
String responseContent = execute( |
|
|
String responseContent = execute( |
|
|
new SimplePostRequestExecutor(), |
|
|
new SimplePostRequestExecutor(), |
|
|
url, |
|
|
url, |
|
|
depart.toJson()); |
|
|
depart.toJson()); |
|
|
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); |
|
|
|
|
|
|
|
|
JsonElement tmpJsonElement = new JsonParser().parse(responseContent); |
|
|
return GsonHelper.getAsInteger(tmpJsonElement.getAsJsonObject().get("id")); |
|
|
return GsonHelper.getAsInteger(tmpJsonElement.getAsJsonObject().get("id")); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
public void departUpdate(WxCpDepart group) throws WxErrorException { |
|
|
public void departUpdate(WxCpDepart group) throws WxErrorException { |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/department/update"; |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/department/update"; |
|
|
post(url, group.toJson()); |
|
|
post(url, group.toJson()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
public void departDelete(Integer departId) throws WxErrorException { |
|
|
public void departDelete(Integer departId) throws WxErrorException { |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/department/delete?id=" + departId; |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/department/delete?id=" + departId; |
|
|
get(url, null); |
|
|
get(url, null); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
public List<WxCpDepart> departGet() throws WxErrorException { |
|
|
public List<WxCpDepart> departGet() throws WxErrorException { |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/department/list"; |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/department/list"; |
|
|
String responseContent = get(url, null); |
|
|
String responseContent = get(url, null); |
|
@@ -265,7 +294,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
* 操蛋的微信API,创建时返回的是 { group : { id : ..., name : ...} } |
|
|
* 操蛋的微信API,创建时返回的是 { group : { id : ..., name : ...} } |
|
|
* 查询时返回的是 { groups : [ { id : ..., name : ..., count : ... }, ... ] } |
|
|
* 查询时返回的是 { groups : [ { id : ..., name : ..., count : ... }, ... ] } |
|
|
*/ |
|
|
*/ |
|
|
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); |
|
|
|
|
|
|
|
|
JsonElement tmpJsonElement = new JsonParser().parse(responseContent); |
|
|
return WxCpGsonBuilder.INSTANCE.create() |
|
|
return WxCpGsonBuilder.INSTANCE.create() |
|
|
.fromJson( |
|
|
.fromJson( |
|
|
tmpJsonElement.getAsJsonObject().get("department"), |
|
|
tmpJsonElement.getAsJsonObject().get("department"), |
|
@@ -325,7 +354,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
String responseContent = get(url, params); |
|
|
String responseContent = get(url, params); |
|
|
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); |
|
|
|
|
|
|
|
|
JsonElement tmpJsonElement = new JsonParser().parse(responseContent); |
|
|
return WxCpGsonBuilder.INSTANCE.create() |
|
|
return WxCpGsonBuilder.INSTANCE.create() |
|
|
.fromJson( |
|
|
.fromJson( |
|
|
tmpJsonElement.getAsJsonObject().get("userlist"), |
|
|
tmpJsonElement.getAsJsonObject().get("userlist"), |
|
@@ -348,7 +377,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
String responseContent = get(url, params); |
|
|
String responseContent = get(url, params); |
|
|
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); |
|
|
|
|
|
|
|
|
JsonElement tmpJsonElement = new JsonParser().parse(responseContent); |
|
|
return WxCpGsonBuilder.INSTANCE.create() |
|
|
return WxCpGsonBuilder.INSTANCE.create() |
|
|
.fromJson( |
|
|
.fromJson( |
|
|
tmpJsonElement.getAsJsonObject().get("userlist"), |
|
|
tmpJsonElement.getAsJsonObject().get("userlist"), |
|
@@ -363,7 +392,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
JsonObject o = new JsonObject(); |
|
|
JsonObject o = new JsonObject(); |
|
|
o.addProperty("tagname", tagName); |
|
|
o.addProperty("tagname", tagName); |
|
|
String responseContent = post(url, o.toString()); |
|
|
String responseContent = post(url, o.toString()); |
|
|
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); |
|
|
|
|
|
|
|
|
JsonElement tmpJsonElement = new JsonParser().parse(responseContent); |
|
|
return tmpJsonElement.getAsJsonObject().get("tagid").getAsString(); |
|
|
return tmpJsonElement.getAsJsonObject().get("tagid").getAsString(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@@ -386,7 +415,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
public List<WxCpTag> tagGet() throws WxErrorException { |
|
|
public List<WxCpTag> tagGet() throws WxErrorException { |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/list"; |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/list"; |
|
|
String responseContent = get(url, null); |
|
|
String responseContent = get(url, null); |
|
|
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); |
|
|
|
|
|
|
|
|
JsonElement tmpJsonElement = new JsonParser().parse(responseContent); |
|
|
return WxCpGsonBuilder.INSTANCE.create() |
|
|
return WxCpGsonBuilder.INSTANCE.create() |
|
|
.fromJson( |
|
|
.fromJson( |
|
|
tmpJsonElement.getAsJsonObject().get("taglist"), |
|
|
tmpJsonElement.getAsJsonObject().get("taglist"), |
|
@@ -399,7 +428,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
public List<WxCpUser> tagGetUsers(String tagId) throws WxErrorException { |
|
|
public List<WxCpUser> tagGetUsers(String tagId) throws WxErrorException { |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/get?tagid=" + tagId; |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/get?tagid=" + tagId; |
|
|
String responseContent = get(url, null); |
|
|
String responseContent = get(url, null); |
|
|
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); |
|
|
|
|
|
|
|
|
JsonElement tmpJsonElement = new JsonParser().parse(responseContent); |
|
|
return WxCpGsonBuilder.INSTANCE.create() |
|
|
return WxCpGsonBuilder.INSTANCE.create() |
|
|
.fromJson( |
|
|
.fromJson( |
|
|
tmpJsonElement.getAsJsonObject().get("userlist"), |
|
|
tmpJsonElement.getAsJsonObject().get("userlist"), |
|
@@ -454,7 +483,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
@Override |
|
|
@Override |
|
|
public String oauth2buildAuthorizationUrl(String redirectUri, String state) { |
|
|
public String oauth2buildAuthorizationUrl(String redirectUri, String state) { |
|
|
String url = "https://open.weixin.qq.com/connect/oauth2/authorize?"; |
|
|
String url = "https://open.weixin.qq.com/connect/oauth2/authorize?"; |
|
|
url += "appid=" + wxCpConfigStorage.getCorpId(); |
|
|
|
|
|
|
|
|
url += "appid=" + this.wxCpConfigStorage.getCorpId(); |
|
|
url += "&redirect_uri=" + URIUtil.encodeURIComponent(redirectUri); |
|
|
url += "&redirect_uri=" + URIUtil.encodeURIComponent(redirectUri); |
|
|
url += "&response_type=code"; |
|
|
url += "&response_type=code"; |
|
|
url += "&scope=snsapi_base"; |
|
|
url += "&scope=snsapi_base"; |
|
@@ -467,7 +496,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public String[] oauth2getUserInfo(String code) throws WxErrorException { |
|
|
public String[] oauth2getUserInfo(String code) throws WxErrorException { |
|
|
return oauth2getUserInfo(wxCpConfigStorage.getAgentId(), code); |
|
|
|
|
|
|
|
|
return oauth2getUserInfo(this.wxCpConfigStorage.getAgentId(), code); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
@@ -476,7 +505,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
+ "code=" + code |
|
|
+ "code=" + code |
|
|
+ "&agendid=" + agentId; |
|
|
+ "&agendid=" + agentId; |
|
|
String responseText = get(url, null); |
|
|
String responseText = get(url, null); |
|
|
JsonElement je = Streams.parse(new JsonReader(new StringReader(responseText))); |
|
|
|
|
|
|
|
|
JsonElement je = new JsonParser().parse(responseText); |
|
|
JsonObject jo = je.getAsJsonObject(); |
|
|
JsonObject jo = je.getAsJsonObject(); |
|
|
return new String[]{GsonHelper.getString(jo, "UserId"), GsonHelper.getString(jo, "DeviceId")}; |
|
|
return new String[]{GsonHelper.getString(jo, "UserId"), GsonHelper.getString(jo, "DeviceId")}; |
|
|
} |
|
|
} |
|
@@ -490,7 +519,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
jsonObject.addProperty("invite_tips", inviteTips); |
|
|
jsonObject.addProperty("invite_tips", inviteTips); |
|
|
} |
|
|
} |
|
|
String responseContent = post(url, jsonObject.toString()); |
|
|
String responseContent = post(url, jsonObject.toString()); |
|
|
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); |
|
|
|
|
|
|
|
|
JsonElement tmpJsonElement = new JsonParser().parse(responseContent); |
|
|
return tmpJsonElement.getAsJsonObject().get("type").getAsInt(); |
|
|
return tmpJsonElement.getAsJsonObject().get("type").getAsInt(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@@ -498,7 +527,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
public String[] getCallbackIp() throws WxErrorException { |
|
|
public String[] getCallbackIp() throws WxErrorException { |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/getcallbackip"; |
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/getcallbackip"; |
|
|
String responseContent = get(url, null); |
|
|
String responseContent = get(url, null); |
|
|
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); |
|
|
|
|
|
|
|
|
JsonElement tmpJsonElement = new JsonParser().parse(responseContent); |
|
|
JsonArray jsonArray = tmpJsonElement.getAsJsonObject().get("ip_list").getAsJsonArray(); |
|
|
JsonArray jsonArray = tmpJsonElement.getAsJsonObject().get("ip_list").getAsJsonArray(); |
|
|
String[] ips = new String[jsonArray.size()]; |
|
|
String[] ips = new String[jsonArray.size()]; |
|
|
for (int i = 0; i < jsonArray.size(); i++) { |
|
|
for (int i = 0; i < jsonArray.size(); i++) { |
|
@@ -507,10 +536,12 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
return ips; |
|
|
return ips; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
public String get(String url, String queryParam) throws WxErrorException { |
|
|
public String get(String url, String queryParam) throws WxErrorException { |
|
|
return execute(new SimpleGetRequestExecutor(), url, queryParam); |
|
|
return execute(new SimpleGetRequestExecutor(), url, queryParam); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
public String post(String url, String postData) throws WxErrorException { |
|
|
public String post(String url, String postData) throws WxErrorException { |
|
|
return execute(new SimplePostRequestExecutor(), url, postData); |
|
|
return execute(new SimplePostRequestExecutor(), url, postData); |
|
|
} |
|
|
} |
|
@@ -518,6 +549,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
/** |
|
|
/** |
|
|
* 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 |
|
|
* 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 |
|
|
*/ |
|
|
*/ |
|
|
|
|
|
@Override |
|
|
public <T, E> T execute(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException { |
|
|
public <T, E> T execute(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException { |
|
|
int retryTimes = 0; |
|
|
int retryTimes = 0; |
|
|
do { |
|
|
do { |
|
@@ -529,9 +561,10 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
* -1 系统繁忙, 1000ms后重试 |
|
|
* -1 系统繁忙, 1000ms后重试 |
|
|
*/ |
|
|
*/ |
|
|
if (error.getErrorCode() == -1) { |
|
|
if (error.getErrorCode() == -1) { |
|
|
int sleepMillis = retrySleepMillis * (1 << retryTimes); |
|
|
|
|
|
|
|
|
int sleepMillis = this.retrySleepMillis * (1 << retryTimes); |
|
|
try { |
|
|
try { |
|
|
log.debug("微信系统繁忙,{}ms 后重试(第{}次)", sleepMillis, retryTimes + 1); |
|
|
|
|
|
|
|
|
this.log.debug("微信系统繁忙,{}ms 后重试(第{}次)", sleepMillis, |
|
|
|
|
|
retryTimes + 1); |
|
|
Thread.sleep(sleepMillis); |
|
|
Thread.sleep(sleepMillis); |
|
|
} catch (InterruptedException e1) { |
|
|
} catch (InterruptedException e1) { |
|
|
throw new RuntimeException(e1); |
|
|
throw new RuntimeException(e1); |
|
@@ -540,7 +573,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
throw e; |
|
|
throw e; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} while (++retryTimes < maxRetryTimes); |
|
|
|
|
|
|
|
|
} while (++retryTimes < this.maxRetryTimes); |
|
|
|
|
|
|
|
|
throw new RuntimeException("微信服务端异常,超出重试次数"); |
|
|
throw new RuntimeException("微信服务端异常,超出重试次数"); |
|
|
} |
|
|
} |
|
@@ -555,7 +588,8 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken; |
|
|
uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken; |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
return executor.execute(getHttpclient(), httpProxy, uriWithAccessToken, data); |
|
|
|
|
|
|
|
|
return executor.execute(getHttpclient(), this.httpProxy, |
|
|
|
|
|
uriWithAccessToken, data); |
|
|
} catch (WxErrorException e) { |
|
|
} catch (WxErrorException e) { |
|
|
WxError error = e.getError(); |
|
|
WxError error = e.getError(); |
|
|
/* |
|
|
/* |
|
@@ -565,7 +599,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
*/ |
|
|
*/ |
|
|
if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) { |
|
|
if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) { |
|
|
// 强制设置wxCpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token |
|
|
// 强制设置wxCpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token |
|
|
wxCpConfigStorage.expireAccessToken(); |
|
|
|
|
|
|
|
|
this.wxCpConfigStorage.expireAccessToken(); |
|
|
return execute(executor, uri, data); |
|
|
return execute(executor, uri, data); |
|
|
} |
|
|
} |
|
|
if (error.getErrorCode() != 0) { |
|
|
if (error.getErrorCode() != 0) { |
|
@@ -580,21 +614,24 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
protected CloseableHttpClient getHttpclient() { |
|
|
protected CloseableHttpClient getHttpclient() { |
|
|
return httpClient; |
|
|
|
|
|
|
|
|
return this.httpClient; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
public void setWxCpConfigStorage(WxCpConfigStorage wxConfigProvider) { |
|
|
public void setWxCpConfigStorage(WxCpConfigStorage wxConfigProvider) { |
|
|
this.wxCpConfigStorage = wxConfigProvider; |
|
|
this.wxCpConfigStorage = wxConfigProvider; |
|
|
ApacheHttpClientBuilder apacheHttpClientBuilder = wxCpConfigStorage.getApacheHttpClientBuilder(); |
|
|
|
|
|
|
|
|
ApacheHttpClientBuilder apacheHttpClientBuilder = this.wxCpConfigStorage |
|
|
|
|
|
.getApacheHttpClientBuilder(); |
|
|
if (null == apacheHttpClientBuilder) { |
|
|
if (null == apacheHttpClientBuilder) { |
|
|
apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get(); |
|
|
apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get(); |
|
|
} |
|
|
} |
|
|
apacheHttpClientBuilder.httpProxyHost(wxCpConfigStorage.getHttp_proxy_host()) |
|
|
|
|
|
.httpProxyPort(wxCpConfigStorage.getHttp_proxy_port()) |
|
|
|
|
|
.httpProxyUsername(wxCpConfigStorage.getHttp_proxy_username()) |
|
|
|
|
|
.httpProxyPassword(wxCpConfigStorage.getHttp_proxy_password()); |
|
|
|
|
|
|
|
|
apacheHttpClientBuilder |
|
|
|
|
|
.httpProxyHost(this.wxCpConfigStorage.getHttp_proxy_host()) |
|
|
|
|
|
.httpProxyPort(this.wxCpConfigStorage.getHttp_proxy_port()) |
|
|
|
|
|
.httpProxyUsername(this.wxCpConfigStorage.getHttp_proxy_username()) |
|
|
|
|
|
.httpProxyPassword(this.wxCpConfigStorage.getHttp_proxy_password()); |
|
|
|
|
|
|
|
|
httpClient = apacheHttpClientBuilder.build(); |
|
|
|
|
|
|
|
|
this.httpClient = apacheHttpClientBuilder.build(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
@@ -610,18 +647,18 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public WxSession getSession(String id) { |
|
|
public WxSession getSession(String id) { |
|
|
if (sessionManager == null) { |
|
|
|
|
|
|
|
|
if (this.sessionManager == null) { |
|
|
return null; |
|
|
return null; |
|
|
} |
|
|
} |
|
|
return sessionManager.getSession(id); |
|
|
|
|
|
|
|
|
return this.sessionManager.getSession(id); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public WxSession getSession(String id, boolean create) { |
|
|
public WxSession getSession(String id, boolean create) { |
|
|
if (sessionManager == null) { |
|
|
|
|
|
|
|
|
if (this.sessionManager == null) { |
|
|
return null; |
|
|
return null; |
|
|
} |
|
|
} |
|
|
return sessionManager.getSession(id, create); |
|
|
|
|
|
|
|
|
return this.sessionManager.getSession(id, create); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -653,7 +690,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public File getTmpDirFile() { |
|
|
public File getTmpDirFile() { |
|
|
return tmpDirFile; |
|
|
|
|
|
|
|
|
return this.tmpDirFile; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public void setTmpDirFile(File tmpDirFile) { |
|
|
public void setTmpDirFile(File tmpDirFile) { |
|
|