新版小程序登录授权的方法

所属分类: 网络编程 / JavaScript 阅读数: 1202
收藏 0 赞 0 分享

小程序自上线以来,官方一直在调整API,因此也出现了一批被废弃的接口,作为程序员的我们,此时此刻千万不能为这不断的变化而感到头疼,应当与时俱进,不断的更新自己的知识储备和应用技能。

首先近期工作中需要做小程序框架升级,升级成美团开源的mpvue框架;然后因为微信小程序API的改版,所以也顺便将授权登录的逻辑重新设计了。

新旧对比:

旧的方法:旧方法wx.getUserInfo按照用户登录时,弹出需要授权的弹窗,用户点击授权后才能使用。

新方法:Open-data的灵活使用方法,不会让你直接获得用户信息,而是小程序点击登录按钮获取用户头像,就是使用 button 组件,并将 open-type 指定为 getUserInfo 类型,获取用户基本信息。

授权登录的逻辑参考了多个小程序,希望能找到最优的模式。下面会配合代码详细讲解整个流程。

模式概览

由于微信小程序的改版导致直接弹出授权的登录方式将逐渐不再支持,受影响的有wx.getUserInfo接口,以及wx.authorize接口传入scope=”scope.userInfo”的情况。所以需要重新设计一套合适的登录授权流程。整体流程如下图:

主动登录

由于APP中有些页面默认需要登录的,如[个人中心]页面,需要登录获取到用户信息,才能继续操作。这样的页面就需要在每次进入页面(onShow)时判断是否授权了。

profile页面

onShow () {
  login(() => {
    do something...
  })
}

关于登录授权相关的逻辑都可以封装在handleLogin.js

handleLogin.js

// 开始login
function login (callback) {
 wx.showLoading()
 wx.login({
  success (res) {
   if (res.code) {
    // 登录成功,获取用户信息
    getUserInfo(res.code, callback)
   } else {
    // 否则弹窗显示,showToast需要封装
    showToast()
   }
  },
  fail () {
   showToast()
  }
 })
}

// 获取用户信息
function getUserInfo (code, callback) {
 wx.getUserInfo({
  // 获取成功,全局存储用户信息,开发者服务器登录
  success (res) {
   // 全局存储用户信息
   store.commit('storeUpdateWxUser', res.userInfo)
   postLogin(code, res.iv, res.encryptedData, callback)
  },
  // 获取失败,弹窗提示一键登录
  fail () {
   wx.hideLoading()
   // 获取用户信息失败,清楚全局存储的登录状态,弹窗提示一键登录
   // 使用token管理登录态的,清楚存储全局的token
   // 使用cookie管理登录态的,可以清楚全局登录状态管理的变量
   store.commit('storeUpdateToken', '')
   // 获取不到用户信息,说明用户没有授权或者取消授权。弹窗提示一键登录,后续会讲
   showLoginModal()
  }
 })
}

// 开发者服务端登录
function postLogin (code, iv, encryptedData, callback) {
 let params = {
  code: code,
  iv: iv,
  encryptedData: encryptedData
 }
 request(apiUrl.postLogin, params, 'post').then((res) => {
  if (res.code == 1) {
   wx.hideLoading()
   // 登录成功,
   // 使用token管理登录态的,存储全局token,用于当做登录态判断,
   // 使用cookie管理登录态的,可以存任意变量当做已登录状态
   store.commit('storeUpdateToken', res.data.token)
   callback && callback()
  } else {
   showToast()
  }
 }).catch((err) => {
  showToast()
 })
}

// 显示toast弹窗
function showToast (content = '登录失败,请稍后再试') {
 wx.showToast({
  title: content,
  icon: 'none'
 })
}

到此为止,登录就算完成了。不管使用token还是cookie都可以,都能有正常的登录态了,可以执行后续操作。

整个流程是 wx.login => wx.getUserInfo => 开发者服务器登录postLogin

调用接口

某些页面默认不需要登录,但某些用户操作事件是需要登录状态的,所以一者可以判断全局存储的登录状态管理的变量,如果为false,那么直接可以弹窗提示需要一键登录。二者如果全局状态为true,则调用接口看接口返回的code是否是未登录状态(此情况一般来说是登录态过期),未登录的话也弹窗提示需要一键登录。

某页面(需登录的用户操作)

getPlayer () {
  // 判断全局是否有登录状态,如果没有直接弹窗提示一键登录
  isLogin(() => {
    let params = {
      token: this.token
    }
    request(apiUrl.getPlayer, params).then((res) => {
      // TODO: 删除打印
      if (res.code === 1) {
        store.commit('storeUpdateUser', res.data.player_info)
      } else {
        // 获取失败了,如果是code是未登录,则去登录,然后执行回调函数this.getPlayer
        // 如果code不是未登录,直接弹窗报错误信息
        handleError(res, this.getPlayer)
      }
    }).catch((err) => {
      handleError(err)
    })
  })
}

handleLogin.js

// 判断是否登录
function isLogin (callback) {
 let token = store.state.token
 if (token) {
  // 如果有全局存储的登录态,暂时认为他是登录状态
  callback && callback()
 } else {
  // 如果没有登录态,弹窗提示一键登录
  showLoginModal()
 }
}

// 接口调用失败处理,
function handleError (res, callback) {
 // 规定-3041和-3042分别代表未登录和登录态失效
 if (res.code == -3041 || res.code == -3042) {
  // 弹窗提示一键登录
  showLoginModal()
 } else if (res.msg) {
  // 弹窗显示错误信息
  showToast(res.msg)
 }
}

到此为止,需要登录的用户操作就可以处理了。如果全局登录状态变量为true,先去调用接口,根据返回的信息是否是未登录再处理。

弹窗提示

由于微信小程序授权的接口wx.getUserInfowx.authorize中scope 为 “scope.userInfo” ,新版中调用这两个API是不会主动触发弹出授权窗口的。需要使用<button open-type="getUserInfo"></button>方法。

上面代码中多处出现的showLoginModal是用于显示一键登录的。如下:

handleLogin.js

// 显示一键登录的弹窗
function showLoginModal () {
 wx.showModal({
  title: '提示',
  content: '你还未登录,登录后可获得完整体验 ',
  confirmText: '一键登录',
  success (res) {
   // 点击一键登录,去授权页面
   if (res.confirm) {
    wx.navigateTo({
     url: '授权登录页面地址',
    })
   }
  }
 })
}

关于授权登录,我们做了一个专门的页面处理,此处的button<button type="primary" v-if="canIUse" open-type="getUserInfo" @getuserinfo="getUserInfo">微信登录</button>。如下:

getUserInfo (e) {
  if (e.target.userInfo) {
    // 点击Button弹窗授权,如果授权了,执行login
    // 因为Login流程中有wx.getUserInfo,此时就可以获取到了
    login(() => {
      // 登录成功后,返回
      wx.navigateBack()
    })
  }
}

到此为止,整个授权和登录流程就算走完了。可以回过头梳理一下最开始的流程图,应该就能理清整个逻辑了。

更多精彩内容其他人还在看

jQuery LigerUI 使用教程表格篇(1)

ligerGrid是ligerui系列插件的核心控件,用户可以快速地创建一个美观,而且功能强大的表格,支持排序、分页、多表头、固定列等等
收藏 0 赞 0 分享

JavaScript中常用的运算符小结

JavaScript中常用的运算符小结,需要的朋友可以参考下。
收藏 0 赞 0 分享

深入理解JavaScript系列(13) This? Yes,this!

在这篇文章里,我们将讨论跟执行上下文直接相关的更多细节。讨论的主题就是this关键字。实践证明,这个主题很难,在不同执行上下文中this的确定经常会发生问题
收藏 0 赞 0 分享

javascript (用setTimeout而非setInterval)

javascript (用setTimeout而非setInterval)如果用setInterval 可能出现 下次调用会在前一次调用前调用
收藏 0 赞 0 分享

JavaScript中两个感叹号的作用说明

用两个感叹号的作用就在于,如果明确设置了o中flag的值(非null/undefined/0""/等值),自然test就会取跟o.flag一样的值;如果没有设置,test就会默认为false,而不是null或undefined
收藏 0 赞 0 分享

javascript写的简单的计算器,内容很多,方法实用,推荐

最近用javascript写了一个简单的计算器,自己测试感觉还好,代码都给了注释,非常不错,推荐大家学习。
收藏 0 赞 0 分享

js的表单操作 简单计算器

javascript写的简单的加减乘除计算器,里面涉及到一些方法还是很实用的哦,新手不要错过
收藏 0 赞 0 分享

Jquery中删除元素的实现代码

empty用来删除指定元素的子元素,remove用来删除元素,或者设定细化条件执行删除
收藏 0 赞 0 分享

javaScript 利用闭包模拟对象的私有属性

JavaScript缺少块级作用域,没有private修饰符,但它具有函数作用域。作用域的好处是内部函数可以访问它们的外部函数的参数和变量(除了this和argument
收藏 0 赞 0 分享

为JavaScript类型增加方法的实现代码(增加功能)

大家在js开发过程中有些功能已经满足不了我们的需求,或没有我们需要的功能,那么我们就可以自己扩展下,个性化js
收藏 0 赞 0 分享
查看更多