闡述
開發(fā)uni-app之前建議大家先看看 manifest.json 配置項各參數(shù),對整個項目開發(fā)是有幫助的
文檔路徑:https://uniapp.dcloud.io/collocation/manifest?id=%E5%AE%8C%E6%95%B4-manifestjson
我先歸納一下登錄邏輯
目前我先歸納小程序的登錄
登陸授權(quán)我分兩大步:1.登錄授權(quán)獲取用戶信息 2.后續(xù)使用檢測登錄態(tài)
登錄授權(quán):
因為授權(quán)的彈框是可以取消的,取消之后第二次打開則是無效,所以解決這個問題,我使用兩個api uni.getSetting uni.openSetting ,一個是獲取用戶當(dāng)前獲取權(quán)限的狀態(tài),一個是打開權(quán)限設(shè)置并授權(quán)。
當(dāng)用戶不授權(quán)的時候,做一個同樣的Buttn按鈕去模擬登錄,提示用戶已經(jīng)取消授權(quán)需要手動開啟授權(quán)權(quán)限,當(dāng)點擊授權(quán)完時,需要取得用戶code,uniapp提供檢測當(dāng)前環(huán)境的api uni.getProvider ,所以先取得環(huán)境在獲取code,當(dāng)拿到code iv encryptedData 時就要可以調(diào)用后臺接口拿到用戶對應(yīng)的信息,并緩存下來,代碼例子:
//login.vue
<template>
<view class="login">
<image src="../../static/images/loginLogo.png" class="logo"></image>
<button class="login-button" type="primary" @click="openSetting" v-if="status==0">微信登錄</button>
<button class="login-button" type="primary" open-type="getUserInfo" @getuserinfo="getuserinfo" v-else>微信登錄</button>
<view class="phone-login">手機(jī)號登錄/注冊</view>
</view>
</template>
<script>
import {getProvider,login,getCode} from '@/api/request/login/login.js'
import {getSetting} from '@/api/request/login/authorize.js'
export default {
components: {
},
data() {
return {
code: '',
status: 0 //2未操作 1已經(jīng)授權(quán) 0拒絕授權(quán)
}
},
onLoad() {
},
onShow() {
(async () => {
//獲取授權(quán)狀態(tài)
this.status = await getSetting()
//獲取服務(wù)商信息
let provider = await getProvider();
//獲取code
this.code = await getCode(provider[0])
})()
},
methods: {
getuserinfo(e) {
if (!this.code) {
uni.showToast({
icon: 'none',
title: '正在加載中,稍等一下',
duration: 2000
});
return
}
if (e.detail && e.detail.errMsg == 'getUserInfo:ok') {
e.detail.code = this.code//add code
login(e.detail, res => {
//授權(quán)成功之后的回調(diào)
uni.showToast({
title: '獲取用戶信息成功',
duration: 2000
});
setTimeout(() => {
uni.redirectTo({
url: '/pages/index/index'
});
}, 2000)
})
} else {
//授權(quán)成功之后的回調(diào)
uni.showToast({
icon: 'none',
title: '已拒絕授權(quán)',
duration: 2000
});
//用戶拒絕授權(quán)
this.status = 0
}
},
openSetting() {
uni.showModal({
title: '提示',
content: '你已經(jīng)取消過授權(quán),需設(shè)置授權(quán)權(quán)限',
confirmText: '設(shè)置',
success: function(res) {
if (res.confirm) {
uni.openSetting({
success(res) {
}
})
} else if (res.cancel) {
console.log('用戶點擊取消');
}
}
});
}
}
}
</script>
<style lang="scss" scoped>
</style>
//驗證授權(quán)狀態(tài) 2未操作 1已經(jīng)授權(quán) 0拒絕授權(quán)
const getSetting = function() {
const promise= new Promise((resolve,reject) => {
uni.getSetting({
success(res) {
let authSetting=res.authSetting
//授權(quán)成功
if(authSetting['scope.userInfo']){
resolve(1)
return
}
//拒絕授權(quán)
if(authSetting['scope.userInfo']===false){
resolve(0)
return
}
resolve(2)
},
fail(res) {
reject(res)
}
})
}).catch(res=>{
uni.showToast({
icon:'none',
title: res.errMsg || '獲取授權(quán)狀態(tài)失敗',
duration: 2000
});
})
return promise
}
export {
getSetting,//驗證授權(quán)狀態(tài)
}
//login.js
import {
authDo
} from '@/api/mpLogin/home.js'
//獲取服務(wù)商信息
const getProvider = () => {
const promise = new Promise((resolve, reject) => {
uni.getProvider({
service: 'oauth', //服務(wù)類型 登錄授權(quán)
success: function(res) {
resolve(res.provider)
},
fail(res) {
reject(res)
}
});
}).catch(res => {
uni.showToast({
icon: 'none',
title: res.errMsg || '獲取服務(wù)商信息失敗',
duration: 2000
});
})
return promise
}
//獲取code
const getCode = provider => {
if (!provider) {
uni.showToast({
icon: 'none',
title: '獲取服務(wù)商信息失敗',
duration: 2000
});
return
}
const promise = new Promise((resolve, reject) => {
uni.login({
provider: provider,
success: function(loginRes) {
if (loginRes && loginRes.code) {
resolve(loginRes.code)
} else {
reject(loginRes)
}
}
});
}).catch(res => {
uni.showToast({
icon: 'none',
title: res.errMsg || '獲取code失敗',
duration: 2000
});
})
return promise
}
//登錄授權(quán)
const login = async function(e,func) {
//獲取服務(wù)商信息
// let provider = await getProvider();
//獲取code
// let code = await getCode(provider[0])
//小程序授權(quán)微信
let param = {
code:e.code,
encryptedData: e.encryptedData,
iv: e.iv
}
let res = await authDo(param);
if (res.resultCode != '0000') {
uni.showToast({
icon: 'none',
title: res.resultMessage,
duration: 2000
});
return
}
let data = res.result || {}
//儲存用戶信息到本地
uni.setStorageSync('user', data);
func&&func(data)
}
export {
login,//登錄授權(quán)
getCode,//獲取code
getProvider//獲取服務(wù)商信息
}
檢測登錄態(tài)
app.vue onShow 里檢查登錄態(tài),這里分兩步,一步是判斷有用戶緩存 沒有前往登錄 如有緩存則判斷登錄態(tài),需要用uni.checkSession檢查登錄態(tài)是否過期,未過期不需要執(zhí)行其他操作,如過期,需要獲取code以及緩存里存的session 調(diào)用后臺接口刷新登錄態(tài),代碼如下:
//app.vue
<script>
import {
checkLoginStatus
} from '@/api/request/login/checkLoginStatus.js' //檢查登錄狀態(tài)
export default {
onLaunch: function() {
console.log('App Launch')
},
onShow: function() {
console.log('App show')
// #ifdef MP
//檢查登錄狀態(tài)
checkLoginStatus()
// #endif
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<style>
/*每個頁面公共css */
@import "css/flex.css";
@import "css/public.css";
</style>
//checkSession.js
//檢測session是否過期
//0未過期 1已過期
const check=()=>{
const promise= new Promise((resolve,reject) => {
uni.checkSession({
success() {
console.log('狀態(tài)未過期')
//未過期
resolve(0)
},
fail() {
console.log('狀態(tài)已過期')
//已過期
resolve(1)
}
})
}).catch(res=>{
uni.showToast({
icon:'none',
title: res.errMsg || '驗證session失效',
duration: 2000
});
})
return promise
}
export default check
//checkLoginStatus.js
import check from "@/api/request/login/checkSession.js" //檢驗sessing是否過期 0未過期 1已過期
import {
getCode,
getProvider
} from "@/api/request/login/login.js"
import {
wxLoginState
} from "@/api/mpLogin/home.js"
//用戶緩存信息
const user = (uni.getStorageSync('user'));
//跳轉(zhuǎn)至小程序登錄頁
const toLogin = () => {
// uni.showToast({
// icon: 'none',
// title: '您的登錄已過期,跳轉(zhuǎn)至授權(quán)頁',
// mask: true,
// duration: 2000
// });
setTimeout(() => {
uni.redirectTo({
url: '/pages/login/index'
});
}, 2000)
}
//小程序登錄態(tài)刷新
const loadLoginState = async function() {
let access3rdToken = user.access3rdToken //平臺sessionId
let provider = await getProvider() //獲取服務(wù)商信息
let code = await getCode(provider[0]) //獲取code
let param = {
access3rdToken,
code
}
let res = await wxLoginState(param);
if (res.resultCode != '0000') {
uni.showToast({
icon: 'none',
title: res.resultMessage,
duration: 2000
});
return
}
console.log('刷新成功')
}
//判斷登錄狀態(tài)
const checkLoginStatus = async function() {
if (user) {
// 檢查 session_key 是否過期
let status = await check()
//已過期
if (status == 1) {
//小程序登錄態(tài)刷新
loadLoginState()
} else {
//未過期
console.log('執(zhí)行下一步操作')
}
} else {
// 無skey,作為首次登錄
toLogin();
}
}
export {
checkLoginStatus, //判斷登錄狀態(tài)
toLogin, //跳轉(zhuǎn)至小程序登錄頁
loadLoginState //小程序登錄態(tài)刷新
}