微信公众号开发——网页授权 (页面分享 、获取用户基本信息)
2016-09-29 09:04
796 查看
第一步:要用到的接口文档如下
第二步:使用网页服务,公众号需要如下配置
1.设置 授权回调页面域名
2.设置 JS接口安全域名设置(点击公众号左边菜单 公众号设置 进入设置页面 点击 功能设置)
上代码
BLL调用程序先贴上来
系统入口 :指的是进入系统主页之前的一个请求地址,请求到达这里 又用调用微信的接口,通过微信来回调系统主页
前端页面代码
WebPageAuthorize (网页授权类)
JsConfig (Js配置生产类)
Common 公共类
BasisApi (基础接口类)
类库结构
第二步:使用网页服务,公众号需要如下配置
1.设置 授权回调页面域名
2.设置 JS接口安全域名设置(点击公众号左边菜单 公众号设置 进入设置页面 点击 功能设置)
上代码
BLL调用程序先贴上来
系统入口 :指的是进入系统主页之前的一个请求地址,请求到达这里 又用调用微信的接口,通过微信来回调系统主页
/// <summary> /// 系统入口( http://jnga.sunmen.cn/Home/Entrance ) /// </summary> /// <returns></returns> public ActionResult Entrance() { string appid, redirect_uri, scope, state; appid = ConfigurationManager.AppSettings["appid"]; redirect_uri = "http://jnga.sunmen.cn/Home/Index"; scope = "snsapi_userinfo"; //snsapi_base用户无感觉 snsapi_userinfo 弹出授权页面 state = ""; //自定义参数 WebPageAuthorize.RedirectUrl(appid, redirect_uri, scope, state); return new EmptyResult(); }
/// <summary> /// 系统首页 /// </summary> /// <param name="code">预授权code</param> /// <param name="state">自定义参数</param> /// <returns></returns> public ActionResult Index(string code, string state) { if (Common.IsWeixinBrowser()) { string weixinJsApiStr = "onMenuShareTimeline,onMenuShareAppMessage"; string appid = ConfigurationManager.AppSettings["appid"]; string secret = ConfigurationManager.AppSettings["secret"]; string weixinJsConfigStr = JsConfig.GetJsConfig(weixinJsApiStr, appid, secret); ViewBag.JsConfigStr = weixinJsConfigStr; if (!string.IsNullOrEmpty(code)) { string openid = Session["openid"] == null ? "" : Session["openid"].ToString(); int userType = 0; if (string.IsNullOrEmpty(openid)) { Hashtable ht = WebPageAuthorize.GetWebPageAuthorizeAccessToken(appid, secret, code); openid = ht["openid"].ToString(); Session["openid"] = openid; } //具体业务省略...... } else { return Content("授权码不存在"); } } else { return Content("请用微信浏览器打开"); } }
前端页面代码
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>金华人口流动申报系统</title> <meta charset="utf-8"> <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0" /> <meta name="format-detection" content="telephone=no,email=no,date=no,address=no"> <link href="~/res/css/aui.2.0.css" rel="stylesheet" /> </head> <body> 省略..... </body> </html> <script src="~/Scripts/jquery-1.7.1.min.js"></script> <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script> <script type="text/javascript"> $(function () { @Html.Raw(@ViewBag.JsConfigStr); //config信息验证后会执行ready方法, //所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。 //对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。 wx.ready(function () { //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: '金华人口流动申报系统', // 分享标题 link: 'http://jnga.sunmen.cn', // 分享链接 imgUrl: 'http://jnga.su 14796 nmen.cn/images/wx.jpg', // 分享图标 success: function () { // 用户确认分享后执行的回调函数 alert("用户确认分享后--执行的回调函数"); }, cancel: function () { // 用户取消分享后执行的回调函数 alert("用户取消分享后--执行的回调函数") } }); wx.onMenuShareAppMessage({ title: '金华人口流动申报系统', // 分享标题 desc: '平安金华', // 分享描述 link: 'http://jnga.sunmen.com', // 分享链接 imgUrl: 'http://jnga.sunmen.cn/images/wx.jpg', // 分享图标 type: 'link', // 分享类型,music、video或link,不填默认为link dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空 success: function () { // 用户确认分享后执行的回调函数 alert("用户确认分享后--执行的回调函数"); }, cancel: function () { // 用户取消分享后执行的回调函数 alert("用户取消分享后--执行的回调函数") } }); }); wx.error(function (res) { //config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。 }); }); </script>
WebPageAuthorize (网页授权类)
using Codeplex.Data; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using WeiXinPublic.utils; namespace WeiXinPublic.web_page_service { /// <summary> /// 网页授权 /// </summary> public class WebPageAuthorize { /// <summary> /// 网页授权:第一步:用户同意授权,获取code,该方法在入口处调用 /// </summary> /// <param name="appid">公众号的唯一标识</param> /// <param name="redirect_uri">授权后重定向的回调链接地址,请使用urlencode对链接进行处理</param> /// <param name="scope">应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)</param> /// <param name="state">重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节</param> public static void RedirectUrl(string appid, string redirect_uri, string scope, string state) { string response_type = "code"; string url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appid + "&redirect_uri=" + redirect_uri + "&response_type=" + response_type + "&scope=" + scope + "&state=" + state + "#wechat_redirect"; System.Web.HttpContext.Current.Response.Redirect(url); /* https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect 如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数redirect_uri?state=STATE code说明 :code作为换取access_token的票据【网页授权特有的接口调用凭证(网页授权access_token)】,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。 回调页面接收code 和 state * * 通过这一步,回调页面 只能再微信浏览器打开 */ } /// <summary> /// 网页授权:第二步:通过code换取网页授权access_token /// </summary> /// <param name="APPID">公众号的唯一标识</param> /// <param name="SECRET">公众号的appsecret</param> /// <param name="CODE">填写第一步获取的code参数</param> /// <returns></returns> private static string get_web_page_authorize_accesstoken(string appid, string secret, string code) { /* 首先请注意,这里通过code换取的是一个特殊的网页授权access_token,与基础支持中的access_token(该access_token用于调用其他接口)不同。 公众号可通过下述接口来获取网页授权access_token。 如果网页授权的作用域为snsapi_base,则本步骤中获取到网页授权access_token的同时,也获取到了openid,snsapi_base式的网页授权流程即到此为止。 */ //获取code后,请求以下链接获取access_token: string res = string.Empty; string url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appid + "&secret=" + secret + "&code=" + code + "&grant_type=authorization_code"; res = Sender.Get(url); return res; } /// <summary> /// 网页授权:第二步:通过code换取网页授权access_token 实体对象 /// </summary> /// <param name="appid"></param> /// <param name="secret"></param> /// <param name="code"></param> /// <returns></returns> public static Hashtable GetWebPageAuthorizeAccessToken(string appid, string secret, string code) { string res = get_web_page_authorize_accesstoken(appid, secret, code); var json = DynamicJson.Parse(res); var access_token = json.access_token; var expires_in = json.expires_in; var refresh_token = json.refresh_token; var openid = json.openid; var scope = json.scope; //var unionid = json.unionid; //万能字典 Hashtable ht = new Hashtable(); ht.Add("access_token", access_token); //【网页授权】接口调用凭证,注意:此access_token与基础支持的access_token不同 ht.Add("expires_in", expires_in); //access_token接口调用凭证超时时间,单位(秒) // 刷新access_token // 由于access_token拥有较短的有效期,当access_token超时后,可以使用refresh_token进行刷新,refresh_token拥有较长的有效期(7天、30天、60天、90天),当refresh_token失效的后,需要用户重新授权。 ht.Add("refresh_token", refresh_token); //用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID ht.Add("openid", openid); //用户授权的作用域,使用逗号(,)分隔 ht.Add("scope", scope); //只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。详见:获取用户个人信息(UnionID机制) // ht.Add("unionid", unionid); return ht; } } }
JsConfig (Js配置生产类)
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using WeiXinPublic.dialog_service; using WeiXinPublic.utils; namespace WeiXinPublic.web_page_service { /// <summary> /// JsConfig /// </summary> public class JsConfig { /// <summary> /// 3.签名计算 生成签名字符串 /// </summary> /// <param name="noncestr">随机字符串</param> /// <param name="jsapi_ticket">有效的票据</param> /// <param name="timestamp">时间戳</param> /// <param name="url">当前网页的URL,不包含#及其后面部分</param> /// <returns></returns> private static string SignatureCompute(string noncestr, string jsapi_ticket, string timestamp, string url) { //3.签名算法 /*签名生成规则如下: 参与签名的字段包括 noncestr(随机字符串), jsapi_ticket(有效的票据), timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待 签名参数 按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。 这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。*/ #region 3-1.签名参数 按照字段名的ASCII 码从小到大排序(字典序)后 Dictionary<string, string> dic = new Dictionary<string, string>(); dic["timestamp"] = timestamp; dic["noncestr"] = noncestr; dic["url"] = url; dic["jsapi_ticket"] = jsapi_ticket; string[] arrkey = new string[] { "timestamp", "noncestr", "url", "jsapi_ticket" }; arrkey = arrkey.OrderBy(n => n).ToArray(); #endregion #region 3-2.使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1 string signatureStr = ""; foreach (string key in arrkey) { signatureStr += key + "=" + dic[key] + "&"; } signatureStr = signatureStr.Substring(0, signatureStr.Length - 1); #endregion return signatureStr; } /// <summary> /// 4.签名字符串 SHA1加密 /// </summary> /// <param name="str"></param> /// <returns></returns> private static string SignatureSha1(string str) { var sha1 = System.Security.Cryptography.SHA1.Create(); byte[] bytes = Encoding.UTF8.GetBytes(str); byte[] bytesArr = sha1.ComputeHash(bytes); StringBuilder sb = new StringBuilder(); foreach (var item in bytesArr) { sb.AppendFormat("{0:x2}", item); } return sb.ToString(); } /// <summary> /// 5.创建微信jsApi配置 字符串 /// </summary> /// <param name="appid">必填,公众号的唯一标识</param> /// <param name="timestamp">必填,生成签名的时间戳</param> /// <param name="noncestr">必填,生成签名的随机串</param> /// <param name="signatureStr">签名字符串 SHA1加密</param> /// <param name="weixinJsApiStr">需要注册的微信js接口 多个接口用,隔开</param> /// <returns></returns> private static string CreateWeiXinJsConfig(string appid, string timestamp, string noncestr, string signatureStr, string weixinJsApiStr) { //"onMenuShareTimeline,onMenuShareAppMessage,onMenuShareQQ"; string jsStr = "wx.config({"; jsStr += "debug: false,"; jsStr += "appId: '" + appid + "',"; jsStr += "timestamp: " + timestamp + ","; jsStr += "nonceStr: '" + noncestr + "',"; jsStr += "signature: '" + signatureStr + "',"; jsStr += "jsApiList: ['" + weixinJsApiStr.Replace(",", "','") + "']"; jsStr += "});"; return jsStr; } /// <summary> /// 获取微信jsApi配置字符串 /// </summary> /// <param name="weixinJsApiStr">需要注册的微信js接口 多个接口用,隔开</param> /// <returns></returns> public static string GetJsConfig(string weixinJsApiStr, string appid, string secret) { //获取随机字符串 必填,生成签名的随机串 string noncestr = Common.GetRandomStr(32); //获取时间戳 必填,生成签名的时间戳 string timestamp = Common.GetTimeStamp(); //获取当前网页地址 可以带参数 string url = System.Web.HttpContext.Current.Request.Url.AbsoluteUri; //1.获取access_token Hashtable ht_access_token = BasisSupport.GetAccessToken(appid, secret); string access_token = ht_access_token["access_token"].ToString(); //2.用第一步拿到的access_token Hashtable ht_jsapi_ticket = BasisApi.GetJsApiTicket(access_token); string ticket = ht_jsapi_ticket["ticket"].ToString(); //3.签名计算 生成签名字符串 string signatureStr = SignatureCompute(noncestr, ticket, timestamp, url); //4.签名字符串 SHA1加密 必填,签名,见附录1 signatureStr = SignatureSha1(signatureStr); return CreateWeiXinJsConfig(appid, timestamp, noncestr, signatureStr, weixinJsApiStr); } } }
Common 公共类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace WeiXinPublic.utils { public class Common { /// <summary> /// 获取客户端浏览器的原始用户代理信息。 /// </summary> /// <returns></returns> public static string GetRequestUserAgent() { return System.Web.HttpContext.Current.Request.UserAgent.ToString(); //获取客户端浏览器的原始用户代理信息。 } /// <summary> /// 判断是否微信浏览器 /// </summary> /// <returns></returns> public static bool IsWeixinBrowser() { string userAgent = GetRequestUserAgent(); return userAgent.IndexOf("MicroMessenger") > 0 ? true : false; } /// <summary> /// 获取随机字符串 /// </summary> /// <param name="length"></param> /// <returns></returns> public static string GetRandomStr(int length) { string str = "0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"; Random random = new Random(); string res = ""; for (int i = 0; i < length; i++) { int index = random.Next(str.Length); res += str.Substring(index, 1); } return res; } /// <summary> /// 获取时间戳 /// </summary> /// <returns></returns> public static string GetTimeStamp() { TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1); return Convert.ToInt64(ts.TotalSeconds).ToString(); } } }
BasisApi (基础接口类)
using Codeplex.Data; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using WeiXinPublic.utils; namespace WeiXinPublic.web_page_service { /// <summary> /// 基础接口 /// 1.判断当前客户端版本是否支持指定JS接口 /// 2.获取jsapi_ticket /// </summary> public class BasisApi { #region 获取jsapi_ticket /// <summary> /// 获得jsapi_ticket 采用http GET方式请求获得jsapi_ticket (有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket) 附录1-JS-SDK使用权限签名算法 /// </summary> /// <param name="accesstoken"></param> /// <returns></returns> private static string get_jsapi_ticket(string accesstoken) { string res = string.Empty; object obj = CacheHelper.GetCache("jsapi_ticket"); if (obj != null) { res = obj.ToString(); } else { string url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accesstoken + "&type=jsapi"; //GET方式请求 res = Sender.Get(url); CacheHelper.AddCache("jsapi_ticket", res, DateTime.Now.AddMinutes(100)); //jsapi_ticket的有效期目前为2个小时 } return res; } /* jsapi_ticket { "errcode":0, "errmsg":"ok", "ticket":"sM4AOVdWfPE4DxkXGEs8VFg9ITyPm9rZNXtk60kDcOW37rgw8PSTCg3DR9CEHATN4k4oIC8uzsCGbhKHykHjdA", "expires_in":7200 } */ /// <summary> /// 获取jsapi_ticket /// </summary> /// <param name="accesstoken"></param> /// <returns></returns> public static Hashtable GetJsApiTicket(string accesstoken) { string res = get_jsapi_ticket(accesstoken); var json = DynamicJson.Parse(res); var errcode = json.errcode; var errmsg = json.errmsg; var ticket = json.ticket; var expires_in = json.expires_in; //万能字典 Hashtable ht = new Hashtable(); ht.Add("errcode", errcode); ht.Add("errmsg", errmsg); ht.Add("ticket", ticket); ht.Add("expires_in", expires_in); return ht; } #endregion } }
类库结构
相关文章推荐
- 微信公众号开发系列-网页授权获取用户基本信息
- C#微信公众号开发-高级接口-之网页授权oauth2.0获取用户基本信息(二)
- 微信公众号开发系列-网页授权获取用户基本信息
- 微信公众号开发之网页授权获取用户基本信息
- 微信公众号开发系列-网页授权获取用户基本信息
- C#微信公众号开发之网页授权oauth2.0获取用户基本信息(一)
- Java微信公众号开发:网页授权获取用户基本信息
- 微信公众号开发系列-网页授权获取用户基本信息
- C#微信公众号开发--网页授权(oauth2.0)获取用户基本信息一
- 微信公众平台开发 网页授权获取用户基本信息
- 夺命雷公狗---微信开发53----网页授权(oauth2.0)获取用户基本信息接口(3)实现世界留言版
- 公众号开发网页授权获取用户基本信息不弹出提示用户选择是否授权
- 微信公众平台开发 网页授权获取用户基本信息
- 微信公众平台开发(71) 网页授权获取用户基本信息
- 微信公众平台开发文档 网页授权获取用户基本信息
- 微信公众平台开发教程第5篇-----网页授权获取用户基本信息
- 微信公众平台开发-网页授权获取用户基本信息
- 微信公众平台开发 OAuth2.0网页授权获取用户基本信息一些知识
- 微信公众平台开发(71) 网页授权获取用户基本信息
- 微信开发公共服务平台开发(.Net) - 网页授权获取用户基本信息