微信公众号开发之access_token的全局共用
最近做微信公众号开发,涉及到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; /// <summary>
/// WeChatUtilities
/// 微信公共服务,远程微信调用接口
///
/// 修改记录
///
/// 2016.11.16 版本:1.0 SongBiao 远程调用服务。
///
/// <author>
/// <name>SongBiao</name>
/// <date>2016.11.16</date>
/// </author>
/// </summary>
public class WeChatUtilities
{
/// <summary>
/// 获取微信AccessToken
/// Redis全局缓存,过期自动获取
/// 对应于公众号是全局唯一的票据,重复获取将导致上次获取的access_token失效
/// </summary>
/// <returns></returns>
public static string GetAccessToken()
{
string key = "WXAccessToken";
string accessToken = string.Empty;
DateTime expiresAt = DateTime.Now;
using (var redisClient = PooledRedisHelper.GetTokenClient())
{
AccessTokenResult tokenResult = redisClient.Get<AccessTokenResult>(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<WxJsonResult>(returnText);
if (errorResult.errcode != )
{
//发生错误
throw new Exception(string.Format("微信请求发生错误!错误代码:{0},说明:{1}",
(int)errorResult.errcode, errorResult.errmsg));
}
}
tokenResult = js.Deserialize<AccessTokenResult>(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 微信公用
/// <summary>
/// 微信接口
/// </summary>
interface IJsonResult
{
string errmsg { get; set; }
object P2PData { get; set; }
}
/// <summary>
/// 公众号返回码(JSON)
/// 应该更名为ReturnCode_MP,但为减少项目中的修改,此处依旧用ReturnCode命名
/// </summary>
enum ReturnCode
{
系统繁忙此时请开发者稍候再试 = -,
请求成功 = ,
获取access_token时AppSecret错误或者access_token无效 = ,
不合法的凭证类型 = ,
不合法的OpenID = ,
不合法的媒体文件类型 = ,
不合法的文件类型 = ,
不合法的文件大小 = ,
不合法的媒体文件id = ,
不合法的消息类型 = ,
不合法的图片文件大小 = ,
不合法的语音文件大小 = ,
不合法的视频文件大小 = ,
不合法的缩略图文件大小 = ,
不合法的APPID = ,
不合法的access_token = ,
不合法的菜单类型 = ,
不合法的按钮个数1 = ,
不合法的按钮个数2 = ,
不合法的按钮名字长度 = ,
不合法的按钮KEY长度 = ,
不合法的按钮URL长度 = ,
不合法的菜单版本号 = ,
不合法的子菜单级数 = ,
不合法的子菜单按钮个数 = ,
不合法的子菜单按钮类型 = ,
不合法的子菜单按钮名字长度 = ,
不合法的子菜单按钮KEY长度 = ,
不合法的子菜单按钮URL长度 = ,
不合法的自定义菜单使用用户 = ,
不合法的oauth_code = ,
不合法的refresh_token = ,
不合法的openid列表 = ,
不合法的openid列表长度 = ,
不合法的请求字符不能包含uxxxx格式的字符 = ,
不合法的参数 = ,
不合法的请求格式 = ,
不合法的URL长度 = ,
不合法的分组id = ,
分组名字不合法 = ,
缺少access_token参数 = ,
缺少appid参数 = ,
缺少refresh_token参数 = ,
缺少secret参数 = ,
缺少多媒体文件数据 = ,
缺少media_id参数 = ,
缺少子菜单数据 = ,
缺少oauth_code = ,
缺少openid = ,
access_token超时 = ,
refresh_token超时 = ,
oauth_code超时 = ,
需要GET请求 = ,
需要POST请求 = ,
需要HTTPS请求 = ,
需要接收者关注 = ,
需要好友关系 = ,
多媒体文件为空 = ,
POST的数据包为空 = ,
图文消息内容为空 = ,
文本消息内容为空 = ,
多媒体文件大小超过限制 = ,
消息内容超过限制 = ,
标题字段超过限制 = ,
描述字段超过限制 = ,
链接字段超过限制 = ,
图片链接字段超过限制 = ,
语音播放时间超过限制 = ,
图文消息超过限制 = ,
接口调用超过限制 = ,
创建菜单个数超过限制 = ,
回复时间超过限制 = ,
系统分组不允许修改 = ,
分组名字过长 = ,
分组数量超过上限 = ,
不存在媒体数据 = ,
不存在的菜单版本 = ,
不存在的菜单数据 = ,
解析JSON_XML内容错误 = ,
api功能未授权 = ,
用户未授权该api = ,
参数错误invalid_parameter = ,
无效客服账号invalid_kf_account = ,
客服帐号已存在kf_account_exsited = ,
/// <summary>
/// 客服帐号名长度超过限制(仅允许10个英文字符,不包括@及@后的公众号的微信号)(invalid kf_acount length)
/// </summary>
客服帐号名长度超过限制 = ,
/// <summary>
/// 客服帐号名包含非法字符(仅允许英文+数字)(illegal character in kf_account)
/// </summary>
客服帐号名包含非法字符 = ,
/// <summary>
/// 客服帐号个数超过限制(10个客服账号)(kf_account count exceeded)
/// </summary>
客服帐号个数超过限制 = ,
无效头像文件类型invalid_file_type = ,
系统错误system_error = ,
日期格式错误 = ,
日期范围错误 = , //新加入的一些类型,以下文字根据P2P项目格式组织,非官方文字
发送消息失败_48小时内用户未互动 = ,
发送消息失败_该用户已被加入黑名单_无法向此发送消息 = ,
发送消息失败_对方关闭了接收消息 = ,
对方不是粉丝 =
} /// <summary>
/// 返回接口
/// </summary>
interface IWxJsonResult : IJsonResult
{
ReturnCode errcode { get; set; }
}
/// <summary>
/// 公众号JSON返回结果(用于菜单接口等)
/// </summary>
[Serializable]
class WxJsonResult : IWxJsonResult
{
public ReturnCode errcode { get; set; }
public string errmsg { get; set; }
/// <summary>
/// 为P2P返回结果做准备
/// </summary>
public virtual object P2PData { get; set; }
}
#endregion }
/// <summary>
/// access_token请求后的JSON返回格式
/// </summary>
[Serializable]
public class AccessTokenResult
{
/// <summary>
/// 获取到的凭证
/// </summary>
public string access_token { get; set; }
/// <summary>
/// 凭证有效时间,单位:秒
/// </summary>
public int expires_in { get; set; } /// <summary>
/// 凭证过期有效时间
/// </summary>
public DateTime expiresAt { get; set; }
} }
aaarticlea/png;base64,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" alt="" />
通过缓存access_token方式实现以后,同步微信后台用户数据正常了。
==============
上面第一个方法可以作为C#开发的同学的获取AccessToken的公共方法,因为还有其他语言开发的同学,所以在这里又增加了一个获取AccessToken的对外接口
//-----------------------------------------------------------------------
// <copyright file="WeChatService.ashx" company="Hairihan">
// Copyright (C) 2016 , All rights reserved.
// </copyright>
//----------------------------------------------------------------------- using System;
using System.Collections.Generic;
using System.Linq;
using System.Web; namespace DotNet.UserCenter
{
using DotNet.Business.HttpUtilities;
using DotNet.Utilities; /// <summary>
/// WeChatService
///
/// 修改记录
///
///
/// 2016-11-17 版本:1.0 SongBiao 创建
///
/// <author>
/// <name>SongBiao</name>
/// <date>2016-11-17</date>
/// </author>
/// </summary>
public class WeChatService : IHttpHandler
{
/// <summary>
/// 获取服务器时间
/// </summary>
/// <param name="context"></param>
private void GetServerDateTime(HttpContext context)
{
JsonResult<string> jsonResult = new JsonResult<string>()
{
Status = true,
StatusMessage = "成功获取服务器时间",
Data = DateTime.Now.ToString(BaseSystemInfo.DateTimeFormat)
};
context.Response.Write(jsonResult.ToJson());
}
/// <summary>
/// 获取用户中心库时间
/// </summary>
/// <param name="context"></param>
private void GetDbDateTime(HttpContext context)
{
JsonResult<string> jsonResult = new JsonResult<string>();
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());
} /// <summary>
/// 获取AccessToken
/// </summary>
/// <param name="context"></param>
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;
}
}
}
}
微信公众号开发之access_token的全局共用的更多相关文章
- 微信公众号开发之VS远程调试
目录 (一)微信公众号开发之VS远程调试 (二)微信公众号开发之基础梳理 (三)微信公众号开发之自动消息回复和自定义菜单 前言 微信公众平台消息接口的工作原理大概可以这样理解:从用户端到公众号端一个流 ...
- 微信公众号开发之H5页面跳转到指定的小程序
前言: 最近公司有一个这样的需要,需要从我们在现有的公众号H5页面中加一个跳转到第三方小程序的按钮.之前只知道小程序之间是可以相互跳转的,今天查阅了下微信开发文档原来现在H5网页也支持小程序之间的跳转 ...
- 微信公众号开发之LBS
百度地图Web服务api:http://lbsyun.baidu.com/index.php?title=webapi 1.测距 Route Matrix API v2.0:http://lbsyun ...
- 微信公众账号开发之N个坑(二)
上篇说到微信公众账号的几个坑,前面五个,已经说到菜单,宝宝继续往下赘述了.可惜,还不知道宝宝的宝宝到底是不是心疼宝宝呢,完了,我凌乱了... 回到正题,我们就不吐槽其他的了,上一篇说到微信的菜单了,那 ...
- 微信公众账号开发之N个坑(一)
我这人干活没有前奏,喜欢直接开始.完了,宝宝已经被你们带污了.. 微信公众账号开发文档,官方版(https://mp.weixin.qq.com/wiki),相信我,我已经无力吐槽写这个文档的人了,我 ...
- Java微信公众平台开发之OAuth2.0网页授权
根据官方文档点击查看在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的"开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息"的配置选项中,修 ...
- 和小猪一起搞微信公众号开发—获取Access_token
前言 前一篇小猪和大家分享了如何回复用户的简单文本,这一篇我们来看看如何获取Access_token 介绍 在前一篇中,我们实现了这么一个简单的过程:用户发送一个文本到公众号后,公众号在该文本后面加上 ...
- 使用 nodeJs 开发微信公众号(获取access_token)
要使用微信提供的功能接口,就需要获取到access_token,这是开发公众号必不可少的一部 access_token有效期20分钟,建议保存起来,过期后在重新获取 获取流程如下: 我将微信相关的操作 ...
- C#微信公众号开发——获取access_token
access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token.正常情况下access_token有效期为7200秒(两个小时),微信获取access_token接 ...
随机推荐
- PyQtdeploy-V2.4 User Guide 中文 (一)
PyQtdeploy 用户指南 目录 介绍 与V1.0+的差异 作者 证书 安装 部署过程概览 PyQt的演示 构建演示 Android IOS Linux MacOS Windos 构建系统根目录 ...
- Dynamics 365 启用跟踪及读取跟踪文件工具
微软动态CRM专家罗勇 ,回复315或者20190313可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!我的网站是 www.luoyong.me . 当根据错误提示排查问 ...
- 使用 MapTiler 进行地图切片
在GIS开发中接触比较多的就是切图与发布,通常大家使用的是GlobalMapper.ArcGIS.GDAL等. 一般在使用Leaflet.js或其他框架开发时,使用的是TMS切片格式,大佬们基本用GD ...
- pythonmysql运行报错解决过程中遇到的其中一个报错解决文章来源
本文章仅记录下面报错的解决文章来源:error: command 'C:\Users\Administrator\AppData\Local\Programs\Common\Micr osoft\Vi ...
- mssql sqlserver 将字段null(空值)值替换为指定值的三种方法分享
摘要: 下文将分享两种将字段中null值替换为指定值的方法分享,如下所示: 实验环境:sqlserver 2008 R2 例: )) go insert into test(info)values(' ...
- c/c++ 模板 类型推断
模板类型的推断 下面的函数f是个模板函数,typename T.下表是,根据调用测的实参,推断出来的T的类型. 请注意下表的红字部分, f(T&& t)看起来是右值引用,但其实它会根据 ...
- Exception in thread "main" org.I0Itec.zkclient.exception.ZkAuthFailedException: Authentication failure is thrown while creating kafka topic
Exception in thread "main" org.I0Itec.zkclient.exception.ZkAuthFailedException: Authentica ...
- 【spring源码分析】IOC容器初始化(八)
前言:在上文bean加载过程中还要一个非常重要的方法没有分析createBean,该方法非常重要,因此特意提出来单独分析. createBean方法定义在AbstractBeanFactory中: 该 ...
- Navicat Premium 12.1.16.0安装与激活
声明:本文所提供的所有软件均来自于互联网,仅供个人研究和学习使用,请勿用于商业用途,下载后请于24小时内删除,请支持正版! 本文介绍Navicat Premium 12的安装.激活与基本使用.已于20 ...
- cordova插件汇总
1.获取当前应用的版本号 cordova plugin add cordova-plugin-app-version 2.获取网络连接信息 cordova plugin add cordova-plu ...