微信access_token存储与更新

/**
 * 
 * @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;
	}
}



微信access_token存储与更新,布布扣,bubuko.com

微信access_token存储与更新

上一篇:企业微信开发 Vue wxConfig agentConfig 授权


下一篇:Web客户端安全性最佳实践(转)