Files
weixin-java-tools/src/main/java/chanjarster/weixin/api/WxServiceImpl.java

174 lines
5.7 KiB
Java
Raw Normal View History

2014-08-21 21:19:24 +08:00
package chanjarster.weixin.api;
2014-08-18 16:48:20 +08:00
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
2014-08-21 21:19:24 +08:00
import chanjarster.weixin.bean.WxAccessToken;
import chanjarster.weixin.bean.WxCustomMessage;
import chanjarster.weixin.bean.WxError;
import chanjarster.weixin.bean.WxMenu;
2014-08-18 16:48:20 +08:00
import chanjarster.weixin.exception.WxErrorException;
public class WxServiceImpl implements WxService {
/**
* 全局的是否正在刷新Access Token的flag
* true: 正在刷新
* false: 没有刷新
*/
protected static final AtomicBoolean GLOBAL_ACCESS_TOKEN_REFRESH_FLAG = new AtomicBoolean(false);
protected static final CloseableHttpClient httpclient = HttpClients.createDefault();
protected static final Charset UTF8 = Charset.forName("UTF-8");
protected WxConfigProvider wxConfigProvider;
public void refreshAccessToken() throws WxErrorException {
if (!GLOBAL_ACCESS_TOKEN_REFRESH_FLAG.getAndSet(true)) {
try {
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential"
+ "&appid=" + wxConfigProvider.getAppId()
+ "&secret=" + wxConfigProvider.getSecret()
;
try {
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response = httpclient.execute(httpGet);
String resultContent = new BasicResponseHandler().handleResponse(response);
WxAccessToken accessToken = WxAccessToken.fromJson(resultContent);
wxConfigProvider.updateAccessToken(accessToken.getAccess_token(), accessToken.getExpires_in());
} 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) {
}
}
// 刷新完毕了,就没他什么事儿了
}
}
/**
* 发送客服消息
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=发送客服消息
* @param message
* @throws WxErrorException
*/
public String sendCustomMessage(WxCustomMessage message) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send";
return post(url, message.toJson());
}
protected String post(String uri, String data) throws WxErrorException {
return execute("POST", uri, data);
}
protected String get(String uri, String data) throws WxErrorException {
return execute("GET", uri, data);
}
/**
* 向微信端发送请求在这里执行的策略是当发生access_token过期时才去刷新然后重新执行请求而不是全局定时请求
* @param request
* @return 微信服务端返回的结果
* @throws WxErrorException
*/
protected String execute(String method, String uri, String data) throws WxErrorException {
if (StringUtils.isBlank(wxConfigProvider.getAccessToken())) {
refreshAccessToken();
}
String accessToken = wxConfigProvider.getAccessToken();
String uriWithAccessToken = uri;
uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken;
try {
String resultContent = null;
if ("POST".equals(method)) {
HttpPost httpPost = new HttpPost(uriWithAccessToken);
StringEntity entity = new StringEntity(data, UTF8);
httpPost.setEntity(entity);
CloseableHttpResponse response = httpclient.execute(httpPost);
resultContent = new BasicResponseHandler().handleResponse(response);
} else if ("GET".equals(method)) {
HttpGet httpGet = new HttpGet(uriWithAccessToken);
CloseableHttpResponse response = httpclient.execute(httpGet);
resultContent = new BasicResponseHandler().handleResponse(response);
}
WxError error = WxError.fromJson(resultContent);
/*
* 关于微信返回错误码 详情请看 http://mp.weixin.qq.com/wiki/index.php?title=全局返回码说明
* 40001 微信图片不对
* 42001 access_token超时
*/
if (error.getErrcode() == 42001 || error.getErrcode() == 40001) {
refreshAccessToken();
return execute(method, uri, data);
}
if (error.getErrcode() != 0) {
throw new WxErrorException(error);
}
return resultContent;
} catch (ClientProtocolException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
*
* @param menu
* @throws WxErrorException
*/
public String createMenu(WxMenu menu) throws WxErrorException {
// TODO
return null;
}
/**
*
* @throws WxErrorException
*/
public String deleteMenu() throws WxErrorException {
// TODO
return null;
}
/**
*
* @return
* @throws WxErrorException
*/
public WxMenu getMenu() throws WxErrorException {
// TODO
return null;
}
public void setWxConfigProvider(WxConfigProvider wxConfigProvider) {
this.wxConfigProvider = wxConfigProvider;
}
}