node解密微信小程序用户信息偶然报错 Illegal Buffer

为什么会报错?

  • 没有一进入页面就获取code
  • 在点击获取了用户信息 wx.getUserProfile()完成之后才去获取code,导致偶然性解密失败
  • 错误信息
decodeWxUserInfo\WXBizDataCrypt.js:24
 throw new Error('Illegal Buffer err')
 Error: Illegal Buffer err
    at WXBizDataCrypt.decryptData (***\decodeWxUserInfo\WXBizDataCrypt.js:24:11)
    at Request._callback (***\getWxInfo\index.js:21:37)
    at Request.self.callback (***\node_modules\request\request.js:185:22)
    at Request.emit (node:events:390:28)
    at Request.<anonymous> (***\request\request.js:1154:10)
    at Request.emit (node:events:390:28)
    at IncomingMessage.<anonymous> (***\node_modules\request\request.js:1076:12)
    at Object.onceWrapper (node:events:509:28)
    at IncomingMessage.emit (node:events:402:35)
    at endReadableNT (node:internal/streams/readable:1343:12)

错误示例

<view class="login-page-btn" wx:if="{{!hasUserInfo}}">
    <van-button wx:if="{{canIUseGetUserProfile}}" bindtap="getUserProfile" type="info" size="large" round>登录</van-button>
</view>
data: {
    canIUseGetUserProfile: false,
},
onLoad(options) {
    if (wx.getUserProfile) {
        this.setData({
            canIUseGetUserProfile: true
        })
    }
},
getUserProfile(e) {
 // 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认
  wx.getUserProfile({
      desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
      success: (res) => {
          console.log('userInfo', res);
          this.login(res)
      },
      fail: _ => {
          wx.showToast({
              title: '用户信息获取失败',
              icon: "error",
              duration: 1000 * 2
          })
      }
  })
},
login(event) {
    wx.showLoading({
        title: '登陆中~',
    })
    const iv = event.iv;
    const encryptedData = event.encryptedData;
    
    this.getCode(iv, encryptedData)
},
getCode(iv, encryptedData) {
    // 登录
    wx.login({
        success: res => {
            wx.$http.post('getUserInfo', {
                code: res.code,
                iv,
                encryptedData
            }).then(res => {
                this.getUserInfo(res)
            }).catch(_ => {
                wx.hideLoading()
                wx.showToast({
                    title: '获取code失败,请重新登录',
                    icon: "none",
                    duration: 1000 * 3
                })
            })
            // 发送 res.code 到后台换取 openId, sessionKey, unionId
        }
    })
},
getUserInfo(res) {
    console.log('iv, encryptedData', res);
    wx.hideLoading()
    wx.showToast({
        title: res.msg,
        icon: "success",
        duration: 1000 * 1.5
    })
},
  • 这样操作的结果:

    • 起初正常

      • 在这里插入图片描述
    • 过一段时间再次点击会报node解密失败

      • 在这里插入图片描述
  • 这样的问题出现在wx.login需要在执行wx.getUserProfile() 之前拿到,具体原因未明

正确示例

  • 进入页面拿到code,存起来
  • 点击获取个人信息按钮,成功之后调用this.login()
  • 然后拿到code,iv,encryptedData发送给后端。
  • node通过code去换到openid,session_key,
  • node再通过session_key,iv,encryptedData去拿到加密后的用户信息进行解密
  • 如果code过期了直接返回
  • 否则进行解密,解密之后返回给前端
data: {
    canIUseGetUserProfile: false,
},
onLoad(options) {
    this.getCode();
    if (wx.getUserProfile) {
        this.setData({
            canIUseGetUserProfile: true
        })
    }
},
getCode() {
    // 登录
    wx.login({
        success: res => {
            this.setData({
                code: res.code
            })
        }
    })
},
getUserProfile(e) {
    // 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认
    wx.getUserProfile({
        desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
        success: (res) => {
            console.log('userInfo', res);
            this.login(res)
        },
        fail: _ => {
            wx.showToast({
                title: '用户信息获取失败',
                icon: "error",
                duration: 1000 * 2
            })
        }
    })
},
login(event) {
    wx.showLoading({
        title: '登陆中~',
    })
    const iv = event.iv;
    const encryptedData = event.encryptedData;

    wx.$http.post('getUserInfo', {
        code: this.data.code,
        iv,
        encryptedData
    }).then(res => {
        this.getUserInfo(res)
    }).catch(err => {
        wx.hideLoading()
        console.log(err);
        wx.showToast({
            title: err,
            icon: "none",
            duration: 1000 * 3
        })
    })
},
getUserInfo(res) {
    console.log('iv, encryptedData', res);
    wx.hideLoading()
    if (res.code === 40163) {
        wx.showToast({
            title: 'code过期,请重新登录!',
            icon: "none",
            duration: 1000 * 1.5
        })
        this.getCode() // 重新获取一次后,再次点击的时候可以用最新的code
    } else {
        wx.showToast({
            title: res.msg,
            icon: "success",
            duration: 1000 * 1.5
        })
    }
},
  • index.js
    import {getUserInfo } from './getWxInfo'
    const express = require('express');
    const router = express.Router();
    router.post('/getUserInfo', (req, res) => {
        const params = req.body;
        getWxInfo.getUserInfo(params.code, params.iv, params.encryptedData).then(child => {
            console.log('child', child);
            res.send({
                code: 200,
                msg: '登录成功',
                body: child
            });
        }).catch(err => {
            res.send({
                code: err.errcode,
                msg: err.errmsg,
                body: null
            })
            console.log({ err });
        })
    });
    
  • getWxInfo/index.js
    const request = require('request')
    const WXBizDataCrypt = require('../decodeWxUserInfo/WXBizDataCrypt')
    
    
    const APP_URL = 'https://api.weixin.qq.com/sns/jscode2session'
    const APP_ID = 'wx276*********2'   //自己小程序的app id ,在公众开发者后台可以看到
    const APP_SECRET = 'd37**************104'  //自己小程序的app secrect,在公众开发者后台可以看到
    exports.getUserInfo = async (code, iv, encryptedData) => {
        // let code=code //解析前端传递过来的参数js_code
        return new Promise((resolve, reject) => {
             request(`${APP_URL}?appid=${APP_ID}&secret=${APP_SECRET}&js_code=${code}&grant_type=authorization_code`, function (err, response, body) {
                if (!err && response.statusCode == 200) {
                    let JSONBody = JSON.parse(body)
                    if (!JSONBody.errcode) {
                        let session_key = JSONBody.session_key
                        const pc = new WXBizDataCrypt(APP_ID, session_key)
                        const data = pc.decryptData(encryptedData, iv)
                        resolve(data)
                    } else {
                        reject(JSONBody)
                    }
                } else {
                    console.log('errs');
                    reject(err)
                }
            })
        })
    }
    
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 这个误通常是由于在使用 `isset()` 或 `empty()` 函数时传入了一个非数组或对象类型的变量作为参数。 例如: ``` $x = "abc"; if (isset($x[0])) { // code here } ``` 在上面的代码中,由于 `$x` 是字符串类型,所以访问 `$x[0]` 时会抛出 "Illegal offset type" 误。 解决方法是确保传入 `isset()` 或 `empty()` 函数的参数是数组或对象类型,或者在使用数组或对象的方式访问变量之前先进行类型检查。 例如: ``` if (is_array($x) && isset($x[0])) { // code here } ``` 或者: ``` if (is_object($x) && isset($x->property)) { // code here } ``` ### 回答2: 该问题是由于在PHP7.1中使用了非法的偏移类型造成的。在PHP7.1之前的版本中,isset()或empty()函数可以接受任何类型的偏移量,包括整数、字符串、浮点数等。但是在PHP7.1中,这两个函数只能接受整数或字符串类型的偏移量。 解决这个问题的方法有两种。第一种方法是将非整数或非字符串类型的偏移量转换为整数或字符串类型。例如,可以使用intval()函数将浮点数转换为整数,使用strval()函数将其他类型的偏移量转换为字符串。然后再将转换后的偏移量传递给isset()或empty()函数进行操作。 第二种方法是使用数组的key_exists()函数来进行判断,而不是使用isset()或empty()函数。key_exists()函数不会对偏移量进行类型检查,因此可以接受任何类型的偏移量。但是需要注意的是,key_exists()函数只能用于数组,并且需要将数组和偏移量作为参数传递给该函数。 综上所述,要解决在PHP7.1中运行的小程序出现的"Illegal offset type in isset or empty",可以将非整数或非字符串类型的偏移量转换为整数或字符串类型,或者使用数组的key_exists()函数进行判断。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码の搬运工

记录学习,记录认知,记录。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值