C#微信公众平台开发一网页受权前端
在开发公众号时常常会遇到有些功能须要用户登陆后才能使用,咱们本身编写的程序或许有自带登陆页面,但用户每次都要输入帐号密码非常麻烦,因此考虑可否用微信帐号受权登陆,这样只要受权过了,除非受权过时,不然都不须要从新登陆,接下来咱们来研究如何完成受权操做。web
1、为了实现网页受权功能,须要解决的问题api
一、微信网页受权是经过在微信客户端调用受权接口,用户赞成受权后微信调用咱们指定的回调函数进行后续业务操做,在这里比较特殊的是回调函数必须是在某个域名下,因此开发者须要先到公众平台官网中的“开发 - 接口权限 - 网页服务 - 网页账号 - 网页受权获取用户基本信息”的配置选项中,修改受权回调域名。安全
二、经过开发者ID及密码调用获取access_token接口时,须要设置访问来源IP(上述域名所在服务器的外网IP地址)为白名单,可在 开发 -> 基本配置 -> 公众号开发信息 -> IP白名单 进行设置。服务器
2、实现步骤微信
1 第一步:用户赞成受权,获取codeapp
在确保微信公众帐号拥有受权做用域(scope参数)的权限的前提下(服务号得到高级接口后,默认拥有scope参数中的snsapi_base和snsapi_userinfo),引导关注者打开以下页面,能够经过微信客户端打开或使用微信web开发者工具打开:微信公众平台
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect 若提示“该连接没法访问”,请检查参数是否填写错误,是否拥有scope参数对应的受权做用域权限。
尤为注意:因为受权操做安全等级较高,因此在发起受权请求时,微信会对受权连接作正则强匹配校验,若是连接的参数顺序不对,受权页面将没法正常访问函数
参考实例(微信web开发者工具)工具
参数说明
参数 | 是否必须 | 说明 |
---|---|---|
appid | 是 | 公众号的惟一标识(能够点开 开发-> 基本配置 查看) |
redirect_uri | 是 | 受权后重定向的回调连接地址, 请使用 urlEncode 对连接进行处理(前面已经说过,咱们的回调函数需部署到域名下,这里的地址就回调函数的地址) |
response_type | 是 | 返回类型,请填写code |
scope | 是 | 应用受权做用域,snsapi_base (不弹出受权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出受权页面,可经过openid拿到昵称、性别、所在地。而且, 即便在未关注的状况下,只要用户受权,也能获取其信息 ) |
state | 否 | 重定向后会带上state参数,开发者能够填写a-zA-Z0-9的参数值,最多128字节 |
#wechat_redirect | 是 | 不管直接打开仍是作页面302重定向时候,必须带此参数 |
2 第二步:经过code换取网页受权access_token
HttpWebRequest 请求方法
/// <summary> /// postweb请求 /// </summary> /// <param name="postUrl"></param> /// <param name="paramData"></param> /// <param name="dataEncode"></param> /// <returns></returns> public static string PostWebRequest(string postUrl, string paramData) { string ret = string.Empty; try { byte[] byteArray = Encoding.UTF8.GetBytes(paramData); HttpWebRequest webReq = WebRequest.Create(postUrl) as HttpWebRequest; webReq.Method = "GET"; HttpWebResponse response = (HttpWebResponse)webReq.GetResponse(); StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8); ret = sr.ReadToEnd(); sr.Close(); response.Close(); } catch (Exception ex) { throw ex; } return ret; }
调用微信接口获取access_token信息
public Dictionary<string, object> get_access_token(string code) { JavaScriptSerializer Jss = new JavaScriptSerializer(); string url = string.Format("https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code", "AppID", "AppSecret", code); Dictionary<string, object> respDic = (Dictionary<string, object>)Jss.DeserializeObject(PostWebRequest(url, "")); return respDic; }
3 第三步:刷新access_token(若是须要)
因为access_token有,涉及access_token的获取access_token的接口是有次数限制的,因此我推荐你们作一个全局变量存储,定时刷新,请参考《C#微信公众平台开发—access_token的获取存储与更新》
4 第四步:拉取用户信息(需scope为 snsapi_userinfo)
根据第二步获取到的access_token调用微信接口获取用户信息
/// <summary> /// 用openid换取用户信息 /// </summary> /// <param name="openid">微信标识id</param> /// <returns></returns> public Dictionary<string, object> GetUserInfo(string code) { JavaScriptSerializer Jss = new JavaScriptSerializer(); Dictionary<string, object> access_info = get_access_token(code);//获取access_token string url = string.Format("https://api.weixin.qq.com/sns/userinfo?access_token={0}&openid={1}&lang=zh_CN", access_info["access_token"], access_info["openid"]); Dictionary<string, object> respDic = (Dictionary<string, object>)Jss.DeserializeObject(PostWebRequest(url, "")); return respDic; }
5 第五步:将上述获取的用户信息展现到客户端上
在受权回调函数中完成相关业务
/// <summary> /// 受权回调函数 /// </summary> /// <returns></returns> public ActionResult Index() { try { var code = Request.QueryString["code"]; //获取回调返回的code if (!string.IsNullOrEmpty(code)) { Dictionary<string, object> DicJson = GetUserInfo(code.ToString()); //获取用户信息 ViewBag.nickname = DicJson["nickname"]; ViewBag.openid = DicJson["openid"]; ViewBag.province = DicJson["province"]; ViewBag.city = DicJson["city"]; ViewBag.country = DicJson["country"]; switch (DicJson["sex"].ToString()) { case "1":ViewBag.sex = "男";break; case "2": ViewBag.sex = "女"; break; default: ViewBag.sex = "未知"; break; } ViewBag.Error = "获取用户信息成功"; } else { ViewBag.nickname = ""; ViewBag.openid = ""; ViewBag.province = ""; ViewBag.city = ""; ViewBag.unionid = ""; ViewBag.code = ""; ViewBag.Error = "code没找到!"; } } catch (Exception ex) { ViewBag.nickname = ""; ViewBag.openid = ""; ViewBag.province = ""; ViewBag.city = ""; ViewBag.unionid = ""; ViewBag.Error = ex.Message; } return View(); }
前端代码参考(这里主要是为了测试,因此没有细调样式,你们凑合着看)
@{ ViewBag.Title = "Home Page"; } <div class="jumbotron"> <h1>获取用户信息</h1> </div> <div class="row"> <div class="col-md-4"> <h2>用户名</h2> <p>@ViewBag.nickname</p> </div> <div class="col-md-4"> <h2>OpenID</h2> <p>@ViewBag.openid</p> </div> <div class="col-md-4"> <h2>性别</h2> <p>@ViewBag.sex</p> </div> </div> <div class="row"> <div class="col-md-4"> <h2>国家</h2> <p>@ViewBag.country</p> </div> <div class="col-md-4"> <h2>省份</h2> <p>@ViewBag.province</p> </div> <div class="col-md-4"> <h2>城市</h2> <p>@ViewBag.city</p> </div> </div> <div class="row"> <div class="col-md-12"> <h2>错误信息</h2> <p>@ViewBag.Error</p> </div> </div>