按照官网要求:从基础库 2.21.2 开始,对获取手机号的接口进行了安全升级 ;因为需要用户主动触发才能发起获取手机号接口,所以该功能不由 API 来调用,需用 button 组件的点击来触发 。
官网链接
HTML
- 需要将 button 组件 open-type 的值设置为 getPhoneNumber,当用户点击并同意之后,可以通过 bindgetphonenumber 事件回调获取iv和encryptedData
<button
open-type="getPhoneNumber"
@getphonenumber="getPhoneNumber"
>获取手机号</button>
JS
- js主要获取接口的几个参数
getPhoneNumber(e) {
// 点击触发的回调
console.log(e)
// 开发者兼容用户点击了拒绝的使用场景
if (e.target.errMsg == "getPhoneNumber:fail user deny") {
console.log("用户点击了拒绝")
wx.showToast({
title: '您取消了授权!!!',
icon: "none"
})
} else {
console.log("点击了允许", e.target)
// 利用后台去解密
let {iv, encryptedData} = e.target
//利用wx.login方法获取临时登录凭证code
wx.login({
success: (res) => {
console.log(res)
let code = res.code
let appid = 'wx4dd9330ad4e958c3'
//小程序秘钥 https://mp.weixin.qq.com/
let secret = 'ec842d018bd0d30xxxxxxxxxxxxxxx'
// 向后端发起网络请求
wx.request({
url: 'http://localhost:3001/getPhoneNumber', //服务器地址
method: "GET",//请求方式
data: {//接口参数
iv,
encryptedData,
code,
appid,
secret
},
header: {//请求头
"content-type": "application/json"
},
success: (res) => {
console.log('请求成功,手机号:=>',res)
}
})
}
})
}
},
node解密校验
- 微信开放平台提供了多种编程语言的解密示例,这里是node
- 其它语言解密示例
const { default: axios } = require("axios");
// // const hostName = '192.168.1.0'; //ip或域名
const hostName = 'localhost'; //ip或域名
const port = 3001; //端口
var express = require('express');
var app = new express();
// 处理post接参
var bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
// 引入请求模块
var WXBizDataCrypt = require('./WXBizDataCrypt')
//2.配置路由
app.get('/getPhoneNumber', async (req, res) => {
console.log('请求参数req:',req)
// 后台需要参数appid encryptedData appid secret code(临时登录凭证)
let { iv, encryptedData, appid, secret, code } = req.query
console.log('req.query',req.query)
/*
session_key:该参数值需要后端调用第三方接口获取,第三方接口需要参数值code appid secret
第三方接口:https://api.weixin.qq.com/sns/jscode2session
接口参数值:
appid:"开发者的appid",
secrect:"开发者的密钥",
js_code:临时的登录凭证,
grant_type:authorization_code//授权类型
code:临时登录凭证
*/
// 调用第三方接口获取session_key
let a = await axios({
url: "https://api.weixin.qq.com/sns/jscode2session?appid=" + appid + "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code",
method: "GET"
})
console.log('成功:=>',a)
var sessionKey = a.data.session_key
//解密
var pc = new WXBizDataCrypt(appid, sessionKey)
var data = pc.decryptData(encryptedData, iv)
//解密数据返给前端
res.send(data)
});
//3.监听端口
// app.listen(3000, 'localhost');
app.listen(port, ()=>{
console.log(`运行在端口:${hostName}:${port}`);
})
主要用到的官方提供的解密文件 WXBizDataCrypt.js
(下面内容在前面提到的官方文档里面就有)
注:官网里面的是new Buffer,这个已经弃用,文件里还没改,使用的时候要改一下,不然会报错,这个需要改成:Buffer.alloc() / Buffer.allocUnsafe() / Buffer.from()
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.from(this.sessionKey, 'base64')
encryptedData = new Buffer.from(encryptedData, 'base64')
iv = new Buffer.from(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
最后: