微信是个坑货4-网页授权
功能:认证服务号通过网页授权获取用户信息
--公众号后台配置
》此次设置的是网页授权域名,设置成你调试的域名或者正式备案的域名(不带http或https)。
--自定义菜单设置
设置参数:
appid:微信公众号的appid
uri:微信网页授权后跳转的网页(该uri需经过UrlEncode编码)
scope:此处使用 snsapi_userinfo方式
关于网页授权的两种scope的区别说明
1、以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)
2、以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。
--授权步骤
1 第一步:用户同意授权,获取code
2 第二步:通过code换取网页授权access_token
3 第三步:刷新access_token(如果需要)
4 第四步:拉取用户信息(需scope为 snsapi_userinfo)
--后台代码
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Xml; namespace wxweb.Areas.wechatPage.Controllers { public class service_PersonalController : Controller { // GET: wechatPage/service_Personal public ActionResult Index() { //--------------微信oauth授权--------------- wxPlatForm.OAuth.wechatOAuth oauth = new wxPlatForm.OAuth.wechatOAuth(); oauth.appid = appid;//微信公众号的appid oauth.secret = secret;//微信公众号的AppSecret oauth.get_code();//获取token及userinfo信息 if (oauth.o_user != null) { //获取用户信息成功,继续逻辑业务操作 } else { return RedirectToAction("Error", "service_Personal"); } //--------------end微信oauth授权--------------- return View(); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Web; using System.Web.Script.Serialization; namespace wxPlatForm.OAuth { public class wechatOAuth { /// <summary> /// 公众号的唯一标识 /// </summary> public string appid; /// <summary> /// 公众号的appsecret /// </summary> public string secret; public OAuthAccess_Token o_token; public OAuthUser o_user; private string code; /// <summary> /// 获取code /// </summary> public void get_code() { try { code = HttpContext.Current.Request.QueryString["Code"]; if (code != ""&&code!=null) { get_access_token(); } } catch (Exception ex) { common.CommonMethod.WriteTxt(ex.Message); } } /// <summary> /// 通过code换取网页授权access_token /// </summary> public void get_access_token() { Dictionary<string, string> obj = new Dictionary<string, string>(); var client = new System.Net.WebClient(); var serializer = 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, secret, code); client.Encoding = System.Text.Encoding.UTF8; string dataaccess = ""; try { dataaccess = client.DownloadString(url); //获取字典 obj = serializer.Deserialize<Dictionary<string, string>>(dataaccess); string accessToken = ""; if (obj.TryGetValue("access_token", out accessToken)) //判断access_Token是否存在 { o_token =new OAuthAccess_Token { access_token=obj["access_token"], expires_in =Convert.ToInt32( obj["expires_in"]), refresh_token = obj["refresh_token"], openid = obj["openid"], scope = obj["scope"] }; if (o_token.scope == "snsapi_userinfo") { get_userinfo(o_token.access_token, o_token.openid); } } else //access_Token 失效时重新发送。 { //存log方法 common.CommonMethod.WriteTxt("access_token 获取失败,time:"+DateTime.Now.ToLongTimeString()); } } catch (Exception e) { //存log方法 common.CommonMethod.WriteTxt(e.Message); } } /// <summary> /// 拉取用户信息(需scope为 snsapi_userinfo) /// </summary> /// <param name="access_token">网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同</param> /// <param name="access_token"> 用户的唯一标识</param> public void get_userinfo(string access_token,string openid) { Dictionary<string, object> obj = new Dictionary<string, object>(); var client = new System.Net.WebClient(); JavaScriptSerializer serializer = new JavaScriptSerializer(); string url = string.Format("https://api.weixin.qq.com/sns/userinfo?access_token={0}&openid={1}&lang=zh_CN", access_token, openid); client.Encoding = System.Text.Encoding.UTF8; string dataaccess = ""; try { dataaccess = client.DownloadString(url); obj = serializer.Deserialize<Dictionary<string, object>>(dataaccess); object user_openid = ""; if (obj.TryGetValue("openid", out user_openid)) //判断access_Token是否存在 { o_user = new OAuthUser { openid = obj["openid"].ToString(), nickname = obj["nickname"].ToString(), sex =Convert.ToInt32( obj["sex"]), province = obj["province"].ToString(), city = obj["city"].ToString(), country = obj["country"].ToString(), headimgurl = obj["headimgurl"].ToString(), privilege =obj["privilege"].ToString(), unionid ="" }; } else //access_Token 失效时重新发送。 { //存log方法 common.CommonMethod.WriteTxt("用户信息 获取失败,time:" + DateTime.Now.ToLongTimeString()); } } catch (Exception e) { //存log方法 common.CommonMethod.WriteTxt(e.Message); } } /// <summary> /// 检验授权凭证(access_token)是否有效 /// </summary> /// <param name="appid">公众号的唯一标识</param> /// <param name="refresh_token">填写通过access_token获取到的refresh_token参数</param> public void refresh_access_token(string refresh_token) { Dictionary<string, string> obj = new Dictionary<string, string>(); var client = new System.Net.WebClient(); var serializer = new JavaScriptSerializer(); string url = string.Format("https://api.weixin.qq.com/sns/oauth2/refresh_token?appid={0}&grant_type=refresh_token&refresh_token={1}", this.appid, refresh_token); client.Encoding = System.Text.Encoding.UTF8; string dataaccess = ""; try { dataaccess = client.DownloadString(url); //获取字典 obj = serializer.Deserialize<Dictionary<string, string>>(dataaccess); string accessToken = ""; if (obj.TryGetValue("access_token", out accessToken)) //判断access_Token是否存在 { OAuthAccess_Token o_token = new OAuthAccess_Token { access_token = obj["access_token"], expires_in = Convert.ToInt32(obj["expires_in"]), refresh_token = obj["refresh_token"], openid = obj["openid"], scope = obj["scope"] }; if (o_token.scope == "snsapi_userinfo") { get_userinfo(o_token.access_token, o_token.openid); } } else //access_Token 失效时重新发送。 { //存log方法 common.CommonMethod.WriteTxt("access_token 获取失败,time:" + DateTime.Now.ToLongTimeString()); } } catch (Exception e) { //存log方法 common.CommonMethod.WriteTxt(e.Message); } } /// <summary> /// 刷新access_token(如果需要) /// </summary> public void check_access_token() { } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace wxPlatForm.OAuth { public class OAuthAccess_Token { public string access_token { get; set; } public int expires_in { get; set; } public string refresh_token { get; set; } /// <summary> /// 用户针对当前公众号的唯一标识 /// 关注后会产生,返回公众号下页面也会产生 /// </summary> public string openid { get; set; } public string scope { get; set; } /// <summary> /// 当前用户的unionid,只有在用户将公众号绑定到微信开放平台帐号后 /// </summary> public string unionid { get; set; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace wxPlatForm.OAuth { /// <summary> /// 授权之后获取用户基本信息 /// </summary> public class OAuthUser { public string openid { get; set; } public string nickname { get; set; } public int sex { get; set; } public string province { get; set; } public string city { get; set; } public string country { get; set; } public string headimgurl { get; set; } /// <summary> /// 用户特权信息,json 数组 /// </summary> //public JArray privilege { get; set; } public string privilege { get; set; } public string unionid { get; set; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.IO; using System.Web; using System.Web.Script.Serialization; namespace common { /// <summary> /// 通用方法类 /// </summary> public class CommonMethod { #region 记录bug,以便调试 /// <summary> /// 记录bug,以便调试 /// </summary> public static bool WriteTxt(string str) { try { string LogPath = HttpContext.Current.Server.MapPath("/err_log/"); if (!Directory.Exists(LogPath)) { Directory.CreateDirectory(LogPath); } FileStream FileStream = new FileStream(System.Web.HttpContext.Current.Server.MapPath("/err_log//xiejun_" + DateTime.Now.ToLongDateString() + "_.txt"), FileMode.Append); StreamWriter StreamWriter = new StreamWriter(FileStream); //开始写入 StreamWriter.WriteLine(str); //清空缓冲区 StreamWriter.Flush(); //关闭流 StreamWriter.Close(); FileStream.Close(); } catch (Exception) { return false; } return true; } #endregion } }