后面代碼需要用到的參數、方法、類
private string WeChatRedirectUrl = "www.test.com";//需要被授權的頁面地址 //對頁面進行授權重新返回的新地址,新地址包含code private string WeChatOauth2Url = @"https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope=snsapi_userinfo&state=STATE#123"; private string WeChatAccessTokenUrl = @"https://api.weixin.qq.com/sns/oauth2/access_token";//網頁授權access_token,獲取用戶唯一標識openID private string WeChatUserInfoUrl = @"https://api.weixin.qq.com/sns/userinfo";//獲取用戶信息地址 private string WeChatAppId = "wx123456789abcdefg";//公眾號的唯一標識 private string WeChatAppSecret = "a6d6ccf8182fn2a5a8e1ae1234e638c9";//公眾號的appsecret /// <summary> /// GET請求 /// </summary> /// <param name="Url">The URL.</param> /// <param name="postDataStr">The post data string.</param> /// <returns>System.String.</returns> public static string HttpGet(string Url, string postDataStr = "") { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url + (postDataStr == "" ? "" : "?") + postDataStr); request.Method = "GET"; request.ContentType = "text/html;charset=UTF-8"; HttpWebResponse response = (HttpWebResponse)request.GetResponse(); Stream myResponseStream = response.GetResponseStream(); StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8")); string retString = myStreamReader.ReadToEnd(); myStreamReader.Close(); myResponseStream.Close(); return retString; } public class JsonHelper { public JsonHelper() { // // TODO: Add constructor logic here // } /// <summary> /// 把對象序列化 JSON 字符串 /// </summary> /// <typeparam name="T">對象類型</typeparam> /// <param name="obj">對象實體</param> /// <returns>JSON字符串</returns> public static string GetJson<T>(T obj) { DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(T)); using (MemoryStream ms = new MemoryStream()) { json.WriteObject(ms, obj); string szJson = Encoding.UTF8.GetString(ms.ToArray()); return szJson; } } /// <summary> /// 把JSON字符串還原為對象 /// </summary> /// <typeparam name="T">對象類型</typeparam> /// <param name="szJson">JSON字符串</param> /// <returns>對象實體</returns> public static T ParseFormJson<T>(string szJson) { T obj = Activator.CreateInstance<T>(); using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(szJson))) { DataContractJsonSerializer dcj = new DataContractJsonSerializer(typeof(T)); return (T)dcj.ReadObject(ms); } } } //授權成功返回的信息 public class OutWechatSuccessInfo { /// <summary> /// code作為換取access_token的票據,每次用戶授權帶上的code將不一樣,code只能使用一次,5分鍾未被使用自動過期。 /// </summary> public string code { get; set; } /// <summary> /// 接口調用憑證 /// </summary> public string access_token { get; set; } /// <summary> /// access_token接口調用憑證超時時間,單位(秒) /// </summary> public int expires_in { get; set; } /// <summary> /// 用戶刷新access_token /// </summary> public string refresh_token { get; set; } /// <summary> /// 授權用戶唯一標識 /// </summary> public string openid { get; set; } /// <summary> /// 用戶授權的作用域,使用逗號(,)分隔 /// </summary> public string scope { get; set; } } //拉取的用戶信息 public class OutWeChatUserInfo { /// <summary> /// 用戶的唯一標識 /// </summary> public string openid { get; set; } /// <summary> /// 用戶昵稱 /// </summary> public string nickname { get; set; } /// <summary> /// 用戶的性別,值為1時是男性,值為2時是女性,值為0時是未知 /// </summary> public int sex { get; set; } /// <summary> /// 用戶個人資料填寫的省份 /// </summary> public string province { get; set; } /// <summary> /// 普通用戶個人資料填寫的城市 /// </summary> public string city { get; set; } /// <summary> /// 國家,如中國為CN /// </summary> public string country { get; set; } /// <summary> /// 用戶頭像,最后一個數值代表正方形頭像大小 /// </summary> public string headimgurl { get; set; } /// <summary> /// 用戶特權信息 /// </summary> public string privilege { get; set; } }
第一步:用戶同意授權,獲取code
/// <summary> /// 獲取授權后的URL /// </summary> /// <returns></returns> public async Task<ReturnJson> GetRedirectUrl() { try { string url = string.Format(WeChatOauth2Url, WeChatAppId, WeChatRedirectUrl); return ReturnJson.ToResult(ReturnCode.Success, new { redirectURL = url }); } catch (Exception e) { return ReturnJson.ToResult(ReturnCode.ServiceError, e.Message); } }
第二步:通過code換取網頁授權access_token和用戶唯一標識openID
/// <summary> /// 獲取用戶唯一標識openID /// </summary> /// <param name="code"></param> /// <returns></returns> public OutWechatSuccessInfo GetOpenID(string code) { string sUrlpara = "appid=" + WeChatAppId + "&secret=" + WeChatAppSecret + "&code=" + code + "&grant_type=authorization_code";//請求的參數 string jsonStr = HttpHelper.HttpGet(WeChatAccessTokenUrl, sUrlpara); if (jsonStr.Contains("errcode")) { return null; } //放回json解析 OutWechatSuccessInfo result = new OutWechatSuccessInfo(); result = JsonHelper.ParseFormJson<OutWechatSuccessInfo>(jsonStr); return result; }
第三步:拉取用戶信息(需scope為 snsapi_userinfo)
/// <summary> /// 拉取登錄用戶信息 /// </summary> /// <param name="accessToken"></param> /// <param name="openId"></param> /// <returns></returns> public OutWeChatUserInfo GetWeChatUserInfo(string accessToken, string openId) { string sUrlpara = "access_token=" + accessToken + "&openid=" + openId + "⟨=zh_CN"; ;//請求的參數 string jsonStr = HttpHelper.HttpGet(WeChatUserInfoUrl, sUrlpara); if (jsonStr.Contains("errcode")) { return null; } //放回json解析 OutWeChatUserInfo result = new OutWeChatUserInfo(); result = JsonHelper.ParseFormJson<OutWeChatUserInfo>(jsonStr); return result; }
補充:關於 return ReturnJson.ToResult ()這個是自己封裝的寫法,不一定要用我這個,只要能以json返回結果就行。ReturnJson.cs和EnumExtension.cs如下:
ReturnJson.cs引入命名空間:
using Common;
public class ReturnJson { public ReturnJson() { Res = new Receive(); } public static ReturnJson ToResult(ReturnCode code) { ReturnJson retJson = new ReturnJson { Code = ((int)code).ToString(), Res = new Receive { Data = new { }, Msg = code.GetEnumText() } }; return retJson; } public static ReturnJson ToResult(ReturnCode code, string msg, object data = null) { ReturnJson retJson = new ReturnJson { Code = ((int)code).ToString(), Res = new Receive { Data = data ?? new { }, Msg = msg ?? code.GetEnumText() } }; return retJson; } public static ReturnJson ToResult(ReturnCode code, object data) { ReturnJson retJson = new ReturnJson { Code = ((int)code).ToString(), Res = new Receive { Data = data ?? new { }, Msg = code.GetEnumText() } }; return retJson; } /// <summary> /// 調用返回值 /// </summary> public string Code { get; set; } public Receive Res { get; set; } } public class Receive { public Receive() { Data = new { }; } public string Msg { get; set; } public dynamic Data { get; set; } } /// <summary> /// 對外使用的返回值 /// </summary> public enum ReturnCode { /// <summary> /// 請求(或處理)成功 /// </summary> [Text("請求(或處理)成功")] Success = 0,
/// <summary> /// 參數錯誤 /// </summary> [Text("參數錯誤")] ParameterError = 409, /// <summary> /// 請求(或處理)失敗 /// </summary> [Text("請求(或處理)失敗")] Fault = 410, /// <summary> /// 系統異常 /// </summary> [Text("系統異常")] SystemError = 500, /// <summary> /// 業務處理異常 /// </summary> [Text("業務處理異常")] ServiceError = 501, }
EnumExtension.cs引入命名空間:
using System;
using System.Collections.Generic;
public static class EnumExtension { private static Dictionary<string, Dictionary<string, string>> _enumCache; private static Dictionary<string, Dictionary<string, string>> EnumCache => _enumCache ?? (_enumCache = new Dictionary<string, Dictionary<string, string>>()); /// <summary> /// 返回枚舉的Text屬性值 /// </summary> /// <param name="en">枚舉</param> /// <returns></returns> public static string GetEnumText(this Enum en) { string enString = string.Empty; if (null == en) return enString; var type = en.GetType(); enString = en.ToString(); if (!EnumCache.ContainsKey(type.FullName)) { var fields = type.GetFields(); Dictionary<string, string> temp = new Dictionary<string, string>(); foreach (var item in fields) { var attrs = item.GetCustomAttributes(typeof(TextAttribute), false); if (attrs.Length == 1) { var v = ((TextAttribute)attrs[0]).Value; temp.Add(item.Name, v); } } EnumCache.Add(type.FullName, temp); } if (EnumCache[type.FullName].ContainsKey(enString)) { return EnumCache[type.FullName][enString]; } return enString; } /// <summary> /// 獲取枚舉的value值 /// </summary> /// <param name="en">枚舉對象</param> /// <returns></returns> public static string ToIntString(this Enum en) { if (en == null) return ""; var t = en.GetType(); var field = t.GetField(en.ToString()); var e = field.GetValue(en); return ((int)e).ToString(); } } public class TextAttribute : Attribute { public TextAttribute(string value) { Value = value; } public string Value { get; set; } }