C#微信公眾平台開發一網頁授權


 

C#微信公眾平台開發一網頁授權

在開發公眾號時經常會遇到有些功能需要用戶登錄后才能使用,我們自己編寫的程序或許有自帶登錄頁面,但用戶每次都要輸入賬號密碼很是麻煩,所以考慮能否用微信賬號授權登錄,這樣只要授權過了,除非授權過期,否則都不需要重新登錄,接下來我們來研究如何完成授權操作。

一、為了實現網頁授權功能,需要解決的問題

1、微信網頁授權是通過在微信客戶端調用授權接口,用戶同意授權后微信調用我們指定的回調函數進行后續業務操作,在這里比較特殊的是回調函數必須是在某個域名下,所以開發者需要先到公眾平台官網中的“開發 - 接口權限 - 網頁服務 - 網頁帳號 - 網頁授權獲取用戶基本信息”的配置選項中,修改授權回調域名。

 

2、通過開發者ID及密碼調用獲取access_token接口時,需要設置訪問來源IP(上述域名所在服務器的外網IP地址)為白名單,可在 開發 -> 基本配置 -> 公眾號開發信息 -> IP白名單 進行設置。

 

二、實現步驟

1 第一步:用戶同意授權,獲取code

在確保微信公眾賬號擁有授權作用域(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>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM