微信开发-access token 过期失效解决方案
起因:因为access_token的重要性,开发过微信的都知道,但是他有自己的生命周期,官方解释为:有效期为7200秒,一天调用2000次。流量一高,就over了,没办法,龙哥不帮我们解决问题,我们就要自己解决,不能等死。
解决思路很简单:建立公共access token数据,有效期内不重新创建access_token。
解决方案:
1、微信类库:有效期内直接读取access token数据文件中的json数据,过期失效,重新获取并创建新的access token数据文件
2、数据文件:存放有效的access token数据,具体有:access_token.json和jsapi_ticket.json
核心代码如下:
index: wxjssdk.cs
===================================================================
--- wxjssdk.cs (revision 0)
+++ wxjssdk.cs (revision 1)
@@ -0,0 +1,209 @@
+using system;
+using system.collections.generic;
+using system.web;
+using system.io;
+using system.security.cryptography;
+using system.runtime.serialization.json;
+using system.runtime.serialization;
+using system.net;
+using system.runtime.serialization.formatters.binary;
+using system.text;
+
+namespace jr.common
+{
+ public class wxjssdk
+ {
+ private string appid;
+ private string appsecret;
+
+
+ public wxjssdk(string appid, string appsecret)
+ {
+ this.appid = appid;
+ this.appsecret = appsecret;
+ }
+
+
+
+ //得到数据包,返回使用页面
+ public system.collections.hashtable getsignpackage()
+ {
+ string jsapiticket = getjsapiticket();
+ string url = httpcontext.current.request.url.tostring(); //"http://$_server[http_host]$_server[request_uri]";
+ string timestamp = convert.tostring(convertdatetimeint(datetime.now));
+ string noncestr = createnoncestr();
+ // 这里参数的顺序要按照 key 值 ascii 码升序排序
+ string rawstring = "jsapi_ticket=" + jsapiticket + "&noncestr=" + noncestr + "×tamp=" + timestamp + "&url=" + url + "";
+ string signature = sha1_hash(rawstring);
+ var signpackage = new system.collections.hashtable();
+ signpackage.add("appid", appid);
+ signpackage.add("noncestr", noncestr);
+ signpackage.add("timestamp", timestamp);
+ signpackage.add("url", url);
+ signpackage.add("signature", signature);
+ signpackage.add("rawstring", rawstring);
+ return signpackage;
+ }
+
+
+ //创建随机字符串
+ private string createnoncestr()
+ {
+ int length = 16;
+ string chars = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789";
+ string str = "";
+ var rad = new random();
+ for (int i = 0; i < length; i++)
+ {
+ str += chars.substring(rad.next(0, chars.length - 1), 1);
+ }
+ return str;
+ }
+
+
+ //得到ticket 如果文件里时间 超时则重新获取
+ private string getjsapiticket()
+ {
+ string ticket = "";
+ // jsapi_ticket 应该全局存储与更新,以下代码以写入到文件中做示例
+ string path = httpcontext.current.server.mappath(@"/log/jssdk/jsapi_ticket.json");
+ if (!file.exists(path))
+ {
+ file.create(path).close();
+ }
+ streamreader sr = new streamreader(path, system.text.encoding.default);
+ string filecontent = sr.readtoend();
+ commonjsonmodel jsonmodel = null;
+ if (!string.isnullorempty(filecontent))
+ {
+ jsonmodel = new commonjsonmodel(filecontent);
+ }
+ sr.close();
+ sr.dispose();
+ if (jsonmodel == null || int.parse(jsonmodel.getvalue("expires_in")) < convertdatetimeint(datetime.now))
+ {
+ string accesstoken = getaccesstoken();
+ string url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=" + accesstoken;
+ jsonmodel = new commonjsonmodel(httpget(url));
+ ticket = jsonmodel.getvalue("ticket");
+ if (ticket != "")
+ {
+ string json = "{\"ticket\":\"" + ticket + "\",\"expires_in\":" + (convertdatetimeint(datetime.now) + 7000) + "}";
+ streamwritermetod(json, path);
+ }
+ }
+ else
+ {
+ ticket = jsonmodel.getvalue("ticket");
+ }
+ return ticket;
+ }
+
+
+ //得到accesstoken 如果文件里时间 超时则重新获取
+ private string getaccesstoken()
+ {
+ // access_token 应该全局存储与更新,以下代码以写入到文件中做示例
+ string access_token = "";
+ string path = httpcontext.current.server.mappath(@"/log/jssdk/access_token.json");
+ if (!file.exists(path))
+ {
+ file.create(path).close();
+ }
+ streamreader sr = new streamreader(path, system.text.encoding.default);
+ string filecontent = sr.readtoend();
+ commonjsonmodel jsonmodel = null;
+ if (!string.isnullorempty(filecontent))
+ {
+ jsonmodel = new commonjsonmodel(filecontent);
+ }
+ sr.close();
+ sr.dispose();
+ if (jsonmodel == null || int.parse(jsonmodel.getvalue("expires_in")) < convertdatetimeint(datetime.now))
+ {
+ string url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid +
+ "&secret=" + appsecret + "";
+ jsonmodel = new commonjsonmodel(httpget(url));
+ access_token = jsonmodel.getvalue("access_token");
+ if (access_token != "")
+ {
+ string json = "{\"access_token\":\"" + access_token + "\",\"expires_in\":" + (convertdatetimeint(datetime.now) + 7000) + "}";
+ streamwritermetod(json, path);
+ }
+ }
+ else
+ {
+ access_token = jsonmodel.getvalue("access_token");
+ }
+ return access_token;
+ }
+
+
+ //发起一个http请球,返回值
+ private string httpget(string url)
+ {
+ try
+ {
+ var mywebclient = new webclient();
+ mywebclient.credentials = credentialcache.defaultcredentials; //获取或设置用于向internet资源的请求进行身份验证的网络凭据
+ byte[] pagedata = mywebclient.downloaddata(url); //从指定网站下载数据
+ string pagehtml = system.text.encoding.default.getstring(pagedata);//如果获取网站页面采用的是gb2312,则使用这句
+ //string pagehtml = encoding.utf8.getstring(pagedata); //如果获取网站页面采用的是utf-8,则使用这句
+ return pagehtml;
+ }
+ catch (webexception webex)
+ {
+ console.writeline(webex.message.tostring());
+ return null;
+ }
+ }
+
+
+ //sha1哈希加密算法
+ private string sha1_hash(string str_sha1_in)
+ {
+ sha1 sha1 = new sha1cryptoserviceprovider();
+ byte[] bytes_sha1_in = system.text.utf8encoding.default.getbytes(str_sha1_in);
+ byte[] bytes_sha1_out = sha1.computehash(bytes_sha1_in);
+ string str_sha1_out = bitconverter.tostring(bytes_sha1_out);
+ str_sha1_out = str_sha1_out.replace("-", "").tolower();
+ return str_sha1_out;
+ }
+
+
+ /// <summary>
+ /// streamwriter写入文件方法
+ /// </summary>
+ private void streamwritermetod(string str, string patch)
+ {
+ filestream stream = new filestream(patch, filemode.openorcreate, fileaccess.write, fileshare.delete | fileshare.readwrite);
+ streamwriter writer = new streamwriter(stream);
+ writer.writeline(str);
+ stream.flush();
+ writer.close();
+ stream.close();
+ stream.dispose();
+ writer.dispose();
+ }
+
+
+
+
+ /// <summary>
+ /// 将c# datetime时间格式转换为unix时间戳格式
+ /// </summary>
+ /// <param name="time">时间</param>
+ /// <returns>double</returns>
+ private int convertdatetimeint(system.datetime time)
+ {
+ int intresult = 0;
+ system.datetime starttime = timezone.currenttimezone.tolocaltime(new system.datetime(1970, 1, 1));
+ intresult = convert.toint32((time - starttime).totalseconds);
+ return intresult;
+ }
+
+
+ }
+
+
+}
access_token.json
{"access_token":"4h14bvcuraxxxxxxxxxxxxwelu-zketabyqsokfjshzdc3xowc-m43wdw2hjzxekng2nc7ijuhydnt5pqrdy7hcoau4lmuapoysiqhdw9ka","expire_time":1428599121}
access_token.json
{"jsapi_ticket":"bxldikrxvbtpdhsm05e5u1wgoccccccccccccccccccccccccccccc11ffzysiqbxzn0sdgn6dnksnt2q","expire_time":1428599122}
更多微信开发-access token 过期失效解决方案 。