.NET微信公众号开发之查询自定义菜单

一.前言

前面我们已经创建好了我们的自定义菜单。那么我们现在要如何查询我们自定义的菜单。

原理都是一样的,而且都是相当简单,只是接口地址文档换掉了。

二、开始编码

同样我们首先创建好我的查询页面,在这里我们使用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方法的代码前面的文章已经有了,在这里就不重复的说明了。

三、令牌优化.

前面我们已经知道了,怎么获取我们的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");
        }

以上所述就是本文的全部内容了,希望大家能够喜欢。

(0)

相关推荐

  • php实现微信公众号主动推送消息

    通过学习借鉴朋友的实现方法进行整理,实现了PHP版的微信公共平台消息主动推送,分享给大家供大家参考,具体内容如下 此方法是通过模拟登录微信公共平台的方法来实现的. 代码如下: 一.登录接口部分代码 //登录 private function login(){ $url = 'https://mp.weixin.qq.com/cgi-bin/login?lang=zh_CN'; $this->send_data = array( 'username' => $this->_account,

  • 微信公众号开发之微信公共平台消息回复类实例

    本文实例讲述了微信公众号开发之微信公共平台消息回复类.分享给大家供大家参考.具体如下: 微信公众号开发代码我在网上看到了有不少,其实都是大同小义了都是参考官方给出的demo文件进行修改的,这里就给各位分享一个. 复制代码 代码如下: <?php /**  * 微信公共平台消息回复类  *  *  */ class BBCweixin{    private $APPID="******";  private $APPSECRET="******";  /*  

  • 微信公众号开发 自定义菜单跳转页面并获取用户信息实例详解

    微信公众号开发 自定义菜单 请先读完本文再进行配置开发 请先前往微信平台开发者文档阅读"网页授权获取用户基本信息"的接口说明 在微信公众账号开发中,往往有定义一个菜单,然后用户点击该菜单就进入用户个人中心的功能,通常应用于各个公众账号中的会员服务. 如何在微信自定义菜单中将用户导航到个人中心页面呢? 首选需要通过用户点击获取用户openid,而通过用户的点击跳转获取用户openid就必须在菜单中动态绑定用户的openid,或者在菜单的跳转URL中填写微信提供的链接,官方给了两个链接类型

  • 微信公众号支付之坑:调用支付jsapi缺少参数 timeStamp等错误解决方法

    这段时间一直比较忙,一忙起来真感觉自己就只是一台挣钱的机器了(说的好像能挣到多少钱似的,呵呵):这会儿难得有点儿空闲时间,想把前段时间开发微信公众号支付遇到问题及解决方法跟大家分享下,这些"暗坑"能不掉就不掉吧,要不然关键时刻出问题,真是让人急的焦头烂额. 双12客户的商城活动正在蓄势进行中,却有用户频频反馈说:支付不了,有问题,并截图如下: 当时问题感觉很奇怪,自己测试多次都ok啊,问题来了都赶紧解决吧,最终找到解决办法: 原因是程序中一个字符串变量被错误的设置为数字类型,解决方法很

  • java微信公众号开发第一步 公众号接入和access_token管理

    本文就来说一说微信开发第一步,公众号接入以及access_token的管理. 一.微信公众号接入 在微信公众号开发手册上,关于公众号接入这一节内容还是写的比较详细的,文档中说接入公众号需要3个步骤,分别是: 1.填写服务器配置 2.验证服务器地址的有效性 3.依据接口文档实现业务逻辑 其实,第3步已经不能算做公众号接入的步骤,而是接入之后,开发人员可以根据微信公众号提供的接口所能做的一些开发. 第1步中服务器配置包含服务器地址(URL).Token和EncodingAESKey. 服务器地址即公

  • java微信公众号开发(搭建本地测试环境)

    俗话说,工欲善其事,必先利其器.要做微信公众号开发,两样东西不可少,那就是要有一个用来测试的公众号,还有一个用来调式代码的开发环境. 测试公众号 微信公众号有订阅号.服务号.企业号,在注册的时候看到这样的信息,只有订阅号可以个人申请,服务号和企业号要有企业资质才可以.这里所说的微信公众号开发指的是订阅号和服务号. 另外,未认证的个人订阅号有一些接口是没有权限的,并且目前个人订阅号已不支持微信认证,也就是说个人订阅号无法调用一些高级的权限接口,下图就是一个未认证的个人订阅号所具备权限列表,像生成二

  • C#微信公众号开发之接收事件推送与消息排重的方法

    本文实例讲述了C#微信公众号开发之接收事件推送与消息排重的方法.分享给大家供大家参考.具体分析如下: 微信服务器在5秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次.这样的话,问题就来了.有这样一个场景:当用户关注微信账号时,获取当前用户信息,然后将信息写到数据库中.类似于pc端网站的注册.可能由于这个关注事件中,我们需要处理的业务逻辑比较复杂.如送积分啊,写用户日志啊,分配用户组啊.等等--一系列的逻辑需要执行,或者网络环境比较复杂,无法保证5秒内响应当前用户的操作,那如果当操作尚未完

  • .NET微信公众号开发之创建自定义菜单

    一.前言 开发之前,我们需要阅读官方的接口说明文档,不得不吐槽一下,微信的这个官方文档真的很烂,但是,为了开发我们需要的功能,我们也不得不去看这些文档. 接口文档地址:http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html 看了这些个文档,基本意思明白了,就是我们把我们要创建的菜单创建好,post到微信的服务器上面,微信服务器然后给我们一些状态码,从而判断我们的菜单是否创建成功,只是在发送json数据以前我们要做

  • C#实现微信公众号群发消息(解决一天只能发一次的限制)实例分享

    总体思路: 1.首先必须要在微信公众平台上申请一个公众号. 2.然后进行模拟登陆.(由于我对http传输原理和编程不是特别懂,在模拟登陆的地方,不是特别清楚,希望有大神指教) 3.模拟登陆后会获得一个token(令牌)和cookie. 4.因为模拟登陆后相当于就进入了微信公众平台,在这个里面就可以抓取到需要的数据,如公众好友的昵称,fakeId.其中的fakeid非常重要,因为传输数据必须要知道对方的fakeid. 5.知道对方的fakeid就可以进行数据的发送了. 这里是整个项目的源码下载:h

  • 微信公众号支付(一)如何获取用户openId

    一.获取apikey,appsecret与商户号 注册公众号.商户号 二.获取用户的OpenId 1.设置[授权回调页面域名] 官方解释:用户在网页授权页同意授权给公众号后,微信会将授权数据传给一个回调页面,回调页面需在此域名下,以确保安全可靠.回调页面域名不支持IP地址. 2.用户同意授权 我是把这个url写在微信菜单下的,当进入这个页面的时候就让用户同意.注意:好像是静默授权的,用户不知道 1.url: https://open.weixin.qq.com/connect/oauth/aut

  • 微信支付PHP SDK之微信公众号支付代码详解

    这里假设你已经申请完微信支付 1. 微信后台配置  如图 我们先进行测试,所以先把测试授权目录和 测试白名单添加上.测试授权目录是你要发起微信请求的哪个文件所在的目录. 例如jsapi 发起请求一般是jsapi.php所在目录 为测试目录,测试白名单即开发人员的微信号. 正式的支付授权目录不能和测试的一样否则会报错.不填写或者填错授权目录以及测试白名单都会报错. 报错样例: NaNsystem:access_denied 不在测试白名单 2. 配置 lib/WxPay.Config.php文件

随机推荐