博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
微信公众号开发之access_token的全局共用
阅读量:5864 次
发布时间:2019-06-19

本文共 12290 字,大约阅读时间需要 40 分钟。

最近做微信公众号开发,涉及到access_token的缓存问题(避免各自的应用都去取access_token,同时解决微信 appid和appsecret的安全问题),在通用权限管理系统底层增加了实现方法:

(access_token默认2小时过期,每取一次,上一次的就自动失效,每天取的次数有限制)

//-----------------------------------------------------------------// All Rights Reserved , Copyright (C) 2016 , Hairihan TECH, Ltd.  //-----------------------------------------------------------------using System;using System.Net;using System.Text;using System.Web.Script.Serialization;namespace DotNet.Business.HttpUtilities{    using DotNet.Utilities;    ///     /// WeChatUtilities     /// 微信公共服务,远程微信调用接口    ///    /// 修改记录    ///    ///        2016.11.16 版本:1.0 SongBiao  远程调用服务。    ///    /// 
///
SongBiao
///
2016.11.16
///
///
public class WeChatUtilities { /// /// 获取微信AccessToken /// Redis全局缓存,过期自动获取 /// 对应于公众号是全局唯一的票据,重复获取将导致上次获取的access_token失效 /// ///
public static string GetAccessToken() { string key = "WXAccessToken"; string accessToken = string.Empty; DateTime expiresAt = DateTime.Now; using (var redisClient = PooledRedisHelper.GetTokenClient()) { AccessTokenResult tokenResult = redisClient.Get
(key); // 不存在或者已过期 if (tokenResult == null || (tokenResult != null && DateTime.Now > tokenResult.expiresAt)) { JavaScriptSerializer js = new JavaScriptSerializer(); string appId = BaseSystemInfo.WeiXinAppId; string appSecret = BaseSystemInfo.WeiXinAppSecret; var url = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", appId, appSecret); using (WebClient wc = new WebClient()) { wc.Proxy = null; wc.Encoding = Encoding.UTF8; string returnText = wc.DownloadString(url); if (returnText.Contains("errcode")) { //可能发生错误 //可能发生错误 WxJsonResult errorResult = js.Deserialize
(returnText); if (errorResult.errcode != 0) { //发生错误 throw new Exception(string.Format("微信请求发生错误!错误代码:{0},说明:{1}", (int)errorResult.errcode, errorResult.errmsg)); } } tokenResult = js.Deserialize
(returnText); // 添加到缓存中 减少10秒 避免一些问题 expiresAt = DateTime.Now.AddSeconds(tokenResult.expires_in); tokenResult.expiresAt = expiresAt; redisClient.Set(key, tokenResult, expiresAt); NLogHelper.Trace(DateTime.Now + ",微信accessToken过期,重新获取,下次过期时间:" + expiresAt); } } accessToken = tokenResult.access_token; } return accessToken; } #region 微信公用 ///
/// 微信接口 /// interface IJsonResult { string errmsg { get; set; } object P2PData { get; set; } } ///
/// 公众号返回码(JSON) /// 应该更名为ReturnCode_MP,但为减少项目中的修改,此处依旧用ReturnCode命名 /// enum ReturnCode { 系统繁忙此时请开发者稍候再试 = -1, 请求成功 = 0, 获取access_token时AppSecret错误或者access_token无效 = 40001, 不合法的凭证类型 = 40002, 不合法的OpenID = 40003, 不合法的媒体文件类型 = 40004, 不合法的文件类型 = 40005, 不合法的文件大小 = 40006, 不合法的媒体文件id = 40007, 不合法的消息类型 = 40008, 不合法的图片文件大小 = 40009, 不合法的语音文件大小 = 40010, 不合法的视频文件大小 = 40011, 不合法的缩略图文件大小 = 40012, 不合法的APPID = 40013, 不合法的access_token = 40014, 不合法的菜单类型 = 40015, 不合法的按钮个数1 = 40016, 不合法的按钮个数2 = 40017, 不合法的按钮名字长度 = 40018, 不合法的按钮KEY长度 = 40019, 不合法的按钮URL长度 = 40020, 不合法的菜单版本号 = 40021, 不合法的子菜单级数 = 40022, 不合法的子菜单按钮个数 = 40023, 不合法的子菜单按钮类型 = 40024, 不合法的子菜单按钮名字长度 = 40025, 不合法的子菜单按钮KEY长度 = 40026, 不合法的子菜单按钮URL长度 = 40027, 不合法的自定义菜单使用用户 = 40028, 不合法的oauth_code = 40029, 不合法的refresh_token = 40030, 不合法的openid列表 = 40031, 不合法的openid列表长度 = 40032, 不合法的请求字符不能包含uxxxx格式的字符 = 40033, 不合法的参数 = 40035, 不合法的请求格式 = 40038, 不合法的URL长度 = 40039, 不合法的分组id = 40050, 分组名字不合法 = 40051, 缺少access_token参数 = 41001, 缺少appid参数 = 41002, 缺少refresh_token参数 = 41003, 缺少secret参数 = 41004, 缺少多媒体文件数据 = 41005, 缺少media_id参数 = 41006, 缺少子菜单数据 = 41007, 缺少oauth_code = 41008, 缺少openid = 41009, access_token超时 = 42001, refresh_token超时 = 42002, oauth_code超时 = 42003, 需要GET请求 = 43001, 需要POST请求 = 43002, 需要HTTPS请求 = 43003, 需要接收者关注 = 43004, 需要好友关系 = 43005, 多媒体文件为空 = 44001, POST的数据包为空 = 44002, 图文消息内容为空 = 44003, 文本消息内容为空 = 44004, 多媒体文件大小超过限制 = 45001, 消息内容超过限制 = 45002, 标题字段超过限制 = 45003, 描述字段超过限制 = 45004, 链接字段超过限制 = 45005, 图片链接字段超过限制 = 45006, 语音播放时间超过限制 = 45007, 图文消息超过限制 = 45008, 接口调用超过限制 = 45009, 创建菜单个数超过限制 = 45010, 回复时间超过限制 = 45015, 系统分组不允许修改 = 45016, 分组名字过长 = 45017, 分组数量超过上限 = 45018, 不存在媒体数据 = 46001, 不存在的菜单版本 = 46002, 不存在的菜单数据 = 46003, 解析JSON_XML内容错误 = 47001, api功能未授权 = 48001, 用户未授权该api = 50001, 参数错误invalid_parameter = 61451, 无效客服账号invalid_kf_account = 61452, 客服帐号已存在kf_account_exsited = 61453, ///
/// 客服帐号名长度超过限制(仅允许10个英文字符,不包括@及@后的公众号的微信号)(invalid kf_acount length) /// 客服帐号名长度超过限制 = 61454, ///
/// 客服帐号名包含非法字符(仅允许英文+数字)(illegal character in kf_account) /// 客服帐号名包含非法字符 = 61455, ///
/// 客服帐号个数超过限制(10个客服账号)(kf_account count exceeded) /// 客服帐号个数超过限制 = 61456, 无效头像文件类型invalid_file_type = 61457, 系统错误system_error = 61450, 日期格式错误 = 61500, 日期范围错误 = 61501, //新加入的一些类型,以下文字根据P2P项目格式组织,非官方文字 发送消息失败_48小时内用户未互动 = 10706, 发送消息失败_该用户已被加入黑名单_无法向此发送消息 = 62751, 发送消息失败_对方关闭了接收消息 = 10703, 对方不是粉丝 = 10700 } ///
/// 返回接口 /// interface IWxJsonResult : IJsonResult { ReturnCode errcode { get; set; } } ///
/// 公众号JSON返回结果(用于菜单接口等) /// [Serializable] class WxJsonResult : IWxJsonResult { public ReturnCode errcode { get; set; } public string errmsg { get; set; } ///
/// 为P2P返回结果做准备 /// public virtual object P2PData { get; set; } } #endregion } ///
/// access_token请求后的JSON返回格式 /// [Serializable] public class AccessTokenResult { ///
/// 获取到的凭证 /// public string access_token { get; set; } ///
/// 凭证有效时间,单位:秒 /// public int expires_in { get; set; } ///
/// 凭证过期有效时间 /// public DateTime expiresAt { get; set; } }}

 

 

 

通过缓存access_token方式实现以后,同步微信后台用户数据正常了。

 

==============

上面第一个方法可以作为C#开发的同学的获取AccessToken的公共方法,因为还有其他语言开发的同学,所以在这里又增加了一个获取AccessToken的对外接口

//-----------------------------------------------------------------------// 
// Copyright (C) 2016 , All rights reserved.//
//-----------------------------------------------------------------------using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace DotNet.UserCenter{ using DotNet.Business.HttpUtilities; using DotNet.Utilities; /// /// WeChatService /// /// 修改记录 /// /// /// 2016-11-17 版本:1.0 SongBiao 创建 /// ///
///
SongBiao
///
2016-11-17
///
///
public class WeChatService : IHttpHandler { /// /// 获取服务器时间 /// /// private void GetServerDateTime(HttpContext context) { JsonResult
jsonResult = new JsonResult
() { Status = true, StatusMessage = "成功获取服务器时间", Data = DateTime.Now.ToString(BaseSystemInfo.DateTimeFormat) }; context.Response.Write(jsonResult.ToJson()); } ///
/// 获取用户中心库时间 /// ///
private void GetDbDateTime(HttpContext context) { JsonResult
jsonResult = new JsonResult
(); try { using (IDbHelper dbHelper = DbHelperFactory.GetHelper(BaseSystemInfo.UserCenterDbType, BaseSystemInfo.UserCenterDbConnection)) { string result = DateTime.Parse(dbHelper.GetDbDateTime()).ToString(BaseSystemInfo.DateTimeFormat); jsonResult.Status = true; jsonResult.StatusMessage = "成功获取用户中心库时间"; jsonResult.Data = result; } } catch (Exception ex) { jsonResult.Status = true; jsonResult.StatusMessage = "获取用户中心库时间异常:" + ex.Message; NLogHelper.Trace(ex, "UserService GetDbDateTime 异常"); } context.Response.Write(jsonResult.ToJson()); } ///
/// 获取AccessToken /// ///
private void GetAccessToken(HttpContext context) { BaseResult baseResult = new BaseResult(); try { string accessToken = WeChatUtilities.GetAccessToken(); if (!string.IsNullOrWhiteSpace(accessToken)) { baseResult.Status = true; baseResult.ResultValue = accessToken; baseResult.StatusMessage = Status.OK.GetDescription(); } else { baseResult.Status = false; baseResult.StatusMessage = "AccessToken获取失败。"; } } catch (Exception ex) { baseResult.Status = false; baseResult.StatusMessage = "AccessToken获取异常:"+ex.Message; } context.Response.Write(baseResult.ToJson()); } public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; if (context.Request["function"] == null) { this.GetServerDateTime(context); } else { string function = context.Request["function"]; if (function.Equals("GetServerDateTime", StringComparison.OrdinalIgnoreCase)) { this.GetServerDateTime(context); } else if (function.Equals("GetAccessToken", StringComparison.OrdinalIgnoreCase)) { this.GetAccessToken(context); } else { context.Response.Write(BaseResult.Error("function对应方法不存在。").ToJson()); } context.Response.End(); } } public bool IsReusable { get { return false; } } }}

 

转载地址:http://erunx.baihongyu.com/

你可能感兴趣的文章
简单易扩展的爬虫架构
查看>>
实现Winform端窗体关闭后刷新html网页内容
查看>>
js词法结构
查看>>
IIS7应用程序池集成和经典的区别
查看>>
UVA 11542 Square [XOR方程组]
查看>>
NPM安装配置
查看>>
listagg( ) within group ( order by ) 与 wm_concat
查看>>
HDU 1032 The 3n + 1 problem
查看>>
shell 实现word count
查看>>
Spark Streaming性能调优
查看>>
【BZOJ】2466: [中山市选2009]树 高斯消元解异或方程组
查看>>
http://q.cnblogs.com/q/39321/
查看>>
【BZOJ】1635: [Usaco2007 Jan]Tallest Cow 最高的牛
查看>>
牛客练习赛10
查看>>
数据库内连接、外连接、左连接、右连接、全连接
查看>>
Leetcode House Robber
查看>>
实验五
查看>>
keypress 、keydown、keyup后触发回车
查看>>
非节点主机通过内网远程管理docker swarm集群
查看>>
js判断PC端还是移动端
查看>>