.NET微信公眾號開發-3.0查詢自定義菜單


一.前言

   前面我們已經創建好了我們的自定義菜單。那么我們現在要如何查詢我們自定義的菜單。原理都是一樣的,而且都是相當簡單,只是接口地址文檔換掉了。

2.0開始編碼

   同樣我們首先創建好我的查詢頁面,在這里我們使用aspx頁面 selectMenu.aspx

        protected void Page_Load(object sender, EventArgs e)
        {
            var str = GetPage("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wxd811f56f3&secret=76eb33f661296");
            JObject jo = JObject.Parse(str);
            access_token = jo["access_token"].ToString();
            GetPage("https://api.weixin.qq.com/cgi-bin/menu/get?access_token=" + access_token + "");
            //GetPage("https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=access_token");
        }

看代碼是不是相當的簡單。相信這對於聰明的你根本不是什么問題。同樣刪除我們的自定義菜單也很簡單,只不過是接口地址換了而已,GetPage方法的代碼前面的文章已經有了,在這里就不重復的說明了。

3.0令牌優化.

  前面我們已經知道了,怎么獲取我們的access_token,我們知道它的有效時間是7200s,在這里難道我們每次請求都需要去重新獲取一次,豈不是很麻煩,而且也不利於性能的優化,在這里我們對這個獲取令牌的方法做一些優化,更有利於我們的代碼.

在這里我們首先創建一個AccessToken類來存儲我們的一些信息。代碼如下

    /// <summary>
    /// 微信許可令牌
    /// </summary>
    public class AccessToken
    {
        /// <summary>
        /// 保存已獲取到的許可令牌,鍵為公眾號,值為公眾號最后一次獲取到的令牌
        /// </summary>
        private static ConcurrentDictionary<string, Tuple<AccessToken, DateTime>> accessTokens = new ConcurrentDictionary<string, Tuple<AccessToken, DateTime>>();

        /// <summary>
        /// 獲取access token的地址
        /// </summary>
        private const string urlForGettingAccessToken = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
        /// <summary>
        /// 獲取access token的http方法
        /// </summary>
        private const string httpMethodForGettingAccessToken = WebRequestMethods.Http.Get;
        /// <summary>
        /// 保存access token的最長時間(單位:秒),超過時間之后,需要重新獲取
        /// </summary>
        private const int accessTokenSavingSeconds = 7000;

        /// <summary>
        /// access token
        /// </summary>
        public string access_token { get; set; }
        /// <summary>
        /// 有效時間,單位:秒
        /// </summary>
        public int expires_in { get; set; }

        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name="_access_token">access token</param>
        /// <param name="_expires_in">有效時間</param>
        internal AccessToken(string _access_token, int _expires_in)
        {
            access_token = _access_token;
            expires_in = _expires_in;
        }

        /// <summary>
        /// 返回AccessToken字符串
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return string.Format("AccessToken:{0}\r\n有效時間:{1}秒", access_token, expires_in);
        }

        /// <summary>
        /// 從JSON字符串解析AccessToken
        /// </summary>
        /// <param name="json">JSON字符串</param>
        /// <returns>返回AccessToken</returns>
        internal static AccessToken ParseFromJson(string json)
        {
            var at = JsonConvert.DeserializeAnonymousType(json, new { access_token = "", expires_in = 1 });
            return new AccessToken(at.access_token, at.expires_in);
        }

        /// <summary>
        /// 嘗試從JSON字符串解析AccessToken
        /// </summary>
        /// <param name="json">JSON字符串</param>
        /// <param name="msg">如果解析成功,返回AccessToken;否則,返回null。</param>
        /// <returns>返回是否解析成功</returns>
        internal static bool TryParseFromJson(string json, out AccessToken token)
        {
            bool success = false;
            token = null;
            try
            {
                token = ParseFromJson(json);
                success = true;
            }
            catch { }
            return success;
        }

        /// <summary>
        /// 得到access token
        /// </summary>
        /// <param name="userName">公眾號</param>
        /// <returns>返回access token</returns>
        public static AccessToken Get(string userName)
        {
            Tuple<AccessToken, DateTime> lastToken = accessTokens.ContainsKey(userName) ? accessTokens[userName] : null;
            AccessToken token = lastToken == null ? null : lastToken.Item1;
            DateTime refreshTime = lastToken == null ? DateTime.MinValue : lastToken.Item2;
            double ms = (DateTime.Now - refreshTime).TotalSeconds;
            if (ms > accessTokenSavingSeconds || token == null)
            {
                //嘗試從微信服務器獲取2次
                ErrorMessage msg;
                AccessToken newToken = GetFromWeixinServer(userName, out msg);
                if (newToken == null)
                    newToken = GetFromWeixinServer(userName, out msg);
                if (newToken != null)
                {
                    lastToken = new Tuple<AccessToken, DateTime>(newToken, DateTime.Now);
                    accessTokens[userName] = lastToken;
                    token = newToken;
                }
            }
            return token;
        }

        /// <summary>
        /// 從微信服務器獲取access token
        /// </summary>
        /// <param name="userName">公眾號</param>
        /// <param name="msg">從服務器返回的錯誤信息。</param>
        /// <returns>返回許可令牌;如果獲取失敗,返回null。</returns>
        private static AccessToken GetFromWeixinServer(string userName, out ErrorMessage msg)
        {
            AccessToken token = null;
            msg = new ErrorMessage(ErrorMessage.ExceptionCode, "");
            string url = string.Format(urlForGettingAccessToken, WxPayConfig.APPID, WxPayConfig.APPSECRET);
            string result;
            if(!HttpHelper.Request(url, out result, httpMethodForGettingAccessToken, string.Empty))
            {
                msg.errmsg = "從微信服務器獲取響應失敗。";
                return token;
            }
            if (ErrorMessage.IsErrorMessage(result))
                msg = ErrorMessage.Parse(result);
            else
            {
                try
                {
                    token = AccessToken.ParseFromJson(result);
                }
                catch (Exception e)
                {
                    msg = new ErrorMessage(e);
                }
            }
            return token;
        }
    }

 從這個類中的代碼我們看到,每次獲取access_token的時候都會判斷一些時間是不是超過了7000,我們的token過期時間是7200s,這樣就不需要每次請求的時候都是重新獲取token。

這個時候我們的查詢代碼可以優化下.

        protected void Page_Load(object sender, EventArgs e)
        {

              string username = System.Configuration.ConfigurationManager.AppSettings["weixinid"].ToString();
              AccessToken token = AccessToken.Get(username);

            GetPage("https://api.weixin.qq.com/cgi-bin/menu/get?access_token=" + access_token + "");
            //GetPage("https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=access_token");
        }

 

本人能力有限,希望大家多多包涵.

  

4.0微信公眾號開發系列

1.0初始微信公眾號

2.0創建自定義菜單

3.0查詢自定義菜單

4.0公眾號消息處理

5.0微信支付

6.0模板消息


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM