/** * * @author xuyw * @email xyw10000@163.com * @date 2014-06-12 */
access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。
正常情况下access_token有效期为7200秒,重复获取将导致上次获取的access_token失效。由于获取access_token的api调用次数非常有限,建议开发者全局存储与更新access_token,频繁刷新access_token会导致api调用受限,影响自身业务。
access_token调用频率一天为2000次,如果简单的使用自定义菜单完全够用.只是微信推出多客服后,如果频繁发送客服消息,将有可能不够用
那么怎么延长,
1 使用定时器刷新
2 存储到数据库
使用定时器个人觉得,如果是个人开发影响不大.若是第三方服务平台的话,帐号一多,是不是带来很大的压力呢?
若是第三方服务平台,我更推荐使用数据库。公众平台的开发接口的access_token长度将增长,其存储至少要保留512个字符空间
使用数据库的话,大概思路就是这样的。第一次使用将其access_token存储起来,下次需要access_token则将其查出。若是失效则,重新创建并更新数据库.若是没有失效,则直接使用。
附上我的小小设计,不足之处还望指出
数据库设计
CREATE TABLE `wx_access_token` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `access_token` varchar(600) NOT NULL COMMENT 'access_token凭证', `expires_in` bigint(20) NOT NULL COMMENT '凭证有效时间,单位:秒', `create_time` bigint(20) NOT NULL COMMENT '创建时间距离当前时间毫秒数', `userid` varchar(128) NOT NULL COMMENT 'userid', `create_date` varchar(25) NOT NULL COMMENT '创建时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
核心代码
省略第一次调用保存代码,相信大家都会
以后调用代码,先查询
// 存在 String _token = map.get("access_token") + ""; String expires_in = map.get("expires_in") + ""; String create_time = map.get("create_time") + ""; int _in = Integer.parseInt(expires_in); long _time = Long.parseLong(create_time); if ((System.currentTimeMillis()-_time)/1000 < _in) {// 有效 //System.out.println("无须创建"); accessToken = new AccessToken(); accessToken.setExpiresIn(_in); accessToken.setToken(_token); } else {// 无效 //System.out.println("无效重新创建"); Map map2 = new HashMap(); map2.put("create_time", System.currentTimeMillis()); map2.put("userid", uid); accessToken = WxUtil.getAccessToken(appid, appsecret); map2.put("access_token", accessToken.getToken()); map2.put("expires_in", accessToken.getExpiresIn()); wxDao.saveAccessToken(map2);//更新数据库 }
public static AccessToken getAccessToken(String appid, String appsecret) { AccessToken accessToken = null; String requestUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appid+"&secret="+appsecret; JSONObject jsonObject = httpRequest(requestUrl, "GET", null); // 如果请求成功 if (null != jsonObject) { try { accessToken = new AccessToken(); accessToken.setToken(jsonObject.getString("access_token")); accessToken.setExpiresIn(jsonObject.getInt("expires_in")); } catch (JSONException e) { accessToken = null; // 获取token失败 log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg")); } } return accessToken; }
public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) { JSONObject jsonObject = null; StringBuffer buffer = new StringBuffer(); try { // 创建SSLContext对象,并使用我们指定的信任管理器初始化 TrustManager[] tm = { new MyX509TrustManager() }; SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE"); sslContext.init(null, tm, new java.security.SecureRandom()); // 从上述SSLContext对象中得到SSLSocketFactory对象 SSLSocketFactory ssf = sslContext.getSocketFactory(); URL url = new URL(requestUrl); HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection(); httpUrlConn.setSSLSocketFactory(ssf); httpUrlConn.setDoOutput(true); httpUrlConn.setDoInput(true); httpUrlConn.setUseCaches(false); // 设置请求方式(GET/POST) httpUrlConn.setRequestMethod(requestMethod); if ("GET".equalsIgnoreCase(requestMethod)) httpUrlConn.connect(); // 当有数据需要提交时 if (null != outputStr) { OutputStream outputStream = httpUrlConn.getOutputStream(); // 注意编码格式,防止中文乱码 outputStream.write(outputStr.getBytes("UTF-8")); outputStream.close(); } // 将返回的输入流转换成字符串 InputStream inputStream = httpUrlConn.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str = null; while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } bufferedReader.close(); inputStreamReader.close(); // 释放资源 inputStream.close(); inputStream = null; httpUrlConn.disconnect(); jsonObject = JSONObject.fromObject(buffer.toString()); } catch (ConnectException ce) { log.error("Weixin server connection timed out."); } catch (Exception e) { log.error("https request error:{}", e); } return jsonObject; }
public class MyX509TrustManager implements X509TrustManager { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } }
public class AccessToken { // 获取到的凭证 private String token; // 凭证有效时间,单位:秒 private int expiresIn; public String getToken() { return token; } public void setToken(String token) { this.token = token; } public int getExpiresIn() { return expiresIn; } public void setExpiresIn(int expiresIn) { this.expiresIn = expiresIn; } }