|
|
@@ -23,7 +23,6 @@ import me.chanjar.weixin.cp.bean.WxCpUser; |
|
|
|
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; |
|
|
|
import org.apache.commons.lang3.StringUtils; |
|
|
|
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; |
|
|
@@ -69,7 +68,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
|
public boolean checkSignature(String msgSignature, String timestamp, String nonce, String data) { |
|
|
|
try { |
|
|
|
return SHA1.gen(this.configStorage.getToken(), timestamp, nonce, data) |
|
|
|
.equals(msgSignature); |
|
|
|
.equals(msgSignature); |
|
|
|
} catch (Exception e) { |
|
|
|
return false; |
|
|
|
} |
|
|
@@ -95,18 +94,18 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
|
synchronized (this.globalAccessTokenRefreshLock) { |
|
|
|
if (this.configStorage.isAccessTokenExpired()) { |
|
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?" |
|
|
|
+ "&corpid=" + this.configStorage.getCorpId() |
|
|
|
+ "&corpsecret=" + this.configStorage.getCorpSecret(); |
|
|
|
+ "&corpid=" + this.configStorage.getCorpId() |
|
|
|
+ "&corpsecret=" + this.configStorage.getCorpSecret(); |
|
|
|
try { |
|
|
|
HttpGet httpGet = new HttpGet(url); |
|
|
|
if (this.httpProxy != null) { |
|
|
|
RequestConfig config = RequestConfig.custom() |
|
|
|
.setProxy(this.httpProxy).build(); |
|
|
|
.setProxy(this.httpProxy).build(); |
|
|
|
httpGet.setConfig(config); |
|
|
|
} |
|
|
|
String resultContent = null; |
|
|
|
try (CloseableHttpClient httpclient = getHttpclient(); |
|
|
|
CloseableHttpResponse response = httpclient.execute(httpGet)) { |
|
|
|
CloseableHttpResponse response = httpclient.execute(httpGet)) { |
|
|
|
resultContent = new BasicResponseHandler().handleResponse(response); |
|
|
|
} finally { |
|
|
|
httpGet.releaseConnection(); |
|
|
@@ -117,9 +116,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
|
} |
|
|
|
WxAccessToken accessToken = WxAccessToken.fromJson(resultContent); |
|
|
|
this.configStorage.updateAccessToken( |
|
|
|
accessToken.getAccessToken(), accessToken.getExpiresIn()); |
|
|
|
} catch (ClientProtocolException e) { |
|
|
|
throw new RuntimeException(e); |
|
|
|
accessToken.getAccessToken(), accessToken.getExpiresIn()); |
|
|
|
} catch (IOException e) { |
|
|
|
throw new RuntimeException(e); |
|
|
|
} |
|
|
@@ -149,7 +146,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
|
String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); |
|
|
|
int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); |
|
|
|
this.configStorage.updateJsapiTicket(jsapiTicket, |
|
|
|
expiresInSeconds); |
|
|
|
expiresInSeconds); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@@ -162,10 +159,10 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
|
String noncestr = RandomUtils.getRandomStr(); |
|
|
|
String jsapiTicket = getJsapiTicket(false); |
|
|
|
String signature = SHA1.genWithAmple( |
|
|
|
"jsapi_ticket=" + jsapiTicket, |
|
|
|
"noncestr=" + noncestr, |
|
|
|
"timestamp=" + timestamp, |
|
|
|
"url=" + url |
|
|
|
"jsapi_ticket=" + jsapiTicket, |
|
|
|
"noncestr=" + noncestr, |
|
|
|
"timestamp=" + timestamp, |
|
|
|
"url=" + url |
|
|
|
); |
|
|
|
WxJsapiSignature jsapiSignature = new WxJsapiSignature(); |
|
|
|
jsapiSignature.setTimestamp(timestamp); |
|
|
@@ -193,7 +190,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
|
@Override |
|
|
|
public void menuCreate(Integer agentId, WxMenu menu) throws WxErrorException { |
|
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/create?agentid=" |
|
|
|
+ this.configStorage.getAgentId(); |
|
|
|
+ this.configStorage.getAgentId(); |
|
|
|
post(url, menu.toJson()); |
|
|
|
} |
|
|
|
|
|
|
@@ -230,7 +227,7 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
|
|
|
|
|
@Override |
|
|
|
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)); |
|
|
|
} |
|
|
|
|
|
|
@@ -244,9 +241,9 @@ public class WxCpServiceImpl implements WxCpService { |
|
|
|
public File mediaDownload(String media_id) throws WxErrorException { |
|
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/media/get"; |
|
|
|
return execute( |
|
|
|
new MediaDownloadRequestExecutor( |
|
|
|
this.configStorage.getTmpDirFile()), |
|
|
|
url, "media_id=" + media_id); |
|
|
|
new MediaDownloadRequestExecutor( |
|
|
|
this.configStorage.getTmpDirFile()), |
|
|
|
url, "media_id=" + media_id); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@@ -254,9 +251,9 @@ this.configStorage.getTmpDirFile()), |
|
|
|
public Integer departCreate(WxCpDepart depart) throws WxErrorException { |
|
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/department/create"; |
|
|
|
String responseContent = execute( |
|
|
|
new SimplePostRequestExecutor(), |
|
|
|
url, |
|
|
|
depart.toJson()); |
|
|
|
new SimplePostRequestExecutor(), |
|
|
|
url, |
|
|
|
depart.toJson()); |
|
|
|
JsonElement tmpJsonElement = new JsonParser().parse(responseContent); |
|
|
|
return GsonHelper.getAsInteger(tmpJsonElement.getAsJsonObject().get("id")); |
|
|
|
} |
|
|
@@ -283,11 +280,11 @@ this.configStorage.getTmpDirFile()), |
|
|
|
*/ |
|
|
|
JsonElement tmpJsonElement = new JsonParser().parse(responseContent); |
|
|
|
return WxCpGsonBuilder.INSTANCE.create() |
|
|
|
.fromJson( |
|
|
|
tmpJsonElement.getAsJsonObject().get("department"), |
|
|
|
new TypeToken<List<WxCpDepart>>() { |
|
|
|
}.getType() |
|
|
|
); |
|
|
|
.fromJson( |
|
|
|
tmpJsonElement.getAsJsonObject().get("department"), |
|
|
|
new TypeToken<List<WxCpDepart>>() { |
|
|
|
}.getType() |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
@@ -313,8 +310,8 @@ this.configStorage.getTmpDirFile()), |
|
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/user/batchdelete"; |
|
|
|
JsonObject jsonObject = new JsonObject(); |
|
|
|
JsonArray jsonArray = new JsonArray(); |
|
|
|
for (int i = 0; i < userids.length; i++) { |
|
|
|
jsonArray.add(new JsonPrimitive(userids[i])); |
|
|
|
for (String userid : userids) { |
|
|
|
jsonArray.add(new JsonPrimitive(userid)); |
|
|
|
} |
|
|
|
jsonObject.add("useridlist", jsonArray); |
|
|
|
post(url, jsonObject.toString()); |
|
|
@@ -343,11 +340,11 @@ this.configStorage.getTmpDirFile()), |
|
|
|
String responseContent = get(url, params); |
|
|
|
JsonElement tmpJsonElement = new JsonParser().parse(responseContent); |
|
|
|
return WxCpGsonBuilder.INSTANCE.create() |
|
|
|
.fromJson( |
|
|
|
tmpJsonElement.getAsJsonObject().get("userlist"), |
|
|
|
new TypeToken<List<WxCpUser>>() { |
|
|
|
}.getType() |
|
|
|
); |
|
|
|
.fromJson( |
|
|
|
tmpJsonElement.getAsJsonObject().get("userlist"), |
|
|
|
new TypeToken<List<WxCpUser>>() { |
|
|
|
}.getType() |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
@@ -366,11 +363,11 @@ this.configStorage.getTmpDirFile()), |
|
|
|
String responseContent = get(url, params); |
|
|
|
JsonElement tmpJsonElement = new JsonParser().parse(responseContent); |
|
|
|
return WxCpGsonBuilder.INSTANCE.create() |
|
|
|
.fromJson( |
|
|
|
tmpJsonElement.getAsJsonObject().get("userlist"), |
|
|
|
new TypeToken<List<WxCpUser>>() { |
|
|
|
}.getType() |
|
|
|
); |
|
|
|
.fromJson( |
|
|
|
tmpJsonElement.getAsJsonObject().get("userlist"), |
|
|
|
new TypeToken<List<WxCpUser>>() { |
|
|
|
}.getType() |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
@@ -404,11 +401,11 @@ this.configStorage.getTmpDirFile()), |
|
|
|
String responseContent = get(url, null); |
|
|
|
JsonElement tmpJsonElement = new JsonParser().parse(responseContent); |
|
|
|
return WxCpGsonBuilder.INSTANCE.create() |
|
|
|
.fromJson( |
|
|
|
tmpJsonElement.getAsJsonObject().get("taglist"), |
|
|
|
new TypeToken<List<WxCpTag>>() { |
|
|
|
}.getType() |
|
|
|
); |
|
|
|
.fromJson( |
|
|
|
tmpJsonElement.getAsJsonObject().get("taglist"), |
|
|
|
new TypeToken<List<WxCpTag>>() { |
|
|
|
}.getType() |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
@@ -417,11 +414,11 @@ this.configStorage.getTmpDirFile()), |
|
|
|
String responseContent = get(url, null); |
|
|
|
JsonElement tmpJsonElement = new JsonParser().parse(responseContent); |
|
|
|
return WxCpGsonBuilder.INSTANCE.create() |
|
|
|
.fromJson( |
|
|
|
tmpJsonElement.getAsJsonObject().get("userlist"), |
|
|
|
new TypeToken<List<WxCpUser>>() { |
|
|
|
}.getType() |
|
|
|
); |
|
|
|
.fromJson( |
|
|
|
tmpJsonElement.getAsJsonObject().get("userlist"), |
|
|
|
new TypeToken<List<WxCpUser>>() { |
|
|
|
}.getType() |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
@@ -460,14 +457,14 @@ this.configStorage.getTmpDirFile()), |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public String oauth2buildAuthorizationUrl(String state) { |
|
|
|
return this.oauth2buildAuthorizationUrl( |
|
|
|
this.configStorage.getOauth2redirectUri(), |
|
|
|
state |
|
|
|
); |
|
|
|
} |
|
|
|
public String oauth2buildAuthorizationUrl(String state) { |
|
|
|
return this.oauth2buildAuthorizationUrl( |
|
|
|
this.configStorage.getOauth2redirectUri(), |
|
|
|
state |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public String oauth2buildAuthorizationUrl(String redirectUri, String state) { |
|
|
|
String url = "https://open.weixin.qq.com/connect/oauth2/authorize?"; |
|
|
|
url += "appid=" + this.configStorage.getCorpId(); |
|
|
@@ -489,8 +486,8 @@ this.configStorage.getOauth2redirectUri(), |
|
|
|
@Override |
|
|
|
public String[] oauth2getUserInfo(Integer agentId, String code) throws WxErrorException { |
|
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?" |
|
|
|
+ "code=" + code |
|
|
|
+ "&agentid=" + agentId; |
|
|
|
+ "code=" + code |
|
|
|
+ "&agentid=" + agentId; |
|
|
|
String responseText = get(url, null); |
|
|
|
JsonElement je = new JsonParser().parse(responseText); |
|
|
|
JsonObject jo = je.getAsJsonObject(); |
|
|
@@ -544,14 +541,14 @@ this.configStorage.getOauth2redirectUri(), |
|
|
|
return executeInternal(executor, uri, data); |
|
|
|
} catch (WxErrorException e) { |
|
|
|
WxError error = e.getError(); |
|
|
|
/** |
|
|
|
/* |
|
|
|
* -1 系统繁忙, 1000ms后重试 |
|
|
|
*/ |
|
|
|
if (error.getErrorCode() == -1) { |
|
|
|
int sleepMillis = this.retrySleepMillis * (1 << retryTimes); |
|
|
|
try { |
|
|
|
this.log.debug("微信系统繁忙,{}ms 后重试(第{}次)", sleepMillis, |
|
|
|
retryTimes + 1); |
|
|
|
retryTimes + 1); |
|
|
|
Thread.sleep(sleepMillis); |
|
|
|
} catch (InterruptedException e1) { |
|
|
|
throw new RuntimeException(e1); |
|
|
@@ -566,7 +563,7 @@ this.configStorage.getOauth2redirectUri(), |
|
|
|
} |
|
|
|
|
|
|
|
protected synchronized <T, E> T executeInternal(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException { |
|
|
|
if (uri.indexOf("access_token=") != -1) { |
|
|
|
if (uri.contains("access_token=")) { |
|
|
|
throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); |
|
|
|
} |
|
|
|
String accessToken = getAccessToken(false); |
|
|
@@ -576,7 +573,7 @@ this.configStorage.getOauth2redirectUri(), |
|
|
|
|
|
|
|
try { |
|
|
|
return executor.execute(getHttpclient(), this.httpProxy, |
|
|
|
uriWithAccessToken, data); |
|
|
|
uriWithAccessToken, data); |
|
|
|
} catch (WxErrorException e) { |
|
|
|
WxError error = e.getError(); |
|
|
|
/* |
|
|
@@ -593,8 +590,6 @@ this.configStorage.getOauth2redirectUri(), |
|
|
|
throw new WxErrorException(error); |
|
|
|
} |
|
|
|
return null; |
|
|
|
} catch (ClientProtocolException e) { |
|
|
|
throw new RuntimeException(e); |
|
|
|
} catch (IOException e) { |
|
|
|
throw new RuntimeException(e); |
|
|
|
} |
|
|
@@ -608,15 +603,15 @@ this.configStorage.getOauth2redirectUri(), |
|
|
|
public void setWxCpConfigStorage(WxCpConfigStorage wxConfigProvider) { |
|
|
|
this.configStorage = wxConfigProvider; |
|
|
|
ApacheHttpClientBuilder apacheHttpClientBuilder = this.configStorage |
|
|
|
.getApacheHttpClientBuilder(); |
|
|
|
.getApacheHttpClientBuilder(); |
|
|
|
if (null == apacheHttpClientBuilder) { |
|
|
|
apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.get(); |
|
|
|
} |
|
|
|
|
|
|
|
apacheHttpClientBuilder.httpProxyHost(this.configStorage.getHttpProxyHost()) |
|
|
|
.httpProxyPort(this.configStorage.getHttpProxyPort()) |
|
|
|
.httpProxyUsername(this.configStorage.getHttpProxyUsername()) |
|
|
|
.httpProxyPassword(this.configStorage.getHttpProxyPassword()); |
|
|
|
.httpProxyPort(this.configStorage.getHttpProxyPort()) |
|
|
|
.httpProxyUsername(this.configStorage.getHttpProxyUsername()) |
|
|
|
.httpProxyPassword(this.configStorage.getHttpProxyPassword()); |
|
|
|
|
|
|
|
if (this.configStorage.getHttpProxyHost() != null && this.configStorage.getHttpProxyPort() > 0) { |
|
|
|
this.httpProxy = new HttpHost(this.configStorage.getHttpProxyHost(), this.configStorage.getHttpProxyPort()); |
|
|
|