在開發微信應用的時候,咱們每每須要確認用戶的身份,通常公衆號惟一區別用戶的身份是openid信息,可是這個信息並非能夠直接獲取到,須要經過code進行獲取,而code的獲取則須要用戶進行一個受權的處理才能得到,本篇隨筆經過結合Session的方式,自動判斷用戶狀態,若是用戶首次訪問頁面,則以重定向的方式實現用戶身份信息的獲取並轉回原來頁面。api
以前爲了在某個頁面裏面獲取用戶身份信息,須要把URL進行一個受權的處理URL,以下所示。微信
經過這樣的方式處理,咱們能夠在頁面處理裏面,得到code參數,而後根據code參數獲取openid。session
string code = Request.QueryString["code"];
var result = baseApi.GetAuthToken(accountInfo.AppID, accountInfo.AppSecret, code); if (result != null && !string.IsNullOrEmpty(result.openid)) { Session["openid"] = result.openid;//存儲在Session }
其中 GetAuthToken 是咱們根據微信API進行封裝的一個經過code換取網頁受權access_token的接口方法。微信開發
/// <summary> /// 經過code換取網頁受權access_token /// 首先請注意,這裏經過code換取的是一個特殊的網頁受權access_token,與基礎支持中的access_token(該access_token用於調用其餘接口)不一樣。 /// 公衆號可經過下述接口來獲取網頁受權access_token。 /// 若是網頁受權的做用域爲snsapi_base,則本步驟中獲取到網頁受權access_token的同時,也獲取到了openid,snsapi_base式的網頁受權流程即到此爲止。 /// </summary> /// <param name="appId">公衆號的惟一標識</param> /// <param name="appSecret">公衆號的appsecret</param> /// <param name="code">code做爲換取access_token的票據,每次用戶受權帶上的code將不同,code只能使用一次,5分鐘未被使用自動過時。</param> /// <param name="grantType">填寫爲authorization_code</param> /// <returns></returns> public AccessTokenResult GetAuthToken(string appId, string appSecret, string code, string grantType = "authorization_code") { var key = code + "_AuthToken"; AccessTokenResult itemResult = MemoryCacheHelper.GetItem<AccessTokenResult>(key); if (itemResult == null) { var url = string.Format("https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type={3}", appId, appSecret, code, grantType); var authToken = WeJsonHelper<AccessTokenResult>.ConvertJson(url); MemoryCacheHelper.AddItem(key, authToken);//先加入一個獲取的值 } //而後每次從其中取,若是超過期間則啓用刷新機制 var access_token = MemoryCacheHelper.GetCacheItem<AccessTokenResult>(key, delegate() { return RefreshAuthToken(appId, itemResult.access_token); }, new TimeSpan(0, 0, 7000)//7000秒過時 ); return access_token; }
這種方式可以正常獲取openid,不過每一個菜單這樣進行URL處理,而且每次重複這樣的邏輯獲取openid,確定不是什麼好的辦法。app
所以考慮一種通用的方式來處理,以減小這些曲折處理過程。函數
上面提出了,採用常規處理方式,菜單URL須要先轉移,後臺重複處理code的轉換,很是不方便咱們開發業務功能。ui
其實咱們能夠把以上獲取用戶身份的處理放置在一個通用函數裏面,這樣每次確保得到Openid便可,若是第一次訪問頁面,那麼記錄當前頁面地址,並重定向到獲取code的頁面,並解析code爲openid便可,而後放在Session裏面存儲起來,下次直接讀取Session獲取便可。url
咱們首先在入口頁面裏面記錄當前頁面地址,而後轉去判斷並獲取openid便可。spa
若是在session裏面沒有獲取到Openid,那麼認爲是第一訪問頁面,從新判斷是否有code進來,若是沒有,先獲取code,而後轉回到當前的 AuthOpenId 地址入口來。 code
/// <summary> /// 經過從新轉向,獲取用戶code並轉換爲openid。 /// 用於自動獲取當前用戶的身份。 /// </summary> /// <returns></returns> protected ActionResult AuthOpenId() { //先判斷Session是否存在 var open_id = Session["openid"]; if (open_id == null) { //若是第一次(沒有code),則再次轉到受權頁面從新獲取code string code = Request.QueryString["code"]; if (string.IsNullOrEmpty(code)) { var authUrl = baseApi.GetAuthorizeUrl(accountInfo.AppID, Request.Url.AbsoluteUri, "", OAuthScope.snsapi_base); Response.Redirect(authUrl); return null; }
若是是已經獲取到了code,則根據code進行解析獲取openid,以下代碼所示。
else { //若是成功獲取code,那麼根據code獲取openid var result = baseApi.GetAuthToken(accountInfo.AppID, accountInfo.AppSecret, code); if (result != null && !string.IsNullOrEmpty(result.openid)) { //LogHelper.Info("openid:" + result.openid); Session["openid"] = result.openid;//存儲在Session } }
最後若是順利得到openid,那麼返回到最初入口的頁面地址(已經存放地址在Session裏面了)
//獲取返回的鏈接 var backUrl = Session["back_url"]; if (backUrl != null) { return Redirect(backUrl.ToString()); } else { return View("PersonalInfo");//返回我的頁面 }
整個函數的完整的代碼以下所示。
/// <summary> /// 經過從新轉向,獲取用戶code並轉換爲openid。 /// 用於自動獲取當前用戶的身份。 /// </summary> /// <returns></returns> protected ActionResult AuthOpenId() { //先判斷Session是否存在 var open_id = Session["openid"]; if (open_id == null) { //若是第一次(沒有code),則再次轉到受權頁面從新獲取code string code = Request.QueryString["code"]; if (string.IsNullOrEmpty(code)) { var authUrl = baseApi.GetAuthorizeUrl(accountInfo.AppID, Request.Url.AbsoluteUri, "", OAuthScope.snsapi_base); Response.Redirect(authUrl); return null; } else { //若是成功獲取code,那麼根據code獲取openid var result = baseApi.GetAuthToken(accountInfo.AppID, accountInfo.AppSecret, code); if (result != null && !string.IsNullOrEmpty(result.openid)) { Session["openid"] = result.openid;//存儲在Session } } } //獲取返回的鏈接 var backUrl = Session["back_url"]; if (backUrl != null) { return Redirect(backUrl.ToString()); } else { return View("PersonalInfo");//返回我的頁面 } }
這樣咱們在菜單裏面,就不須要前面所說的轉義函數處理了,全部的身份獲取都經過標準操做確保獲取用戶的openid了。
頁面的處理也變得相對容易一些,根據用戶身份顯示不一樣的視圖頁面。
/// <summary> /// 患者問診 /// </summary> /// <returns></returns> public ActionResult DrugInquiry() { Session["back_url"] = Request.Url.AbsoluteUri; AuthOpenId();//自動獲取當前用戶的身份。 string openid = (string)Session["openid"]; if (!string.IsNullOrEmpty(openid)) { //刷新配置JS的參數 RefreshTicket(); ViewBag.openid = openid; var userInfo = BLLFactory<User>.Instance.FindByOpenId(openid); if (userInfo != null) { //識別用戶身份後的處理邏輯 ............... } return View("DrugInquiry"); } else { ViewBag.Title = "沒法獲取用戶身份信息"; ViewBag.Message = "沒法獲取用戶身份信息"; ViewBag.Type = "error"; return View("info"); } }
以上就是微信開發中使用通用函數處理,以重定向的方式實現用戶身份信息的獲取並轉回原來頁面的作法,這個函數給咱們減輕了不少繁瑣的問題,而且減小了重複複製代碼來獲取用戶身份的弊端,是咱們在H5頁面裏面處理用戶身份信息的利器,但願對你們在開發微信公衆號或者企業微信,獲取用戶身份的時候,提供好的參考思路和代碼。