服务器之家

服务器之家 > 正文

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

时间:2019-12-18 16:10     来源/作者:hebedich

一.前言

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

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

二、开始编码

   同样我们首先创建好我的查询页面,在这里我们使用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类来存储我们的一些信息。代码如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/// <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");
        }

 

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

相关文章

热门资讯

玄元剑仙肉身有什么用 玄元剑仙肉身境界等级划分
玄元剑仙肉身有什么用 玄元剑仙肉身境界等级划分 2019-06-21
男生常说24816是什么意思?女生说13579是什么意思?
男生常说24816是什么意思?女生说13579是什么意思? 2019-09-17
配置IIS网站web服务器的安全策略配置解决方案
配置IIS网站web服务器的安全策略配置解决方案 2019-05-23
Nginx服务器究竟是怎么执行PHP项目
Nginx服务器究竟是怎么执行PHP项目 2019-05-24
华为nova5pro和p30pro哪个好 华为nova5pro和华为p30pro对比详情
华为nova5pro和p30pro哪个好 华为nova5pro和华为p30pro对比详情 2019-06-22
返回顶部