微信小程序:wx.login和getPhonenumber获取手机号解密失败问题

Posted 彭世瑜

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了微信小程序:wx.login和getPhonenumber获取手机号解密失败问题相关的知识,希望对你有一定的参考价值。

原来的登录处理流程:

通过按钮点击触发,在处理函数内调用wx.login()

发现每次登录,第一次都会解密失败,第二次就成功了。

<button open-type="getPhoneNumber" 
	bindgetphonenumber="getPhonenumber">登录</button>
async getPhonenumber(e)
   wx.login()

此时,是先点击的获取用户信息,再进行登录。
逻辑是不对的,因为获取手机号之后才进行的登录

第一次获取手机号,微信使用的是当前session_key对手机号信息进行加密,而我们的session_key还是空的,或者用户之前登录过,那么session_key就是上一次登录的状态。解密失败。

第二次获取手机号,我们通过上次登录,获取了最新的session_key,服务端也存了同样的一份session_key, 微信加密和我们服务器解密使用的是同一份数据。解密成功。

解决办法

知道了登录的问题所在,当用户授权之前,应该使得服务端session_key当前session_key保持一致。

// 该方法应该在进入页面的时候,或者getPhonenumber之前调用
login()
   // 如果有session_id,可以检查一下是否过期
	wx.checkSession()
	// 过期就登录
	wx.login()
	// 将session状态同步至服务器
	// 登录成功后本地可以保存一份session_id


async getPhonenumber(e)
  // 获取手机号逻辑

解决方法二:

微信基础库 2.21.2 开始 提供了新的获取手机号接口,通过动态令牌code就能换取用户手机号信息,能避免使用session_key不一致的问题。

https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html

微信小程序wx.login 和 wx.getUserProfile 同时使用问题

场景

在使用微信登录时,通常会在调用 wx.login 获取 code 后再通过 wx.getUserProfile 获取 ivencryptedData (加密数据)一起发到后端进行登录验证;

但是,在实际使用中如果在 wx.login 方法调用后再调用 wx.getUserProfile 会报错;

官方解释


也就是说,不能在调用方法的回调中使用 wx.getUserProfule()

解决方法

使用Promise.all()方法实现平级调用;

Promise.all() 方法接收一个 promiseiterable 类型(注:ArrayMapSet 都属于ES6 的 iterable 类型)的输入,并且只返回一个 Promise 实例, 那个输入的所有promiseresolve 回调的结果是一个数组。这个 Promiseresolve 回调执行是在所有输入的 promiseresolve 回调都结束,或者输入的 iterable 里没有 promise 了的时候。它的 reject 回调执行是,只要任何一个输入的 promisereject 回调执行或者输入不合法的 promise 就会立即抛出错误,并且 reject 的是第一个抛出的错误信息。

简单点说就是会等到两个方法都回调成功该方法才会返回来值,返回值是一个数组。

代码

封装 wx.loginwx.getUserProfile 两个接口:

/**
 * 使用promise封装用户信息接口
 */
getUserInfo:function(){
  return new Promise((resolve,reject) => {
    wx.getUserProfile({
      desc: '用户登录', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
      success: (res) => {
        resolve(res)
      },
      fail:(err) => {
        reject(err)
      }
    })
  })
},

/**
 * 使用promise封装wx.login接口
 */
getLogin:function(){
 return new Promise((resolve,reject) => {
   wx.login({
     success (res) {
       resolve(res)
    },
    fail: (err) => {
      reject(err)
   	}
  })
 })
},

封装登录接口

/**
 * 登录接口
 */
login: function(){
  let userRes = this.getUserInfo()
  let loginRes = this.getLogin()
  //使用promise.all()平级调用
  Promise.all([userRes,loginRes]).then((res) => {
   console.log(res)
   let param = {
     code: res[1].code,
     iv: res[0].iv,
     encryptedData: res[0].encryptedData
   }
   let data = {
     method: "post",
     url: api.apiName.wxLogin,
     params: param
   }
   request.request(data).then(res => {
     wx.setStorageSync('token', res.data)
     wx.setStorageSync('hasLogin', true)
     //获取用户信息
     let data = {
       method: "get",
       url: api.apiName.getUserInfo,
       params: null
     }
     request.request(data).then(res2 => {
       wx.hideLoading({})
       wx.setStorageSync('userInfo', res2.data)
     }).catch(err => {
       wx.hideLoading({})
       console.log(err.msg)
     })
     setTimeout(function(){
       wx.switchTab({
          url: '../../index/index',
       })
     },1500)
    }).catch(err => {
      console.log(err.msg)
    })
  })
}

以上是关于微信小程序:wx.login和getPhonenumber获取手机号解密失败问题的主要内容,如果未能解决你的问题,请参考以下文章

微信小程序-bug-调用wx.login()无响应的原因和解决方案

微信小程序:wx.login和getPhonenumber获取手机号解密失败问题

微信小程序登陆授权

微信小程序获取openid

微信小程序登录

微信小程序获取openId SpringBoot