微信小程序非跳轉(zhuǎn)式組件授權(quán)登錄的方法示例
首先附上官方文檔地址和授權(quán)流程
官方地址:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html
流程圖:
大致邏輯:授權(quán) -> 發(fā)送code到服務(wù)器獲取session_key - > 保存在小程序緩存內(nèi) -> 調(diào)用wx.getUserInfo和session_key獲取用戶信息 -> 登錄成功返回訪問(wèn)token -> 記錄登錄狀態(tài) -> 執(zhí)行登錄成功監(jiān)聽(tīng)(失敗則不監(jiān)聽(tīng))
直接上代碼,一下均為小程序組件模式有興趣的可以看下官方文檔
創(chuàng)建components(自定義名稱)文件夾pages文件夾同級(jí)主要放置組件文件
創(chuàng)建 authorize (自定義名稱)文件夾 還是一樣的創(chuàng)建 對(duì)應(yīng)的authorize.js ,authorize.wxml .authorize.wxss,authorize.json特別注意這里的 authorize.json 文件里面要定義當(dāng)前頁(yè)面為組件
{ "component": true }
到這里準(zhǔn)備工作完成
authorize.js 換成組件的寫(xiě)法,具體參考小程序官方文檔,這里展示我定義的
Component({ //組件的對(duì)外屬性 說(shuō)的確實(shí)很官方,用過(guò)vue組件的就很容易理解這點(diǎn) //父級(jí)向子級(jí)傳值這里就是接收值得地方 properties:{ //名稱要和父級(jí)綁定的名稱相同 //這里主要是控制自動(dòng)授權(quán)彈框是否顯示 true=隱藏 false=顯示 iShidden:{ type:Boolean,//定義類型 value: true,//定義默認(rèn)值 }, //是否自動(dòng)登錄 這里主要用于沒(méi)有授權(quán)是否自動(dòng)彈出授權(quán)提示框 //**用在不自動(dòng)登錄頁(yè)面但是某些操作需要授權(quán)登錄** isAuto:{ type: Boolean, value: true, }, }, //組件的內(nèi)部數(shù)據(jù),和 properties 一同用于組件的模板渲染 data:{ cloneIner:null }, //組件所在頁(yè)面的生命周期聲明對(duì)象 pageLifetimes:{ //頁(yè)面隱藏 hide:function(){ //關(guān)閉頁(yè)面時(shí)銷(xiāo)毀定時(shí)器 if(this.data.cloneIner) clearInterval(this.data.clearInterval); }, //頁(yè)面打開(kāi) show:function(){ //打開(kāi)頁(yè)面銷(xiāo)毀定時(shí)器 if (this.data.cloneIner) clearInterval(this.data.clearInterval); }, }, //組件生命周期函數(shù),在組件實(shí)例進(jìn)入頁(yè)面節(jié)點(diǎn)樹(shù)時(shí)執(zhí)行 attached(){ }, //組件的方法 methods:{ } });
注:以下的方法都需寫(xiě)在 methods 內(nèi)
第一步:未授權(quán)用戶判斷是否執(zhí)行授權(quán)還是直接進(jìn)行獲取用戶信息
//檢測(cè)登錄狀態(tài)并執(zhí)行自動(dòng)登錄 setAuthStatus(){ var that = this; that.setErrorCount(); wx.getSetting({ success(res) { //這里會(huì)檢測(cè)是否授權(quán),如果授權(quán)了會(huì)直接調(diào)用自動(dòng)登錄 if (!res.authSetting['scope.userInfo']) { //沒(méi)有授權(quán)不會(huì)自動(dòng)彈出登錄框 if (that.data.isAuto === false) return; //自動(dòng)彈出授權(quán) that.setData({ iShidden: false }); } else { //自動(dòng)登錄 that.setData({ iShidden: true }); if (app.globalData.token) { //這里是授權(quán)回調(diào) that.triggerEvent('onLoadFun', app.globalData.token); that.WatchIsLogin(); } else { wx.showLoading({ title: '正在登錄中' }); //這里是已授權(quán)調(diào)用wx.getUserInfo that.getUserInfoBydecryptCode(); } } } }) }
第二步,沒(méi)有授權(quán)執(zhí)行打開(kāi)授權(quán)彈出框
//授權(quán) setUserInfo(e){ var that = this, pdata={}; pdata.userInfo = e.detail.userInfo; pdata.spid = app.globalData.spid; wx.showLoading({ title: '正在登錄中' }); wx.login({ success: function (res) { if (!res.code) return app.Tips({ title: '登錄失??!' + res.errMsg}); //獲取session_key并緩存 that.getSessionKey(res.code, function () { that.getUserInfoBydecryptCode(); }); }, fail() { wx.hideLoading(); } }) }, //從緩存中獲取session_key,如果沒(méi)有則請(qǐng)求服務(wù)器再次緩存 getSessionKey(code,successFn,errotFn){ var that=this; wx.checkSession({ success: function (res){ if(wx.getStorageSync('session_key')) successFn && successFn(); else that.setCode(code, successFn, errotFn); }, fail:function(){ that.setCode(code, successFn, errotFn); } }); }, //訪問(wèn)服務(wù)器獲得session_key 并存入緩存中 setCode(code, successFn, errotFn){ var that = this; app.basePost(app.U({ c: 'Login', a: 'setCode' }), { code: code }, function (res) { wx.setStorageSync('session_key', res.data.session_key); successFn && successFn(res); }, function (res) { if (errotFn) errotFn(res); else return app.Tips({ title: '獲取session_key失敗' }); }); }
第三步:執(zhí)行g(shù)etUserInfoBydecryptCode 登錄獲取訪問(wèn)權(quán)限
getUserInfoBydecryptCode: function () { var that = this; var session_key = wx.getStorageSync('session_key') //沒(méi)有獲取到session_key,打開(kāi)授權(quán)頁(yè)面 //這里必須的判斷存在緩存中的session_key是否存在,因?yàn)樵诘谝徊降臅r(shí)候,判斷了 //授權(quán)了將自動(dòng)執(zhí)行獲取用戶信息的方法 if (!session_key) { wx.hideLoading(); if(that.data.isAuto) that.setData({ iShidden: false }) return false; }; wx.getUserInfo({ lang: 'zh_CN', success: function (res) { var pdata = res; pdata.userInfo = res.userInfo; pdata.spid = app.globalData.spid;//獲取推廣人ID pdata.code = app.globalData.code;//獲取推廣人分享二維碼ID if (res.iv) { pdata.iv = encodeURI(res.iv); pdata.encryptedData = res.encryptedData; pdata.session_key = session_key; //獲取用戶信息生成訪問(wèn)token app.basePost(app.U({ c: 'login', a: 'index' }), { info: pdata},function(res){ if (res.data.status == 0) return app.Tips( { title: '抱歉,您已被禁止登錄!' }, { tab: 4, url: '/pages/login-status/login-status' } ); else if(res.data.status==410){ wx.removeStorage({ key:'session_key'}); wx.hideLoading(); if (that.data.iShidden == true) that.setData({ iShidden: false }); return false; } //取消登錄提示 wx.hideLoading(); //關(guān)閉登錄彈出窗口 that.setData({ iShidden: true, ErrorCount:0}); //保存token和記錄登錄狀態(tài) app.globalData.token = res.data.token; app.globalData.isLog = true; //執(zhí)行登錄完成回調(diào) that.triggerEvent('onLoadFun', app.globalData.uid); //監(jiān)聽(tīng)登錄狀態(tài) that.WatchIsLogin(); },function(res){ wx.hideLoading(); return app.Tips({title:res.msg}); }); } else { wx.hideLoading(); return app.Tips({ title: '用戶信息獲取失敗!'}); } }, fail: function () { wx.hideLoading(); that.setData({ iShidden: false }); }, }) }
第四步:監(jiān)聽(tīng)登錄狀態(tài)
再服務(wù)器無(wú)法獲取到token時(shí),當(dāng)前頁(yè)面會(huì)一直監(jiān)聽(tīng)token是否為空,防止無(wú)限獲取token設(shè)置錯(cuò)誤次數(shù),終止監(jiān)聽(tīng)
監(jiān)聽(tīng)token的用意為:token是服務(wù)器返回當(dāng)前用戶的訪問(wèn)憑證,憑證有過(guò)期的時(shí)候這時(shí)候所有的網(wǎng)絡(luò)請(qǐng)求將無(wú)法訪問(wèn),所以用了一個(gè)愚蠢的方法來(lái)監(jiān)聽(tīng)token
//監(jiān)聽(tīng)登錄狀態(tài) WatchIsLogin:function(){ this.data.cloneIner=setInterval(function(){ //防止死循環(huán),超過(guò)錯(cuò)誤次數(shù)終止監(jiān)聽(tīng) if (this.getErrorCount()) return clearInterval(this.data.clearInterval); if (app.globalData.token == '') this.setAuthStatus(); }.bind(this),800); this.setData({ cloneIner:this.data.cloneIner}); } /** * 處理錯(cuò)誤次數(shù),防止死循環(huán) * */ setErrorCount:function(){ if (!this.data.ErrorCount) this.data.ErrorCount=1; else this.data.ErrorCount++; this.setData({ ErrorCount: this.data.ErrorCount}); }, /** * 獲取錯(cuò)誤次數(shù),是否終止監(jiān)聽(tīng) * */ getErrorCount:function(){ return this.data.ErrorCount >= 10 ? true : false; }
以上就是組件內(nèi)全部的方法需要在組件生命周期函數(shù)內(nèi)調(diào)用第一步的方法檢測(cè)授權(quán),執(zhí)行登錄
attached(){ this.setAuthStatus(); }
注:在網(wǎng)絡(luò)請(qǐng)求中一定要處理token失效的操作,主要把 app.globalData.token和app.globalData.isLog 設(shè)置回空和false
這里附上沒(méi)有定義的一些app內(nèi)公用的快捷方法以下的方法最好是寫(xiě)在其他文件里面在app.js里面寫(xiě)一個(gè)快捷調(diào)用的方法
/* * post網(wǎng)絡(luò)請(qǐng)求 * @param string | object 請(qǐng)求地址 * @param object data POST請(qǐng)求數(shù)組 * @param callable successCallback 成功執(zhí)行方法 * @param callable errorCallback 失敗執(zhí)行方法 */ const basePost = function (url, data, successCallback, errorCallback, header) { if (typeof url == 'object') url = U(url); wx.request({ url: url, data: data, dataType : 'json', method: 'POST', header: header, success: function (res) { try{ if (res.data.code == 200) { successCallback && successCallback(res.data); } else { if (res.data.code == 402) getApp().globalData.token = '', getApp().globalData.isLog = false; //返回狀態(tài)為401時(shí),用戶被禁止訪問(wèn) 關(guān)閉當(dāng)前所有頁(yè)面跳轉(zhuǎn)至用戶禁止登錄頁(yè)面 if (res.data.code == 401) return Tips({ title: res.data.msg}, { tab: 4, url:'/pages/login-status/login-status'}); errorCallback && errorCallback(res.data); } } catch (e) { console.log(e); } }, fail: function (res) { errorCallback && errorCallback(res); }, complete: function (res) { } }); } /* * 組裝URl *@param object opt */ const U = function (opt, url) { var m = opt.m || 'routine_two', c = opt.c || 'auth_api', a = opt.a || 'index', q = opt.q || '', p = opt.p || {}, params = '', gets = ''; if (url == undefined) url=getApp().globalData.url; params = Object.keys(p).map(function (key) { return key + '/' + p[key]; }).join('/'); gets = Object.keys(q).map(function (key) { return key + '=' + q[key]; }).join('&'); return url + '/' + m + '/' + c + '/' + a + (params == '' ? '' : '/' + params) +'.html'+ (gets == '' ? '' : '?' + gets); }
代碼量有點(diǎn)多,都是能用到的,望大神們多多指點(diǎn)
本小程序后臺(tái)框架由 http://github.crmeb.net/u/blue 提供
TP5+EasyWeChat技術(shù)支持
如果對(duì)微信小程序授權(quán)不熟悉的可以用 EasyWeChat,確實(shí)好用;不是來(lái)吹這個(gè)EasyWeChat來(lái)了,只是個(gè)人覺(jué)得好用勿噴
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 微信小程序獲取手機(jī)號(hào)授權(quán)用戶登錄功能
- 微信小程序用戶授權(quán),以及判斷登錄是否過(guò)期的方法
- 微信小程序?qū)崿F(xiàn)授權(quán)登錄
- 微信小程序 授權(quán)登錄詳解(附完整源碼)
- php實(shí)現(xiàn)微信小程序授權(quán)登錄功能(實(shí)現(xiàn)流程)
- uni-app微信小程序登錄授權(quán)的實(shí)現(xiàn)
- 微信小程序后端實(shí)現(xiàn)授權(quán)登錄
- 微信小程序授權(quán)登錄及解密unionId出錯(cuò)的方法
- 微信小程序授權(quán)登錄解決方案的代碼實(shí)例(含未通過(guò)授權(quán)解決方案)
- 微信小程序授權(quán)登錄的優(yōu)雅處理方式
相關(guān)文章
javascript實(shí)現(xiàn)頁(yè)面的實(shí)時(shí)時(shí)鐘顯示示例
這篇文章主要介紹了javascript實(shí)現(xiàn)頁(yè)面的實(shí)時(shí)時(shí)鐘顯示示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08layui 實(shí)現(xiàn)table翻頁(yè)滾動(dòng)條位置保持不變的例子
今天小編就為大家分享一篇layui 實(shí)現(xiàn)table翻頁(yè)滾動(dòng)條位置保持不變的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09JavaScript按位運(yùn)算符的應(yīng)用簡(jiǎn)析
下面根據(jù)自己的認(rèn)知簡(jiǎn)單的談一下js中的位操作使用(同樣適用于其他語(yǔ)言),如果有錯(cuò)誤,歡迎指正2014-02-02JS+CSS實(shí)現(xiàn)鼠標(biāo)滑過(guò)時(shí)動(dòng)態(tài)翻滾的導(dǎo)航條效果
這篇文章主要介紹了JS+CSS實(shí)現(xiàn)鼠標(biāo)滑過(guò)時(shí)動(dòng)態(tài)翻滾的導(dǎo)航條效果,涉及JavaScript動(dòng)態(tài)設(shè)置css樣式動(dòng)畫(huà)過(guò)度效果的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-09-09xmlplus組件設(shè)計(jì)系列之分隔框(DividedBox)(8)
xmlplus 是一個(gè)JavaScript框架,用于快速開(kāi)發(fā)前后端項(xiàng)目。這篇文章主要介紹了xmlplus布局類組件之分隔框,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05js實(shí)現(xiàn)網(wǎng)頁(yè)定位導(dǎo)航功能
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)網(wǎng)頁(yè)定位導(dǎo)航功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03javascript實(shí)現(xiàn)獲取字符串hash值
Hash 可以看作是一個(gè) 關(guān)聯(lián)數(shù)組,它對(duì)每一個(gè)值都綁定了一個(gè)唯一的鍵(值并不必須是唯一的), 然而,它不能保證迭代時(shí)元素的順序始終一致。因?yàn)?JavaScript 程序語(yǔ)言的特性,每個(gè)對(duì)象實(shí)際上都是一個(gè) hash,下面我們就來(lái)詳細(xì)探討下。2015-05-05