小程序获取微信运动步数
最近有个需求需要在小程序获取到微信的运动步数
看了一下微信的官方文档有个内置api可以用
wx.getWeRunData(Object object)
但是获取到的信息是加密的,需要解密后才能使用
细看文档官方给了四种不同语言的方法
这里我们使用Node,在前端本地进行解密
先看看官方的demo
javascript
//demo.js
var WXBizDataCrypt = require('./WXBizDataCrypt')
var appId = 'wx4f4bc4dec97d474b'
var sessionKey = 'tiihtNczf5v6AKRyjwEUhQ=='
var encryptedData =
'CiyLU1Aw2KjvrjMdj8YKliAjtP4gsMZM'+
'QmRzooG2xrDcvSnxIMXFufNstNGTyaGS'+
'9uT5geRa0W4oTOb1WT7fJlAC+oNPdbB+'+
'3hVbJSRgv+4lGOETKUQz6OYStslQ142d'+
'NCuabNPGBzlooOmB231qMM85d2/fV6Ch'+
'evvXvQP8Hkue1poOFtnEtpyxVLW1zAo6'+
'/1Xx1COxFvrc2d7UL/lmHInNlxuacJXw'+
'u0fjpXfz/YqYzBIBzD6WUfTIF9GRHpOn'+
'/Hz7saL8xz+W//FRAUid1OksQaQx4CMs'+
'8LOddcQhULW4ucetDf96JcR3g0gfRK4P'+
'C7E/r7Z6xNrXd2UIeorGj5Ef7b1pJAYB'+
'6Y5anaHqZ9J6nKEBvB4DnNLIVWSgARns'+
'/8wR2SiRS7MNACwTyrGvt9ts8p12PKFd'+
'lqYTopNHR1Vf7XjfhQlVsAJdNiKdYmYV'+
'oKlaRv85IfVunYzO0IKXsyl7JCUjCpoG'+
'20f0a04COwfneQAGGwd5oa+T8yO5hzuy'+
'Db/XcxxmK01EpqOyuxINew=='
var iv = 'r7BXXKkLb8qrSNn05n0qiA=='
var pc = new WXBizDataCrypt(appId, sessionKey)
var data = pc.decryptData(encryptedData , iv)
console.log('解密后 data: ', data)
// 解密后的数据为
//
// data = {
// "nickName": "Band",
// "gender": 1,
// "language": "zh_CN",
// "city": "Guangzhou",
// "province": "Guangdong",
// "country": "CN",
// "avatarUrl": "http://wx.qlogo.cn/mmopen/vi_32/aSKcBBPpibyKNicHNTMM0qJVh8Kjgiak2AHWr8MHM4WgMEm7GFhsf8OYrySdbvAMvTsw3mo8ibKicsnfN5pRjl1p8HQ/0",
// "unionId": "ocMvos6NjeKLIBqg5Mr9QjxrP1FA",
// "watermark": {
// "timestamp": 1477314187,
// "appid": "wx4f4bc4dec97d474b"
// }
// }
javascript
//WXBizDataCrypt.js
var crypto = require('crypto')
function WXBizDataCrypt(appId, sessionKey) {
this.appId = appId
this.sessionKey = sessionKey
}
WXBizDataCrypt.prototype.decryptData = function (encryptedData, iv) {
// base64 decode
var sessionKey = new Buffer(this.sessionKey, 'base64')
encryptedData = new Buffer(encryptedData, 'base64')
iv = new Buffer(iv, 'base64')
try {
// 解密
var decipher = crypto.createDecipheriv('aes-128-cbc', sessionKey, iv)
// 设置自动 padding 为 true,删除填充补位
decipher.setAutoPadding(true)
var decoded = decipher.update(encryptedData, 'binary', 'utf8')
decoded += decipher.final('utf8')
decoded = JSON.parse(decoded)
} catch (err) {
throw new Error('Illegal Buffer')
}
if (decoded.watermark.appid !== this.appId) {
throw new Error('Illegal Buffer')
}
return decoded
}
module.exports = WXBizDataCrypt
乍一看,官方的例子好像还行,但是用起来...不必多说
开始踩坑
问题1.将WXBizDataCrypt.js放入本地的utils后,马上报错找不到crypto
遂查之
原因是微信小程序的前端环境中不支持 Node.js 的 crypto 模块 ,因为 crypto
是 Node.js 的内置模块,主要用于服务器端的加密操作,而微信小程序运行在客户端,无法直接使用 Node.js 的模块
气煞我也
怒改之
- 使用 npm install crypto-js --save 将crypto-js下载到node_modules
- 找到 node_modules\crypto-js\crypto-js.js 将crypto-js.js复制到utils
- 将WXBizDataCrypt.js文件中的 var crypto = require('crypto') 替换为 const CryptoJS = require('crypto-js');
over,再跑一下
问题2.WXBizDataCrypt.js文件中Buffer不存在
遂查之
原因是Buffer
是 Node.js 中的一个核心模块,用于处理二进制数据。然而,微信小程序的前端环境并不支持 Node.js 的 Buffer
模块,因为它是基于浏览器环境的
怒喷之 (我***)
怒改之
-
使用 CryptoJS 的 Base64 解码
javascriptconst sessionKeyBuffer = CryptoJS.enc.Base64.parse(this.sessionKey); const encryptedDataBuffer = CryptoJS.enc.Base64.parse(encryptedData); const ivBuffer = CryptoJS.enc.Base64.parse(iv);
最终代码 WXBizDataCrypt.js
javascript
const CryptoJS = require('crypto-js');
function WXBizDataCrypt(appId, sessionKey) {
this.appId = appId;
this.sessionKey = sessionKey;
}
WXBizDataCrypt.prototype.decryptData = function (encryptedData, iv) {
// 使用 CryptoJS 的 Base64 解码
const sessionKeyBuffer = CryptoJS.enc.Base64.parse(this.sessionKey);
const encryptedDataBuffer = CryptoJS.enc.Base64.parse(encryptedData);
const ivBuffer = CryptoJS.enc.Base64.parse(iv);
try {
// 解密操作
const decrypted = CryptoJS.AES.decrypt(
{ ciphertext: encryptedDataBuffer },
sessionKeyBuffer,
{
iv: ivBuffer,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}
);
// 将解密后的数据转换为字符串
const decryptedText = decrypted.toString(CryptoJS.enc.Utf8);
// 将字符串解析为 JSON 对象
const decryptedData = JSON.parse(decryptedText);
// 校验 appid
if (decryptedData.watermark.appid !== this.appId) {
throw new Error('Invalid appid');
}
return decryptedData;
} catch (err) {
console.error('解密失败:', err);
throw new Error('Illegal Buffer');
}
}
module.exports = WXBizDataCrypt;
小程序中使用
javascript
wx.getWeRunData({
success: (res) => {
console.log("getWeRunData>>>",res)
// code: loginRes.code,
const encryptedData = res.encryptedData
const iv = res.iv
const appId = "*********" //自取
const sessionKey = "*********" //自取
var pc = new WXBizDataCrypt(appId, sessionKey)
var data = pc.decryptData(encryptedData , iv)
console.log('解密后 data: ', data)
}
});