微信小程序登录流程与实现
兔子先森兔子先森 -在了解小程序登录之前,请大家先了解小程序的全局实例和全局组件,以方便理解本文的后续内容,已经了解的可以直接开始。
全局实例和全局组件( 👈 点击直达)
首先需要写一个微信小程序的登录弹窗,登录弹窗的作用就是发起登录,让用户点击授权后登录小程序,该弹窗是一个全局弹窗,因为小程序是有分享功能的,如果新用户是从分享的链接进来的,那么会先让新用户登录再做后续操作。
所以,登录功能得是一个组件,而且,登录必须是全局弹窗。
在登录页面的index.json
文件中,设置登录弹窗为组件
{
"component": true,
"usingComponents": {
// xxxx.....
}
}
登录弹窗上需要有授权的选项,如果未勾选授权直接点击登录,需要提示用户先授权再登录用户勾选授权后,点击登录。 小程序登录需要使用 button
组件,将button
组件的 open-type
的值设置为 getPhoneNumber
,当用户点击并同意之后,可以通过 bindgetphonenumber
事件回调获取到动态令牌code
,然后把code
传到开发者后台,并在开发者后台调用微信后台提供的 phonenumber.getPhoneNumber
接口,消费code
来换取用户手机号。并且每个code
有效期为5
分钟,且只能消费一次。
open-type="getPhoneNumber"使用文档 ( 👈 点击直达)
getPhoneNumber
返回的 code
与 wx.login
返回的 code
作用是不一样的,不能混用。<button open-type="getPhoneNumber" bindgetphonenumber="handleConfirm"></button>
data: {
show: false, // 登录弹窗是否显示
selected: true, // 是否勾选授权
loginSuccess: undefined,
loginFail: undefined,
},
// 确认授权手机号-这里可以做节流操作,防止用户点击次数过多,为了便于演示,这里未做节流
async handleConfirm(data) {
const {selected} = this.data
// 用户未勾选,提示请勾选
if(!selected){
wx.showToast({
title: '请同意《用户隐私协议》',
icon: 'none'
})
return
}
// data.detail.code就是获取手机号的动态令牌
let info = data.detail
let fail = this.data.loginFail
if (info.code) {
// info.code就是手机号动态令牌
/**新版本微信小程序不需要提前调用wx.login进行登录,这里的写法是为了实配老版本,在获取手机号授权登录之前先调用wx.login
这里的app.globalData.userInfo为全局挂载的userInfo,关于userInfo的解释在本文下方
*/
/* 使用awiat阻塞进程 */
await app.globalData.userInfo._getLoginCode() // wx.login登录
// 调用了wx.login后进入下一步
this.setPhoneInfo(info) // 绑定手机号-获取手机号授权用户登录功能
} else {
fail && fail(info)
}
},
// 绑定手机号-获取手机号授权用户登录功能
setPhoneInfo(data) {
let success = this.data.loginSuccess
let fail = this.data.loginFail
// data.jsCode保存通过login获取的code
data.jsCode = app.globalData.userInfo.code
// 手机号动态令牌
data.phoneCode = data.code
// 调用用户登录接口,removeNull其实是一个封装的方法, 用来去掉空格,本质就是传了一个data
getLoginSession(removeNull(data)).then(async res => {
// then为登录成功,存入token
wx.setStorageSync('token', res.data)
// 手机号授权算登录成功
success && success()
// 设置全局userInfo属性,isLogin = true,表示登录成功
app.globalData.userInfo.isLogin = true
// 清除等待列表
wx.queue.asyncExe("login_back")
// 调用全局的_getUserInfo方法,传入'login'参数
await app.globalData.userInfo._getUserInfo('login')
// 关闭弹框
this.hideLogin()
}).catch(async e => {
if (e.data.indexOf("已绑定") > -1) {
success && success()
wx.setStorageSync("token", e.data)
await app.globalData.userInfo._getUserInfo('login')
} else {
fail && fail()
}
// 关闭弹框
this.hideLogin()
})
},
// 关闭弹框
hideLogin() {
// 关闭弹框
this.setData({
show: false
}, () => {
if (isPopup()) {
// 显示tabbar()
setTimeout(() => {
this.getTabBar().show()
}, 300)
}
})
},
旧版本的微信小程序是需要提前调用wx.login
获取code
才能进行下一步操作,而新版本则不需要提前调用wx.login
进行登录。
wx.login文档 ( 👈 点击直达)
下面是userInfo.js
文件,该文件内部创建了一个class
类,该类会挂载到全局实例身上
// userInfo.js
import {
getUserInfo
} from '../service/user'
class UserInfo {
code = '' // 用户授权登录时需要用到的code
isLogin = false // 判断用户是否已经登录拿到token
isInfo = false // 判断用户是否已经登录了
/**
* 获取用户信息
*/
_getUserInfo(type) {
return new Promise((resolve,reject)=>{
// isInfo初始化为false,表示未登录过,如登录过isInfo = true,如果登录过则直接获取本地的token
if(type=="login"&&this.isInfo) return resolve(wx.getStorageSync('userInfo'))
this.isInfo = true
// 调用获取用户信息的接口
getUserInfo().then(res=>{
// 如果返回200,拿到token以后,保存用户的信息,主要是名称和头像
if (res.code == 200) {
// 保存用户信息到本地
wx.setStorageSync('userInfo', res.data)
// resolve返回
resolve(res)
}
// 不等于200 isInfo = false,表示已经登录过,重新获取即可
this.isInfo = false
// 不等于200 返回错误信息
reject(res)
},(err)=>{
// 不等于200 isInfo = false,表示已经登录过,重新获取即可
this.isInfo = false
// 不等于200 返回错误信息
reject(err)
})
})
}
/**
* 通过wx.login获取code
* 不全局调用,每次授权调用Login方法前,都重新获取一次
*/
async _getLoginCode() {
try {
const loginCodeRes = await wx.p.login()
console.log(loginCodeRes)
/**loginCodeRes.code : 用户登录凭证(有效期五分钟)。开发者需要在开发者服务器后台调用 code2Session,使用 code 换取 openid、unionid、session_key 等信息 */
// 将该code挂载到全局的global.userInfo中
this.code = loginCodeRes.code
} catch (error) {
console.error(error, 'get jscode error');
}
}
}
export default UserInfo
// app.js
import UserInfo from './private/UserInfo'
App({
/** 小程序生命周期,全局调用一次onLaunch */
onLaunch(e) {
/**new UserInfo() */
this.globalData.userInfo = new UserInfo()
},
onShow(e) {},
globalData: {
userInfo: null, /**private -> UserInfo的属性和方法挂载到这里 */
show:false
}
})
流程总结通过getPhoneNumber
的方式登录
1、components
中创建auth
文件夹,该文件夹就是内的html
就是小程序的登录弹窗,auth
是一个全局组件,在app.json
中挂载
2、在private
文件夹中封装小程序的登录方法 ——> UserInfo.js
——> js
文件内创建class
类,在class
中封装方法并导出
3、在app.js
的onLaunch
中new UserInfo
获取之前封装好的小程序登录方法,该方法挂载到globalData.userInfo
中
import UserInfo from './private/UserInfo'
App({
onLaunch(e){
this.globalData.userInfo = new UserInfo()
}
})
4、auth
文件夹为小程序的全局授权登录弹窗,从基础库 2.21.2
开始,对获取手机号的接口进行了安全升级,新版小程序需要用户自动触发才能获取手机号接口,需用 button 组件的点击来触发。新版小程序不再需要提前调用wx.login
进行登录
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber"></button>
Page({
getPhoneNumber (e) {
console.log(e.detail.code) // 该code就是动态令牌,用于换取用户手机号
}
})
需要将 button 组件 open-type
的值设置为 getPhoneNumber
,当用户点击并同意之后,可以通过 bindgetphonenumber
事件回调获取到动态令牌code
,然后把code
传到开发者后台,并在开发者后台调用微信后台提供的 phonenumber.getPhoneNumber 接口,消费code
来换取用户手机号。每个code
有效期为5分钟,且只能消费一次。
getPhoneNumber
返回的 code
与 wx.login
返回的 code
作用是不一样的,不能混用。5、用户点击弹框后,先让用户勾选协议,勾选后才允许点击登录,调用登录接口,将登录接口单独封装起来,将获取到的code
手机号动态令牌当参数传入登录方法。
新版本微信不许要提前调用login
来获取code
码,旧版本微信小程序是需要提前调用login
获取code
码
为了演示,所以这里提前调用 wx.login
来获取code
码,并将该code
码存入全局app.globalData.userInfo
中,需要注意的是,该code
码的有效期是5分钟
6、调用登录方法, 携带code
手机号动态令牌和接口规定的必传参数,请求登录接口,返回200
为登录成功,
1)、将登录成功的token存入本地
2)、设置全局属性app.globalData.userInfo.isLogin = true表示登录成功
3)、清除等待列表
7、调用获取用户信息接口,也就是全局挂载的await app.globalData.userInfo._getUserInfo()
,关闭登录弹框
await app.globalData.userInfo._getUserInfo('login')
8、获取用户信息接口,通过传入的参数判断是是否要登录,这里有两种情况:
1)、用户已经登录了,只是想重新获取一下token
2)、用户第一次登录,要获取用户信息,例如头像、用户名称
根据这两种情况,传入的参数"login"
当然是不够的,所以需要再加一个状态,isInfo
,isInfo
默认为false
/**
* 获取用户信息
*/
_getUserInfo(type) {
return new Promise((resolve,reject)=>{
// 用户登录过
if(type=="login"&&this.isInfo) return resolve(wx.getStorageSync('userInfo'))
// 设置isInfo = true,因为下面要走获取用户信息流程,获取后,第二次调用_getUserInfo判断isInfo = true,直接return掉
this.isInfo = true
// 调用获取用户信息的接口
getUserInfo().then(res=>{
// 如果返回200,拿到token以后,保存用户的信息,主要是名称和头像
if (res.code == 200) {
// 保存用户信息到本地
wx.setStorageSync('userInfo', res.data)
// resolve返回
resolve(res)
}
// 不等于200 isInfo = false,表示已经登录过,重新获取即可
this.isInfo = false
// 不等于200 返回错误信息
reject(res)
},(err)=>{
// 不等于200 isInfo = false,表示已经登录过,重新获取即可
this.isInfo = false
// 不等于200 返回错误信息
reject(err)
})
})
}
最后附上微信官方对登录的说明 ( 👈 点击直达)
以上就是微信小程序的登录流程,这些步骤都是按实际需求编写的,有些时候流程的2、3、4、5、6都是混着写的,大家可以根据项目的实际需求做自由调整。
如果觉得这篇文章对你有帮助,欢迎点赞、收藏、转发哦~