微信小程序非跳轉(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獲取用戶信息 -> 登錄成功返回訪問token -> 記錄登錄狀態(tài) -> 執(zhí)行登錄成功監(jiān)聽(失敗則不監(jiān)聽)
直接上代碼,一下均為小程序組件模式有興趣的可以看下官方文檔
創(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)前頁面為組件
{
"component": true
}
到這里準(zhǔn)備工作完成
authorize.js 換成組件的寫法,具體參考小程序官方文檔,這里展示我定義的
Component({
//組件的對(duì)外屬性 說的確實(shí)很官方,用過vue組件的就很容易理解這點(diǎn)
//父級(jí)向子級(jí)傳值這里就是接收值得地方
properties:{
//名稱要和父級(jí)綁定的名稱相同
//這里主要是控制自動(dòng)授權(quán)彈框是否顯示 true=隱藏 false=顯示
iShidden:{
type:Boolean,//定義類型
value: true,//定義默認(rèn)值
},
//是否自動(dòng)登錄 這里主要用于沒有授權(quán)是否自動(dòng)彈出授權(quán)提示框
//**用在不自動(dòng)登錄頁面但是某些操作需要授權(quán)登錄**
isAuto:{
type: Boolean,
value: true,
},
},
//組件的內(nèi)部數(shù)據(jù),和 properties 一同用于組件的模板渲染
data:{
cloneIner:null
},
//組件所在頁面的生命周期聲明對(duì)象
pageLifetimes:{
//頁面隱藏
hide:function(){
//關(guān)閉頁面時(shí)銷毀定時(shí)器
if(this.data.cloneIner) clearInterval(this.data.clearInterval);
},
//頁面打開
show:function(){
//打開頁面銷毀定時(shí)器
if (this.data.cloneIner) clearInterval(this.data.clearInterval);
},
},
//組件生命周期函數(shù),在組件實(shí)例進(jìn)入頁面節(jié)點(diǎn)樹時(shí)執(zhí)行
attached(){
},
//組件的方法
methods:{
}
});
注:以下的方法都需寫在 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']) {
//沒有授權(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();
}
}
}
})
}
第二步,沒有授權(quán)執(zhí)行打開授權(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,如果沒有則請(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ù)器獲得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 登錄獲取訪問權(quán)限
getUserInfoBydecryptCode: function () {
var that = this;
var session_key = wx.getStorageSync('session_key')
//沒有獲取到session_key,打開授權(quán)頁面
//這里必須的判斷存在緩存中的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;
//獲取用戶信息生成訪問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à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ài)
再服務(wù)器無法獲取到token時(shí),當(dāng)前頁面會(huì)一直監(jiān)聽token是否為空,防止無限獲取token設(shè)置錯(cuò)誤次數(shù),終止監(jiān)聽
監(jiān)聽token的用意為:token是服務(wù)器返回當(dāng)前用戶的訪問憑證,憑證有過期的時(shí)候這時(shí)候所有的網(wǎng)絡(luò)請(qǐng)求將無法訪問,所以用了一個(gè)愚蠢的方法來監(jiān)聽token
//監(jiān)聽登錄狀態(tài)
WatchIsLogin:function(){
this.data.cloneIner=setInterval(function(){
//防止死循環(huán),超過錯(cuò)誤次數(shù)終止監(jiān)聽
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)聽
*
*/
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
這里附上沒有定義的一些app內(nèi)公用的快捷方法以下的方法最好是寫在其他文件里面在app.js里面寫一個(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í),用戶被禁止訪問 關(guān)閉當(dāng)前所有頁面跳轉(zhuǎn)至用戶禁止登錄頁面
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í)好用;不是來吹這個(gè)EasyWeChat來了,只是個(gè)人覺得好用勿噴
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 微信小程序獲取手機(jī)號(hào)授權(quán)用戶登錄功能
- 微信小程序用戶授權(quán),以及判斷登錄是否過期的方法
- 微信小程序?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í)例(含未通過授權(quán)解決方案)
- 微信小程序授權(quán)登錄的優(yōu)雅處理方式
相關(guān)文章
javascript實(shí)現(xiàn)頁面的實(shí)時(shí)時(shí)鐘顯示示例
這篇文章主要介紹了javascript實(shí)現(xiàn)頁面的實(shí)時(shí)時(shí)鐘顯示示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08
layui 實(shí)現(xiàn)table翻頁滾動(dòng)條位置保持不變的例子
今天小編就為大家分享一篇layui 實(shí)現(xiàn)table翻頁滾動(dòng)條位置保持不變的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-09-09
JavaScript按位運(yùn)算符的應(yīng)用簡析
下面根據(jù)自己的認(rèn)知簡單的談一下js中的位操作使用(同樣適用于其他語言),如果有錯(cuò)誤,歡迎指正2014-02-02
JS+CSS實(shí)現(xiàn)鼠標(biāo)滑過時(shí)動(dòng)態(tài)翻滾的導(dǎo)航條效果
這篇文章主要介紹了JS+CSS實(shí)現(xiàn)鼠標(biāo)滑過時(shí)動(dòng)態(tài)翻滾的導(dǎo)航條效果,涉及JavaScript動(dòng)態(tài)設(shè)置css樣式動(dòng)畫過度效果的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-09-09
xmlplus組件設(shè)計(jì)系列之分隔框(DividedBox)(8)
xmlplus 是一個(gè)JavaScript框架,用于快速開發(fā)前后端項(xiàng)目。這篇文章主要介紹了xmlplus布局類組件之分隔框,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05
js實(shí)現(xiàn)網(wǎng)頁定位導(dǎo)航功能
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)網(wǎng)頁定位導(dǎo)航功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
javascript實(shí)現(xiàn)獲取字符串hash值
Hash 可以看作是一個(gè) 關(guān)聯(lián)數(shù)組,它對(duì)每一個(gè)值都綁定了一個(gè)唯一的鍵(值并不必須是唯一的), 然而,它不能保證迭代時(shí)元素的順序始終一致。因?yàn)?JavaScript 程序語言的特性,每個(gè)對(duì)象實(shí)際上都是一個(gè) hash,下面我們就來詳細(xì)探討下。2015-05-05

