一、前期准备工作
1.接口权限表点击修改【OAuth2.0网页授权】。(读者可网上搜索什么是OAuth2.0)
注意:此处应填写与回调页面相同的域名。
2.编写正确的URL
https://open.weixin.qq.com/connect/oauth2/authorize?appid=公众号APPID &redirect_uri= RedirectUri&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
注意:
a)读者可将此URL与自定义菜单结合,利用自定义菜单中的view类型跳转,当然也有其他方式,例如发送链接给用户。
b) 此处的RedirectUri就是所谓的回调页面,需要填上完整的验证网页授权的URL,例如http://....../OAuthRedirectUri.aspx(OAuthRedirectUri.aspx为笔者进行网页授权的页面,下面会详细介绍)
c)scope 应用授权作用域
snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid);
snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)
d)URL中的&符号不可以省略,笔者第一次试验的时候就是因为少了一个&,导致失败。检查半个多小时才发现这么一个小小的错误T_T。
俗话所的好,没有好的地基怎能立起高楼大厦,这两项前期准备工作非常重要,缺一不可,一步错都将导致失败。
二、网页授权流程
1.引导用户进入授权页面同意授权,获取code
code说明 :code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
获取非常简单,string Code = Request.QueryString["code"].ToString(); 一句就搞定了。
2.通过code换取网页授权access_token(与基础支持中的access_token不同)
获取code后,请求以下链接获取access_token:
参数说明:
APPID:公众号唯一标识
secret:公众号的appsecret
code:第一步获取的code
grant_type:填写为authorization_code
正确时返回的JSON数据包如下:
{ "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE" }
3.如果需要,开发者可以刷新网页授权access_token,避免过期
获取第二步的refresh_token后,请求以下链接获取access_token:
参数说明:
APPID:公众号唯一标识
grant_type:填写为refresh_token
refresh_token:填写通过access_token获取到的refresh_token参数
正确时返回的JSON数据包如下:
{ "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE" }
4.通过网页授权access_token和openid获取用户基本信息
https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
参数说明:
access_token:填写步骤2获取的access_token
oppenid:用户的唯一标识(每个用户对公众号的oppenid都是唯一的)填写步骤3获取的oppenid
lang:返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语
正确时返回的JSON数据包如下:
{ "openid":" OPENID", " nickname": NICKNAME, "sex":"1", "province":"PROVINCE" "city":"CITY", "country":"COUNTRY", "headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46", "privilege":[ "PRIVILEGE1" "PRIVILEGE2" ] }
以上便是网页授权流程,通过网页授权可以获取用户的oppenid、用户昵称(nickname)、用户性别(sex,1为男性)、省份(province)、城市(city)、国家(country)、用户头像(headimgurl)、用户特权信息(privilege)
三、完整的OAuthRedirectUri.aspx(C#后台代码)
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.IO; using System.Text; using System.Runtime.Serialization.Json; using System.Net; public partial class OAuthRedirectUri : System.Web.UI.Page { string Appid = "";//公众号APPID string appsecret = "";//公众号secret protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { if (!string.IsNullOrEmpty(Request.QueryString["code"])) { string Code = Request.QueryString["code"].ToString(); //获得Token OAuth_Token Model = Get_token(Code); //Response.Write(Model.access_token); OAuthUser OAuthUser_Model = Get_UserInfo(Model.access_token, Model.openid); Response.Write("用户OPENID:" + OAuthUser_Model.openid + "<br>用户昵称:" + OAuthUser_Model.nickname + "<br>性别:" + OAuthUser_Model.sex + "<br>所在省:" + OAuthUser_Model.province + "<br>所在市:" + OAuthUser_Model.city + "<br>所在国家:" + OAuthUser_Model.country + "<br>头像地址:" + OAuthUser_Model.headimgurl + "<br>用户特权信息:" + OAuthUser_Model.privilege); } } } //获得Token protected OAuth_Token Get_token(string Code) { string Str = GetJson("https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + Appid + "&secret=" + appsecret + "&code=" + Code + "&grant_type=authorization_code"); OAuth_Token Oauth_Token_Model = JsonHelper.ParseFromJson<OAuth_Token>(Str); return Oauth_Token_Model; } //刷新Token protected OAuth_Token refresh_token(string REFRESH_TOKEN) { string Str = GetJson("https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" + Appid + "&grant_type=refresh_token&refresh_token=" + REFRESH_TOKEN); OAuth_Token Oauth_Token_Model = JsonHelper.ParseFromJson<OAuth_Token>(Str); return Oauth_Token_Model; } //获得用户信息 protected OAuthUser Get_UserInfo(string REFRESH_TOKEN, string OPENID) { // Response.Write("获得用户信息REFRESH_TOKEN:" + REFRESH_TOKEN + "||OPENID:" + OPENID); string Str = GetJson("https://api.weixin.qq.com/sns/userinfo?access_token=" + REFRESH_TOKEN + "&openid=" + OPENID); OAuthUser OAuthUser_Model = JsonHelper.ParseFromJson<OAuthUser>(Str); return OAuthUser_Model; } protected string GetJson(string url) { WebClient wc = new WebClient(); wc.Credentials = CredentialCache.DefaultCredentials; wc.Encoding = Encoding.UTF8; string returnText = wc.DownloadString(url); if (returnText.Contains("errcode")) { //可能发生错误 } //Response.Write(returnText); return returnText; } public class OAuth_Token { public OAuth_Token() { // //TODO: 在此处添加构造函数逻辑 // } //access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同 //expires_in access_token接口调用凭证超时时间,单位(秒) //refresh_token 用户刷新access_token //openid 用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID //scope 用户授权的作用域,使用逗号(,)分隔 public string access_token { get; set; } public string expires_in { get; set; } public string refresh_token { get; set; } public string openid { get; set; } public string scope { get; set; } } public class OAuthUser { public OAuthUser() { } #region 数据库字段 private string _openID; private string _searchText; private string _nickname; private string _sex; private string _province; private string _city; private string _country; private string _headimgUrl; private string _privilege; #endregion #region 字段属性 /// <summary> /// 用户的唯一标识 /// </summary> public string openid { set { _openID = value; } get { return _openID; } } /// <summary> /// /// </summary> public string SearchText { set { _searchText = value; } get { return _searchText; } } /// <summary> /// 用户昵称 /// </summary> public string nickname { set { _nickname = value; } get { return _nickname; } } /// <summary> /// 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知 /// </summary> public string sex { set { _sex = value; } get { return _sex; } } /// <summary> /// 用户个人资料填写的省份 /// </summary> public string province { set { _province = value; } get { return _province; } } /// <summary> /// 普通用户个人资料填写的城市 /// </summary> public string city { set { _city = value; } get { return _city; } } /// <summary> /// 国家,如中国为CN /// </summary> public string country { set { _country = value; } get { return _country; } } /// <summary> /// 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空 /// </summary> public string headimgurl { set { _headimgUrl = value; } get { return _headimgUrl; } } /// <summary> /// 用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)其实这个格式称不上JSON,只是个单纯数组 /// </summary> public string privilege { set { _privilege = value; } get { return _privilege; } } #endregion } public class JsonHelper { /// <summary> /// 生成Json格式 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="obj"></param> /// <returns></returns> public static string GetJson<T>(T obj) { DataContractJsonSerializer json = new DataContractJsonSerializer(obj.GetType()); using (MemoryStream stream = new MemoryStream()) { json.WriteObject(stream, obj); string szJson = Encoding.UTF8.GetString(stream.ToArray()); return szJson; } } /// <summary> /// 获取Json的Model /// </summary> /// <typeparam name="T"></typeparam> /// <param name="szJson"></param> /// <returns></returns> public static T ParseFromJson<T>(string szJson) { T obj = Activator.CreateInstance<T>(); using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(szJson))) { DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType()); return (T)serializer.ReadObject(ms); } } } }