关于前端:微信小程序登录流程与实现

1次阅读

共计 5898 个字符,预计需要花费 15 分钟才能阅读完成。

在理解小程序登录之前,请大家先理解小程序的全局实例和全局组件,以不便了解本文的后续内容,曾经理解的能够间接开始。
全局实例和全局组件(👈 点击中转)

微信小程序的登录流程

微信小程序的登录

首先须要写一个微信小程序的登录弹窗,登录弹窗的作用就是发动登录,让用户点击受权后登录小程序,该弹窗是一个全局弹窗,因为小程序是有分享性能的,如果新用户是从分享的链接进来的,那么会先让新用户登录再做后续操作。
所以,登录性能得是一个组件,而且,登录必须是全局弹窗。
在登录页面的 index.json 文件中,设置登录弹窗为组件

{
  "component": true,
  "usingComponents": {// xxxx.....}
}

登录弹窗上须要有受权的选项,如果未勾选受权间接点击登录,须要提醒用户先受权再登录

用户勾选受权后,点击登录。小程序登录须要应用 button 组件,将 button 组件的 open-type 的值设置为 getPhoneNumber,当用户点击并批准之后,能够通过 bindgetphonenumber 事件回调获取到动静令牌 code,而后把code 传到开发者后盾,并在开发者后盾调用微信后盾提供的 phonenumber.getPhoneNumber 接口,生产 code 来换取用户手机号。并且每个 code 有效期为 5 分钟,且只能生产一次。
open-type=”getPhoneNumber” 应用文档(👈 点击中转)

注:getPhoneNumber 返回的 codewx.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.jsonLaunchnew 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 返回的 codewx.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" 当然是不够的,所以须要再加一个状态,isInfoisInfo默认为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 都是混着写的,大家能够依据我的项目的理论需要做自在调整。


如果感觉这篇文章对你有帮忙,欢送点赞、珍藏、转发哦~

正文完
 0