|  |  | @@ -46,11 +46,9 @@ import java.util.concurrent.atomic.AtomicBoolean; | 
		
	
		
			
			|  |  |  | public class WxCpServiceImpl implements WxCpService { | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | /** | 
		
	
		
			
			|  |  |  | * 全局的是否正在刷新Access Token的flag | 
		
	
		
			
			|  |  |  | * true: 正在刷新 | 
		
	
		
			
			|  |  |  | * false: 没有刷新 | 
		
	
		
			
			|  |  |  | * 全局的是否正在刷新access token的锁 | 
		
	
		
			
			|  |  |  | */ | 
		
	
		
			
			|  |  |  | protected static final AtomicBoolean GLOBAL_ACCESS_TOKEN_REFRESH_FLAG = new AtomicBoolean(false); | 
		
	
		
			
			|  |  |  | protected static final Object GLOBAL_ACCESS_TOKEN_REFRESH_LOCK = new Object(); | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | protected WxCpConfigStorage wxCpConfigStorage; | 
		
	
		
			
			|  |  |  | 
 | 
		
	
	
		
			
				|  |  | @@ -73,45 +71,37 @@ public class WxCpServiceImpl implements WxCpService { | 
		
	
		
			
			|  |  |  | execute(new SimpleGetRequestExecutor(), url, null); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | public void accessTokenRefresh() throws WxErrorException { | 
		
	
		
			
			|  |  |  | if (!GLOBAL_ACCESS_TOKEN_REFRESH_FLAG.getAndSet(true)) { | 
		
	
		
			
			|  |  |  | try { | 
		
	
		
			
			|  |  |  | String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?" | 
		
	
		
			
			|  |  |  | + "&corpid=" + wxCpConfigStorage.getCorpId() | 
		
	
		
			
			|  |  |  | + "&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); | 
		
	
		
			
			|  |  |  | if (error.getErrorCode() != 0) { | 
		
	
		
			
			|  |  |  | throw new WxErrorException(error); | 
		
	
		
			
			|  |  |  | public String getAccessToken() throws WxErrorException { | 
		
	
		
			
			|  |  |  | if (wxCpConfigStorage.isAccessTokenExpired()) { | 
		
	
		
			
			|  |  |  | synchronized (GLOBAL_ACCESS_TOKEN_REFRESH_LOCK) { | 
		
	
		
			
			|  |  |  | if (wxCpConfigStorage.isAccessTokenExpired()) { | 
		
	
		
			
			|  |  |  | String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?" | 
		
	
		
			
			|  |  |  | + "&corpid=" + wxCpConfigStorage.getCorpId() | 
		
	
		
			
			|  |  |  | + "&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); | 
		
	
		
			
			|  |  |  | if (error.getErrorCode() != 0) { | 
		
	
		
			
			|  |  |  | throw new WxErrorException(error); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | WxAccessToken accessToken = WxAccessToken.fromJson(resultContent); | 
		
	
		
			
			|  |  |  | wxCpConfigStorage.updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn()); | 
		
	
		
			
			|  |  |  | } catch (ClientProtocolException e) { | 
		
	
		
			
			|  |  |  | throw new RuntimeException(e); | 
		
	
		
			
			|  |  |  | } catch (IOException e) { | 
		
	
		
			
			|  |  |  | throw new RuntimeException(e); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | WxAccessToken accessToken = WxAccessToken.fromJson(resultContent); | 
		
	
		
			
			|  |  |  | wxCpConfigStorage.updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn()); | 
		
	
		
			
			|  |  |  | } catch (ClientProtocolException e) { | 
		
	
		
			
			|  |  |  | throw new RuntimeException(e); | 
		
	
		
			
			|  |  |  | } catch (IOException e) { | 
		
	
		
			
			|  |  |  | throw new RuntimeException(e); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } finally { | 
		
	
		
			
			|  |  |  | GLOBAL_ACCESS_TOKEN_REFRESH_FLAG.set(false); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } else { | 
		
	
		
			
			|  |  |  | // 每隔100ms检查一下是否刷新完毕了 | 
		
	
		
			
			|  |  |  | while (GLOBAL_ACCESS_TOKEN_REFRESH_FLAG.get()) { | 
		
	
		
			
			|  |  |  | try { | 
		
	
		
			
			|  |  |  | Thread.sleep(100); | 
		
	
		
			
			|  |  |  | } catch (InterruptedException e) { | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | // 刷新完毕了,就没他什么事儿了 | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | return wxCpConfigStorage.getAccessToken(); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | public void messageSend(WxCpMessage message) throws WxErrorException { | 
		
	
	
		
			
				|  |  | @@ -369,10 +359,7 @@ public class WxCpServiceImpl implements WxCpService { | 
		
	
		
			
			|  |  |  | * @throws WxErrorException | 
		
	
		
			
			|  |  |  | */ | 
		
	
		
			
			|  |  |  | public <T, E> T execute(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException { | 
		
	
		
			
			|  |  |  | if (StringUtils.isBlank(wxCpConfigStorage.getAccessToken())) { | 
		
	
		
			
			|  |  |  | accessTokenRefresh(); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | String accessToken = wxCpConfigStorage.getAccessToken(); | 
		
	
		
			
			|  |  |  | String accessToken = getAccessToken(); | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | String uriWithAccessToken = uri; | 
		
	
		
			
			|  |  |  | uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken; | 
		
	
	
		
			
				|  |  | @@ -387,7 +374,8 @@ public class WxCpServiceImpl implements WxCpService { | 
		
	
		
			
			|  |  |  | * 42001 access_token超时 | 
		
	
		
			
			|  |  |  | */ | 
		
	
		
			
			|  |  |  | if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) { | 
		
	
		
			
			|  |  |  | accessTokenRefresh(); | 
		
	
		
			
			|  |  |  | // 强制设置wxCpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token | 
		
	
		
			
			|  |  |  | wxCpConfigStorage.expireAccessToken(); | 
		
	
		
			
			|  |  |  | return execute(executor, uri, data); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | /** | 
		
	
	
		
			
				|  |  | 
 |