手机号解密失败?扫盲帖+解决方案
发布于 4 年前 作者 yangxiuying 1875 次浏览 来自 分享

一、之前的解密流程,会偶现“解密失败”,步骤如下:

1、点击 ‘getPhoneNumber’ 的按钮,弹出授权界面

2、调用 wx.checkSession 进行检查,success 的话就发送授权手机号解密接口;fail 的话就进行 wx.login 获取 code 后请求后端获取 openid/sessionKey,并将两个值缓存到本地,然后再进行手机号解密。

二、粗暴方式解密流程,会偶现“解密失败”,步骤如下:

1、点击 ‘getPhoneNumber’ 的按钮,弹出授权界面

2、调用 wx.login 获取 code 后请求后端获取 openid/sessionKey,然后进行手机号解密

探讨微信解密机制(个人理解,如有不对,请指出哟),如下:

1、点击 ‘getPhoneNumber’ 的按钮,弹出授权界面时,在微信后台会生成一个加密的 ‘encryptedData’ 和拉取用于解密的 ‘sessionKey-0(-0为假想标识符)’,sessionKey 是 wx.login 解密之后生成的,在微信后台会存储。

2、按照如上错误的步骤,进行 wx.login 获取 code 再获取 sessionKey-1,由于 wx.login 会刷新微信后台的登录状态,此时获取的 sessionKey-1 和上一步中点击按钮在微信后台生成的 sessionKey-0 并不是同一个,于是解密失败了。

3、重点:必须保持操作前后的 sessionKey 都是同一个,如果 wx.login 刷新了后台的 sessionKey,而之前的操作还是原来的 sessionKey,则会失败。

必现方式一(解密失败),如下:

1、正常授权解密后,关闭小程序一段时间,测试的时候大概 30-40 分钟左右,后台 sessionKey 过期了

2、重新打开小程序走之前的步骤,出现“解密失败”,然后第二次进行授权解密时,又成功了

必现方式二(解密失败),如下:

1、清理缓存后,点击授权登录(此时后台的sessionKey为空,所以无论怎么做登录和检查,都会解密失败),弹出界面后调用 wx.login 进行登录获取 sessionKey

2、授权解密,失败

3、再次点击授权登录(此时会获取第一步中登录生成的 sessionKey,与未过期的sessionKey一致),则进行解密,成功。


解决方案,如下:

基于对上面机制的理解,wx.login 方式获取的 sessionKey 必须在唤起授权弹窗前进行,必须保证授权弹窗时获取的 sessionKey 和 本地未过期的sessionKey是同一个。

1、在 app.js 的 onLaunch 中,先进行 wx.checkSession。success,则进行后续代码执行;如果 fail,则进行 wx.login 重新获取 sessionKey,后端同学将 sessionKey 存储至数据库,openid 是唯一的,可以作为主键。此时,会先于任何操作之前生成一个 sessionKey。

2、唤起授权界面,点击“允许”后,将 openid+iv+encryptedData 传给后端进行解密。

代码如下(IDE复制后没发改样式,const 等变量可能看不清,可以复制到自己的编辑器中查看哈):

然后在 onLaunch 中调用 onLogin.checkSession 进行前置 session 检查和获取

export const onLogin = {
  // 检查 session 是否有效
  checkSession(cb = () => {}) {
    const _this = this;

    // 检查登录态是否可用
    wx.checkSession({
      success () {
        console.log('session success');
        // session_key 未过期,并且在本生命周期一直有效
        const { openid, session_key } = wx.getStorageSync('session');
        cb(openid, session_key);
      },
      // 登录态失效了
      fail () {
        console.log('session fail');
        _this._wxLogin((openid, session_key) => {
          cb(openid, session_key);
        });
      }
    });
  },
  // 微信获取 code 进行解密
  _wxLogin(cb = () => {}) {
    // 将 js_code 发送给后端获取 openId 和 sessionKey,并进行缓存
    wx.showLoading({ mask: true });
    wx.login({
      success: ({ code }) => {
        // 将 js_code 发送给后端获取 openId 和 sessionKey,并进行缓存
        request({
          url: `/wx/open/getSessionKey.json?code=${code}&clientIdentity=${CONFIG.clientIdentity}`,
          onSuccess: ({ openid, session_key }) => {
            wx.setStorageSync('session', { openid, session_key });
            cb(openid, session_key);
          },
          complete: () => {
            wx.hideLoading();
          }
        })
      }
    });
  },
}
回到顶部