在了解小程序登录之前,请大家先了解小程序的全局实例和全局组件,以方便理解本文的后续内容,已经了解的可以直接开始。
全局实例和全局组件( 👈 点击直达)
微信小程序的登录流程
微信小程序的登录
首先需要写一个微信小程序的登录弹窗,登录弹窗的作用就是发起登录,让用户点击授权后登录小程序,该弹窗是一个全局弹窗,因为小程序是有分享功能的,如果新用户是从分享的链接进来的,那么会先让新用户登录再做后续操作。
所以,登录功能得是一个组件,而且,登录必须是全局弹窗。
在登录页面的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> • 1
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> • 1
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都是混着写的,大家可以根据项目的实际需求做自由调整。
如果觉得这篇文章对你有帮助,欢迎点赞、收藏、转发哦~