微信Access Token默认缓存是2小时,但是需要特别强调,微信服务号和微信企业号缓存并不相同。
(1)微信公众号号:每次Http请求Access Token 系统会返回不同的Token,并附带超时时间,默认是2小时。
(2)微信企业号:每次请求Access Token,默认有效期为2个小时,在这2个小时内获取的Access Token是一样的。
对于微信公众号,我们通过txt存储每次获取的Access Token。换句话说,当缓存后,再次获取Access时,直接从txt里获取。代码如下:
private static string wxml = HttpContext.Current.Server.MapPath("~/app_data/access_token.txt"); public static string GetAccessToken() { string json = ""; DateTime dt = DateTime.Now; if (!System.IO.File.Exists(wxml)) {
//txt不存在,创建 json = GetTokenFromURL(); } else { json = System.IO.File.ReadAllText(wxml); } //获取最后txt写入的时间 dt = System.IO.File.GetLastWriteTime(wxml); DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(AccessToken)); var mStream = new MemoryStream(Encoding.Default.GetBytes(json)); AccessToken token = (AccessToken)serializer.ReadObject(mStream); //_expires_in默认为 7200秒,也就是2小时,也就是access_token2小时即失效。为了保证可靠性,系统让access_tokey 1.5小时失效。 int minRefreshTimeSpan = 1800 - int.Parse(token.expires_in); // -5400秒 if (minRefreshTimeSpan > 0) { minRefreshTimeSpan = -1800; } if (dt < DateTime.Now.AddSeconds(minRefreshTimeSpan)) { GetTokenFromURL(); json = System.IO.File.ReadAllText(wxml); serializer = new DataContractJsonSerializer(typeof(AccessToken)); mStream = new MemoryStream(Encoding.Default.GetBytes(json)); token = (AccessToken)serializer.ReadObject(mStream); } return token.access_token; } private static string GetTokenFromURL() { string appid = AppID; string secret = AppSecret; string strUrl = Access_Token_URL; string json = HttpUtility.SendGetHttpRequest(strUrl); System.IO.File.WriteAllText(wxml, json); return json; }
(2)对于企业微信AccessToken,可以使用单列模式存储
public class TokenSingleton { //缓存accessToken 的Map ,map中包含 一个accessToken 和 缓存的时间戳 //当然也可以分开成两个属性咯 public final static String weixin_jssdk_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi"; private Map<String, String> map = new HashMap<>(); private TokenSingleton() { } private static TokenSingleton single = null; // 静态工厂方法 public static TokenSingleton getInstance() { if (single == null) { single = new TokenSingleton(); } return single; } public Map<String, String> getMap(WeixinAccountServiceI weixinAccountService) { String time = map.get("time"); String accessToken = map.get("access_token"); Long nowDate = new Date().getTime(); if (accessToken != null && time != null && nowDate - Long.parseLong(time) < 3000 * 1000) { // result = accessToken; System.out.println("accessToken存在,且没有超时 , 返回单例"); } else { System.out.println("accessToken 超时 , 或者不存在 , 重新获取"); System.out.println("weixinAccountService : " + weixinAccountService); String access_token=weixinAccountService.getNewAccessToken("gh_ab6e37102f85"); //"这里是直接调用微信的API去直接获取 accessToken 和Jsapi_ticket 获取"; String jsapi_token = getJsapiToken(access_token); //"获取jsapi_token"; map.put("time", nowDate + ""); map.put("access_token", access_token); map.put("jsapi_token", jsapi_token); // result = access_token; } return map; } public void setMap(Map<String, String> map) { this.map = map; } public static TokenSingleton getSingle() { return single; } public static void setSingle(TokenSingleton single) { TokenSingleton.single = single; } public String getJsapiToken(String accessToken){ //获取jsapi_ticket System.out.println("获取jsapi_ticket"); String jsapi_Url = weixin_jssdk_ticket_url.replace("ACCESS_TOKEN", accessToken); String jsapi_ticket = null; net.sf.json.JSONObject jsonObject = WeixinUtil.httpRequest(jsapi_Url, "GET", null); System.out.println("请求返回数据: " + jsonObject); // 如果请求成功 if (null != jsonObject) { System.out.println("jsapi_ticket : "+jsonObject); jsapi_ticket=jsonObject.getString("ticket"); } return jsapi_ticket; } }