一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情。
主要功能是,使用 nodejs 作为后端,去获取微信小程序的 openid。此处的 openid 用于作为使用小程序的唯一标识。
一、步骤概述
(1)微信小程序的功能
首先小程序登录功能,调用 wx.login 接口获取登录凭证(code),调用 wx.getUserProfile 接口获取 encryptedData 和 iv
wx.login 文档:点击查看
wx.login 接口请求参数和返回值:
wx.getUserProfile 文档:点击查看
wx.getUserProfile 接口请求参数和返回值:
其中,encryptedData 包括敏感数据在内的完整用户信息的加密数据;iv 是加密算法的初始向量,详见 用户数据的签名验证和加解密
在微信小程序端,将 code,encryptedData 和 iv 三个的值传给后端。
(2)nodejs 后台的功能
在nodejs端,调用 auth.code2Session 去获取 openid 和 sessionKey。再使用 sessionKey 去解密得到用户信息,将用户信息保存进表里,完成登录过程。
auth.code2Session 文档:点击查看
请求参数和返回值:
二、具体代码
小程序代码
index.wxml
<view class='login-btn'>
<button class='bottom-btn' open-type="getUserInfo" bindgetuserinfo="getUserInfo">立即登录</button>
</view>
inde.js
Page({
/**获取用户授权及信息 */
getUserInfo: function (e) {
let that = this;
if (e.detail.userInfo) {
//用户按了允许授权按钮
wx.showLoading({
title: '正在登录...',
})
wx.login({
success: res => {
let code = res.code; //获取登录的临时凭证
if (code) {
//获取授权信息
wx.getSetting({
success: function (res) {
if (res.authSetting['scope.userInfo']) {
//获取用户信息:getUserInfo必须是在用户已经授权的情况下调用
wx.getUserInfo({
withCredentials: true,
success: res => {
app.globalData.userInfo = res.userInfo //非敏感用户信息
// 发送请求,获取openid
let url = " xxxxx";//后台请求地址
let params = {
"code": code,
"encryptedData": res.encryptedData,
"iv": res.iv
}
http.request(url, "POST", params ).then(loginInfo => {
console.log("loginInfo:", loginInfo);
})
}
})
}
}
});
}
}
});
}
}
})
request.js utils 工具类里的方法,用于网络请求
function request(url, method, params) {
let apiUrl = "http://xx.xx.xx.xx:8080/";
return new Promise((resolve, reject) => {
wx.request({
url: apiUrl + url,
data: params,
header: {
'content-type': 'application/json'
},
method: method,
dataType: 'json',
responseType: 'text',
success: function(res) {
if (res.statusCode == 200) {
resolve(res.data);
}
if (res.statusCode == 500) {
wx.showToast({
title: '服务异常',
})
}
},
fail: function(err) {
wx.hideLoading();
reject(err);
},
complete: function(res) {
wx.hideLoading();
},
})
});
}
module.exports = {
request: request
}
nodejs 代码
获取openid和sessionKey
let encryptedData = params.encryptedData;//获取小程序传来的encryptedData
let iv = params.iv;//获取小程序传来的iv
let appid = "xxxxxxx";//自己小程序后台管理的appid,可登录小程序后台查看
let secret = "xxxxxxx";//小程序后台管理的secret,可登录小程序后台查看
let grant_type = "authorization_code";// 授权(必填)默认值
//请求获取openid
let url = "https://api.weixin.qq.com/sns/jscode2session?grant_type="+grant_type+"&appid="+appid+"&secret="+secret+"&js_code="+code;
let openid,sessionKey;
let https = require("https");
https.get(url, (res) => {
res.on('data', (d) => {
console.log('返回的信息: ', JSON.parse(d));
openid = JSON.parse(d).openid;//得到openid
sessionKey = JSON.parse(d).session_key;//得到session_key
}).on('error', (e) => {
console.error(e);
});
});
下面这部分,是解密,解密后,可得到用户信息。 其实在用户授权后,也能在小程序上通过 wx.getUserInfo 方法,去获取到这些用户信息。
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
}
//解密
var pc = new WXBizDataCrypt(appid, sessionKey);//这里的sessionKey 是上面获取到的
var decodeData = pc.decryptData(encryptedData , iv);//encryptedData 是从小程序获取到的
console.log('解密后 data: ', decodeData);
完毕~