C#微信公衆平臺開發一網頁受權

 

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>
相關文章
相關標籤/搜索