在微信小程序中,如果想获取用户的昵称等信息可以不用另外写后台,如果需要获取用户的unionId,则需要后台来提供获取sessionKey和解码encryptedData。
wx.getUserInfo(OBJECT) 注意:此接口有调整,使用该接口将不再出现授权弹窗,请使用
<button wx:if="{{!hasUserInfo}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo">
获取用户信息 </button>
引导用户主动进行授权操作,需要注意: 1.当用户未授权过,调用该接口将直接进入fail回调 2.当用户授权过,可以使用该接口获取用户信息 js部分代码为:
getUserInfo: function(e) {
console.log(e)
app.globalData.userInfo = e.detail.userInfo
this.setData({
userInfo: e.detail.userInfo,
hasUserInfo: true
})
}
当用户点击按钮时则会弹出授权操作的按钮,用户通过授权后即可返回用户的信息,这些信息不包含unionId和openid。在app.js中可以判断用户是否授权过,如果授权过则不再进行授权,在有效期内科直接获取用户的信息
onLunch(){
// 获取用户信息
wx.getSetting({
success: res => {
if (res.authSetting['scope.userInfo']) {
// 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
console.log("获取");
wx.getUserInfo({
success: res => {
// 可以将 res 发送给后台解码出 unionId
this.globalData.userInfo = res.userInfo
console.log(res);
// 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
// 所以此处加入 callback 以防止这种情况
if (this.userInfoReadyCallback) {
this.userInfoReadyCallback(res)
}
}
})
}
}
})
}
至此简单的获取用户信息则完成了。
小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系。需要注意的一点是如果要获取unionid,则需要将小程序关联到微信开放平台,同时是已经认证过的账号。
登录流程时序
说明: 小程序调用wx.login() 获取 临时登录凭证code ,并回传到开发者服务器。
开发者服务器以code换取 用户唯一标识openid 和 会话密钥session_key。
之后开发者服务器可以根据用户标识来生成自定义登录态,用于后续业务逻辑中前后端交互时识别用户身份。
接下来先看小程序端的代码执行 app.js
onLaunch: function () {
var self = this;
// 登录
wx.login({
success: function (res) {
if (res.code) {
//发起网络请求
wx.request({
url: 'http://172.19.22.50:3000/api/wxUserInfo',
//获取session_key用于获取unionid
data: {
code: res.code
},
success: function (data) {
console.log(data);
wx.setStorageSync('session_key', data.data.session_key)
}
})
} else {
console.log('登录失败!' + res.errMsg)
}
}
});
// 获取用户信息
wx.getSetting({
success: res => {
if (res.authSetting['scope.userInfo']) {
// 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
console.log("获取");
wx.getUserInfo({
success: res => {
// 可以将 res 发送给后台解码出 unionId
this.globalData.userInfo = res.userInfo
var session_key = wx.getStorageSync('session_key');
self.getUnid(res.encryptedData, res.iv, session_key);
console.log(res);
// 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
// 所以此处加入 callback 以防止这种情况
if (this.userInfoReadyCallback) {
this.userInfoReadyCallback(res)
}
}
})
}
}
})
},
//获取unionid方法,
getUnid(encryptedData, iv, session_key){
wx.request({
url: 'http://172.19.22.50:3000/api/decodeUserInfo',
data: {
encryptedData: encryptedData,
iv: iv,
sessionKey: session_key
},
success: function (data) {
console.log(data);
}
})
}
在调用登录的页面还是需要一个点击获取用户信息的按钮
<button wx:if="{{!hasUserInfo}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo">
获取用户信息 </button>
js部分
getUserInfo: function(e) {
console.log(e)
app.globalData.userInfo = e.detail.userInfo
this.setData({
userInfo: e.detail.userInfo,
hasUserInfo: true
})
var session_key = wx.getStorageSync('session_key');
var encryptedData = e.detail.encryptedData;
var iv = e.detail.iv;
app.getUnid(encryptedData, iv, session_key);
}
此时,前面部分已经完成。在者就是需要搭建后台服务器来进行信息获取了。我这里以nodejs为后台进行获取示例
//用于获取session_key,方便后续解密encryptedData
router.get("/api/wxUserInfo",function(req,res){
var code = req.query.code;
var appid='appid';
var secret='secret'
var url = 'https://api.weixin.qq.com/sns/jscode2session?appid='+appid+'&secret='+secret+'&js_code=' + code+'&grant_type=authorization_code'
common.get_https_request(url,function(response){
if(response.success){
res.json(JSON.parse(response.body));
}else{
res.json(response);
}
})
});
对于解密算法,封装成了一个模块
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
然后再接口中进行调用
router.get("/api/decodeUserInfo",function(req,res){
var appId = 'appid';
var sessionKey = req.query.sessionKey;
var encryptedData = req.query.encryptedData;
var iv = req.query.iv;
var pc = new WXBizDataCrypt(appId, sessionKey)
var data = pc.decryptData(encryptedData , iv)
console.log('解密后 data: ', data)
res.json(data)
})
至此已经完成了整个流程,至于其他语言的解密算法,官方文档也给出了相应的方法,位置在下图中已经指出