You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
3.3 KiB
134 lines
3.3 KiB
'use strict';
|
|
/**
|
|
* 微信相关业务
|
|
*/
|
|
const {
|
|
wxConfigMp,
|
|
wxConfigApp,
|
|
} = require('config')
|
|
|
|
const crypto = require('crypto')
|
|
const db = uniCloud.database();
|
|
|
|
/**
|
|
* 微信小程序授权登录获取session_key
|
|
* @param {Object} options
|
|
* @param {String} options.code 小程序code
|
|
*
|
|
* @param {String} options.encryptedData 可选,存在encryptedData和iv时返回用户信息(包含unionid)
|
|
* @param {String} options.iv 可选
|
|
*/
|
|
const mpWxGetSessionKey = async options=>{
|
|
const {code, encryptedData, iv} = options;
|
|
const {appId, secret} = wxConfigMp;
|
|
|
|
let url = 'https://api.weixin.qq.com/sns/jscode2session';
|
|
url += '?appid=' + appId;
|
|
url += '&secret=' + secret;
|
|
url += '&js_code=' + code + '&grant_type=authorization_code';
|
|
const res = await uniCloud.httpclient.request(url, {
|
|
method: 'GET',
|
|
dataType: 'json'
|
|
})
|
|
const data = res.res.data;
|
|
if(data.errcode){
|
|
return {
|
|
status: 0,
|
|
msg: 'appid错误',
|
|
data,
|
|
appId
|
|
}
|
|
}
|
|
if(!data.session_key){
|
|
return {
|
|
status: 0,
|
|
msg: '获取微信授权失败',
|
|
data
|
|
}
|
|
}
|
|
if(!encryptedData || !iv){
|
|
return {
|
|
status: 1,
|
|
openid: data.openid,
|
|
session_key: data.session_key
|
|
}
|
|
}
|
|
const userInfo = WXBizDataCrypt({
|
|
sessionKey: data.session_key,
|
|
encryptedData,
|
|
iv
|
|
})
|
|
return {
|
|
status: 1,
|
|
session_key: data.session_key,
|
|
...userInfo
|
|
}
|
|
}
|
|
/**
|
|
* 获取AccessToken
|
|
*/
|
|
const getAccessToken = async options=>{
|
|
const accData = await db.collection('mix-access-token').get();
|
|
let accInfo = {};
|
|
if(accData.data.length === 1){
|
|
accInfo = accData.data[0]
|
|
//提前10分钟重新拉取
|
|
if(accInfo.access_token && accInfo.expires_in*1000 > + new Date() - accInfo.add_time - 10*60*1000){
|
|
return accInfo.access_token
|
|
}
|
|
}
|
|
const {appId, secret} = wxConfigMp;
|
|
let url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential';
|
|
url += '&appid=' + appId;
|
|
url += '&secret=' + secret;
|
|
const res = await uniCloud.httpclient.request(url, {
|
|
method: 'GET',
|
|
dataType: 'json'
|
|
})
|
|
await db.collection('mix-access-token').doc(accInfo._id || '1').set({
|
|
access_token: res.data.access_token,
|
|
expires_in: res.data.expires_in,
|
|
add_time: + new Date()
|
|
})
|
|
|
|
return res.data.access_token;
|
|
}
|
|
|
|
/**
|
|
* 解密encryptedData 获取unionid
|
|
* @param {Object} options
|
|
* @param {String} options.sessionKey
|
|
* @param {String} options.encryptedData
|
|
* @param {String} options.iv
|
|
*/
|
|
const WXBizDataCrypt = options=>{
|
|
const appId = wxConfigMp.appId;
|
|
let {sessionKey, encryptedData, iv} = options;
|
|
sessionKey = new Buffer(sessionKey, 'base64')
|
|
encryptedData = new Buffer(encryptedData, 'base64')
|
|
iv = new Buffer(iv, 'base64')
|
|
|
|
let decoded;
|
|
try {
|
|
// 解密
|
|
let decipher = crypto.createDecipheriv('aes-128-cbc', sessionKey, iv)
|
|
// 设置自动 padding 为 true,删除填充补位
|
|
decipher.setAutoPadding(true)
|
|
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 !== appId) {
|
|
throw new Error('Illegal Buffer')
|
|
}
|
|
return decoded
|
|
}
|
|
|
|
|
|
module.exports = {
|
|
mpWxGetSessionKey,
|
|
WXBizDataCrypt,
|
|
getAccessToken
|
|
}
|