使用uniapp開發(fā)app時(shí),需要實(shí)現(xiàn)三種登錄:1.本機(jī)號(hào)碼一鍵登錄 2.手機(jī)號(hào)驗(yàn)證碼登錄 3.郵箱驗(yàn)證碼登錄。
由于手機(jī)號(hào)/郵箱的驗(yàn)證碼配置流程類似,且都是后端與運(yùn)維同學(xué)操作配置,我只需要將手機(jī)號(hào)/郵箱進(jìn)行匹配后告知后端就可以了,所以本篇詳細(xì)記錄如何接入本機(jī)號(hào)碼一鍵登錄。

首先在插件市場(chǎng)找到阿里云號(hào)碼認(rèn)證SDK,由于我是使用離線打包的,所以我直接下載了壓縮包,解壓后得到名為AliCloud-NirvanaPns的文件夾,里面四個(gè)項(xiàng)目

阿里云官方給出了uni-app接入的文檔與步驟,uni-app接入文檔根據(jù)文檔“在項(xiàng)目中引入插件”的步驟走就好了


走完“d.單擊確定即可引入”即本地插件引入完成。接下來要瀏覽一下文檔,了解開放出來的方法API要如何去使用。

根據(jù)文檔可以得到setAuthSDKInfo必調(diào),目的是為了設(shè)置密鑰,而密鑰又是與Bundle ID或包名匹配的,所以后端同學(xué)會(huì)給我一組密鑰(安卓、iOS的密鑰不同,需根據(jù)當(dāng)前手機(jī)型號(hào)動(dòng)態(tài)設(shè)置),密鑰只需設(shè)置一次(意味著僅需調(diào)用setAuthSDKInfo一次)。
那么就要思考,這個(gè)setAuthSDKInfo方法調(diào)用要寫在哪里?若寫在pages/login/index.vue中的話豈不是每次都要設(shè)置么,所以我就放在了App.vue的onLaunch中,意味著只有app首次打開時(shí)會(huì)觸發(fā)設(shè)置。參考文檔:uniapp全局文件 - App.vue/uvue的應(yīng)用生命周期
App.vue代碼實(shí)現(xiàn)
<script>
//初始化
const aLiSDKModule = uni.requireNativePlugin('AliCloud-NirvanaPns');
export default {
setup() {
return {}
},
onLaunch: async function() {
// 獲取手機(jī)系統(tǒng)信息
const systemInfo = uni.getSystemInfoSync();
let sdkInfo = '';
// 判斷手機(jī)機(jī)型 安卓/iOS
if (systemInfo.osName == 'android') {
//開啟SDK日志打印
aLiSDKModule.setLoggerEnable(true);
aLiSDKModule.expandAuthPageCheckedScope(true);
//開啟區(qū)分界面返回及物理返回功能,自動(dòng)控制后續(xù)返回事件
aLiSDKModule.userControlAuthPageCancel();
//是否跟隨系統(tǒng)深色模式(由于我們開發(fā)時(shí)未做深色模式版UI樣式,所以設(shè)置為false)
aLiSDKModule.setAuthPageUseDayLight(false);
sdkInfo = "這里是安卓的密鑰";
} else if (systemInfo.osName == 'ios') {
sdkInfo = "這里是iOS的密鑰";
}
//設(shè)置密鑰
aLiSDKModule.setAuthSDKInfo(sdkInfo);
}
}
app首次打開時(shí),設(shè)置好了號(hào)碼認(rèn)證SDK的密鑰,后進(jìn)入首頁,當(dāng)用戶點(diǎn)擊功能入口時(shí)會(huì)檢測(cè)當(dāng)前用戶是否登錄,沒有token時(shí)會(huì)跳轉(zhuǎn)至login頁面。
交互要點(diǎn):
1.在login/index頁面onMounted時(shí)就要使用checkEnvAvailable方法去檢測(cè)當(dāng)前用戶的環(huán)境是否支持喚起本機(jī)號(hào)碼一鍵登錄的功能,若支持則喚起;否則顯示手機(jī)號(hào)驗(yàn)證碼登錄頁面
2.環(huán)境要素:測(cè)試該功能的手機(jī)要有SIM卡,且該SIM卡有費(fèi)可正常使用網(wǎng)絡(luò)(蜂窩數(shù)據(jù))。 ??僅Wi-Fi是無法喚起的
3.aLiSDKModule.getLoginToken方法的第二個(gè)參數(shù)config為授權(quán)頁UI配置,詳情參考修改授權(quán)頁主題配置。demo中我只定義了一個(gè)字段示意
4.實(shí)際使用本機(jī)號(hào)碼一鍵登錄時(shí),喚起頁面需要時(shí)間,所以加一個(gè)loading動(dòng)畫過渡一下
5.注意??:demo中有很多quitLoginPage調(diào)用

login參考代碼如下
<template>
<layout class="popup-content flex-column">
<!-- 手機(jī)號(hào) + 驗(yàn)證碼 -->
<phoneLog v-if="loginType === 1"></phoneLog>
<!-- 郵箱 + 驗(yàn)證碼 -->
<emailLogin v-if="loginType === 3"></emailLogin>
<!-- loading動(dòng)畫 -->
<view v-if="loginType === 0" class="loadpopup flex align-center justify-center">
<image src="/static/app/gif/load.gif"></image>
</view>
</layout>
</template>
<script setup>
import { ref, reactive, onMounted, onUnmounted } from 'vue'
import phoneLog from './phoneLogin.vue'
import emailLogin from './emailLogin.vue';
import { login } from '@/api/index.ts'
import { userStore } from '@/store/index'
const store = userStore()
const loginType = ref(0) // 1-手機(jī)號(hào)驗(yàn)證碼登錄 2-本機(jī)號(hào)碼一鍵登錄 3-email登錄
const aLiSDKModule = uni.requireNativePlugin('AliCloud-NirvanaPns'); //引入
const systemInfo = uni.getSystemInfoSync(); //獲取手機(jī)系統(tǒng)信息
let config = {} //授權(quán)頁UI配置,詳情參見。
// 喚起一鍵登錄
const loginFun = () => {
aLiSDKModule.getLoginToken(5000, config, tokenResult => {
if ("600001" == tokenResult.resultCode) {
loginType.value = 2
// console.log("授權(quán)頁拉起成功");
} else if ("600000" == tokenResult.resultCode) {
// console.log("獲取Token成功,接下來拿著結(jié)果里面的Token去服務(wù)端換取手機(jī)號(hào)碼,SDK服務(wù)到此結(jié)束");
formSubmit(tokenResult.token)
//手動(dòng)關(guān)閉授權(quán)頁
aLiSDKModule.quitLoginPage();
} else {
//其他失敗情況,手動(dòng)關(guān)閉授權(quán)頁,并切換其他登錄方式
}
}, clickResult => {
switch (clickResult.resultCode) {
case "700000":
console.log("用戶點(diǎn)擊返回按鈕");
uni.navigateBack({ delta: 1 })
//手動(dòng)關(guān)閉授權(quán)頁
aLiSDKModule.quitLoginPage();
break;
case "700001":
console.log("用戶切換其他登錄方式");
//手動(dòng)關(guān)閉授權(quán)頁,并切換其他登錄方式
break;
case "700002":
console.log("用戶點(diǎn)擊登錄按鈕");
//通過isChecked字段可以得到checkbox是否勾選,未勾選可以用自定義Toast進(jìn)行提示
if (!clickResult.result.isChecked && systemInfo.osName === 'ios') {
return
}
break;
case "700003":
console.log("用戶點(diǎn)擊checkBox");
break;
case "700004":
console.log("用戶點(diǎn)擊協(xié)議");
break;
case "700010":
//調(diào)用userControlAuthPageCancel后方可使用
console.log("用戶點(diǎn)擊返回按鈕,Android專用");
uni.navigateBack({ delta: 1 })
//手動(dòng)關(guān)閉授權(quán)頁
aLiSDKModule.quitLoginPage();
break;
case "700011":
//調(diào)用userControlAuthPageCancel后方可使用
console.log("用戶使用物理返回鍵,Android專用");
uni.navigateBack({ delta: 1 })
//手動(dòng)關(guān)閉授權(quán)頁
aLiSDKModule.quitLoginPage();
break;
}
})
}
// 本機(jī)號(hào)碼一鍵登錄 - 提交換token
const formSubmit = (token) => {
let loginData = {
username: token,
loginType: 'spToken'
}
login(loginData).then((res) => {
// 登錄成功后,記錄用戶token
store.setToken(res.token)
uni.setStorage({ key: 'token', data: res.token })
uni.setStorage({ key: 'refreshToken', data: res.refreshToken })
// 登錄成功后,獲取用戶信息
getUserInfo()
// 登錄成功,關(guān)閉彈窗,toast告知用戶,并跳轉(zhuǎn)頁面
uni.navigateBack({ delta: 1 })
}).catch ((err) => {
console.log('err', err)
// 登錄失敗,toast告知用戶并切換至其他登錄方式
})
}
onMounted(async () => {
try {
aLiSDKModule.checkEnvAvailable(2, result => {
if (result.resultCode === '600000') {
aLiSDKModule.accelerateLoginPage(5000, (result) => {
if ("600000" == result.resultCode) {
loginFun()
} else { // 切換其他登錄方式 }
});
} else { // 切換其他登錄方式 }
})
} catch (error) {
console.error('Initialization failed:', error)
// 切換為其他登錄方式
}
})
onUnmounted(() => {
aLiSDKModule.quitLoginPage();
})
</script>