天天看點

(二)擷取Access_token

擷取access_token

access_token是公衆号的全局唯一接口調用憑據,公衆号調用各接口時都需使用access_token,開發者需要進行妥善儲存。

access_token的存儲至少要保留512個字元空間。

access_token的有效期目前為2個小時,需定時重新整理,重複擷取将導緻上次擷取的access_token失效。

公衆平台的API調用所需的access_token的使用及生成方式說明:

1、建議公衆号開發者使用中控伺服器統一擷取和重新整理access_token,其他業務邏輯伺服器所使用的access_token均來自于該中控伺服器,不應該各自去重新整理,否則容易造成沖突,導緻access_token覆寫而影響業務;

2、目前access_token的有效期通過傳回的expire_in來傳達,目前是7200秒之内的值。中控伺服器需要根據這個有效時間提前去重新整理新access_token。在重新整理過程中,中控伺服器可對外繼續輸出的老access_token,此時公衆平台背景會保證在5分鐘内,新老access_token都可用,這保證了第三方業務的平滑過渡;

3、access_token的有效時間可能會在未來有調整,是以中控伺服器不僅需要内部定時主動重新整理,還需要提供被動重新整理access_token的接口,這樣便于業務伺服器在API調用獲知access_token已逾時的情況下,可以觸發access_token的重新整理流程。

公衆号和小程式均可以使用AppID和AppSecret調用本接口來擷取access_token。AppID和AppSecret可在“微信公衆平台-開發-基本配置”頁中獲得(需要已經成為開發者,且帳号沒有異常狀态)。調用接口時,請登入“微信公衆平台-開發-基本配置”提前将伺服器IP位址添加到IP白名單中,點選檢視設定方法,否則将無法調用成功。小程式無需配置IP白名單。

接口調用請求說明

https請求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
           

參數說明

參數 是否必須 說明
grant_type 擷取access_token填寫client_credential
appid 第三方使用者唯一憑證
secret 第三方使用者唯一憑證密鑰,即appsecret

傳回說明

正常情況下,微信會傳回下述JSON資料包給公衆号:

{"access_token":"ACCESS_TOKEN","expires_in":7200}
           

參數說明

參數 說明
access_token 擷取到的憑證
expires_in 憑證有效時間,機關:秒

錯誤時微信會傳回錯誤碼等資訊,JSON資料包示例如下(該示例為AppID無效錯誤):

{"errcode":40013,"errmsg":"invalid appid"}
           

傳回碼說明

傳回碼 說明
-1 系統繁忙,此時請開發者稍候再試
請求成功
40001 AppSecret錯誤或者AppSecret不屬于這個公衆号,請開發者确認AppSecret的正确性
40002 請確定grant_type字段值為client_credential
40164 調用接口的IP位址不在白名單中,請在接口IP白名單中進行設定。(小程式及小遊戲調用不要求IP位址在白名單内。)

示例代碼:

//建立 Access_token類
public class Access_token
    {
        public string access_token { get; set; }
        public string expires_in { get; set; }
       
    }       

再将access_token做緩存,建立一個XML檔案存儲(或存儲在資料庫中,根據自己的程式設計愛好),XML格式如下:

<?xml version="1.0" encoding="utf-8"?>

<xml>

  <Access_Token>第一次可以随便寫</Access_Token>

  <Access_YouXRQ>2016/2/21 20:15:49</Access_YouXRQ>

</xml>

剛建好的XML,Access_Token節點中的資料可以随便寫,Access_YouXRQ節點中的資料寫一個之前兩小時的時間就可以了(推薦直接寫前一天的23:59:59)

擷取的邏輯是:當需要用到Access_Token的時候,直接調用IsExistAccess_Token()方法即可,以下是IsExistAccess_Token()方法實作的代碼:

/// <summary>
        /// 根據目前日期 判斷Access_Token 是否超期  如果超期傳回新的Access_Token   否則傳回之前的Access_Token
        /// </summary>
        /// <param name="datetime"></param>
        /// <returns></returns>
        private static string IsExistAccess_Token()
        {
            string Token = string.Empty;
            DateTime YouXRQ;
            // 讀取XML檔案中的資料,并顯示出來 ,注意檔案路徑
            string filepath = HttpContext.Current.Server.MapPath(".") + "\\AccessToken.xml";

            StreamReader str = new StreamReader(filepath, Encoding.UTF8);
            XmlDocument xml = new XmlDocument();
            xml.Load(str);
            str.Close();
            str.Dispose();
            Token = xml.SelectSingleNode("xml").SelectSingleNode("Access_Token").InnerText;
            YouXRQ = Convert.ToDateTime(xml.SelectSingleNode("xml").SelectSingleNode("Access_YouXRQ").InnerText);

            //TimeSpan st1 = new TimeSpan(YouXRQ.Ticks); //最後重新整理的時間
            //TimeSpan st2 = new TimeSpan(DateTime.Now.Ticks); //目前時間
            //TimeSpan st = st2 - st1; //兩者相差時間
            if (DateTime.Now > YouXRQ)
            {
                DateTime _youxrq = DateTime.Now;
                Access_token mode = GetAccess_token();
                xml.SelectSingleNode("xml").SelectSingleNode("Access_Token").InnerText = mode.access_token;
                _youxrq = _youxrq.AddSeconds(int.Parse(mode.expires_in));
                xml.SelectSingleNode("xml").SelectSingleNode("Access_YouXRQ").InnerText = _youxrq.ToString();
                xml.Save(filepath);
                Token = mode.access_token;
            }
            return Token;
        }


        /// <summary>
        /// 擷取Access_token
        /// </summary>
        /// <returns></returns>
        private static Access_token GetAccess_token()
        {
            string appid = "你自己微信公衆測試号的appID"; //微信公衆号appid
            string secret = "你自己微信公衆測試号的appsecret";  //微信公衆号appsecret
            string strUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret;
            Access_token mode = new Access_token();

            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(strUrl);  //用GET形式請求指定的位址 
            req.Method = "GET";

            using (WebResponse wr = req.GetResponse())
            {
                //HttpWebResponse myResponse = (HttpWebResponse)req.GetResponse();  
                StreamReader reader = new StreamReader(wr.GetResponseStream(), Encoding.UTF8);
                string content = reader.ReadToEnd();
                reader.Close();
                reader.Dispose();

                //在這裡對Access_token 指派  
                Access_token token = new Access_token();
                token = JsonHelper.ParseFromJson<Access_token>(content);
                mode.access_token = token.access_token;
                mode.expires_in = token.expires_in;
            }
            return mode;
        }      

可以看出來上面的GetAccess_token()方法裡面使用了JsonHelper類,這個類可以在網上下載下傳,也可以自己寫,下面是我自己寫的JsonHelper類供參考:

public class JsonHelper
    {
        /// <summary>
        /// 生成Json格式
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string GetJson<T>(T obj)
        {
            DataContractJsonSerializer json = new DataContractJsonSerializer(obj.GetType());
            using (MemoryStream stream = new MemoryStream())
            {
                json.WriteObject(stream, obj);
                string szJson = Encoding.UTF8.GetString(stream.ToArray()); return szJson;
            }
        }
        /// <summary>
        /// 擷取Json的Model
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="szJson"></param>
        /// <returns></returns>
        public static T ParseFromJson<T>(string szJson)
        {
            T obj = Activator.CreateInstance<T>();
            using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(szJson)))
            {
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
                return (T)serializer.ReadObject(ms);
            }
        }
    }      

至此就可以生成帶緩存功能的Access_Token,調用的時候string token=IsExistAccess_Token();