|
|
const crypto = require('crypto')
|
|
|
const {
|
|
|
userCollection
|
|
|
} = require('../../common/constants')
|
|
|
const {
|
|
|
ERROR
|
|
|
} = require('../../common/error')
|
|
|
const {
|
|
|
getRedisEnable
|
|
|
} = require('./utils')
|
|
|
const {
|
|
|
openDataCollection
|
|
|
} = require('../../common/constants')
|
|
|
|
|
|
function decryptWeixinData ({
|
|
|
encryptedData,
|
|
|
sessionKey,
|
|
|
iv
|
|
|
} = {}) {
|
|
|
const oauthConfig = this.configUtils.getOauthConfig({
|
|
|
provider: 'weixin'
|
|
|
})
|
|
|
const decipher = crypto.createDecipheriv(
|
|
|
'aes-128-cbc',
|
|
|
Buffer.from(sessionKey, 'base64'),
|
|
|
Buffer.from(iv, 'base64')
|
|
|
)
|
|
|
// 设置自动 padding 为 true,删除填充补位
|
|
|
decipher.setAutoPadding(true)
|
|
|
let decoded
|
|
|
decoded = decipher.update(encryptedData, 'base64', 'utf8')
|
|
|
decoded += decipher.final('utf8')
|
|
|
decoded = JSON.parse(decoded)
|
|
|
if (decoded.watermark.appid !== oauthConfig.appid) {
|
|
|
throw new Error('Invalid wechat appid in decode content')
|
|
|
}
|
|
|
return decoded
|
|
|
}
|
|
|
|
|
|
function getWeixinPlatform () {
|
|
|
const platform = this.clientPlatform
|
|
|
const userAgent = this.getUniversalClientInfo().userAgent
|
|
|
switch (platform) {
|
|
|
case 'app':
|
|
|
case 'app-plus':
|
|
|
return 'app'
|
|
|
case 'mp-weixin':
|
|
|
return 'mp'
|
|
|
case 'h5':
|
|
|
case 'web':
|
|
|
return userAgent.indexOf('MicroMessenger') > -1 ? 'h5' : 'web'
|
|
|
default:
|
|
|
throw new Error('Unsupported weixin platform')
|
|
|
}
|
|
|
}
|
|
|
|
|
|
async function saveWeixinUserKey ({
|
|
|
openid,
|
|
|
sessionKey, // 微信小程序用户sessionKey
|
|
|
accessToken, // App端微信用户accessToken
|
|
|
refreshToken, // App端微信用户refreshToken
|
|
|
accessTokenExpired // App端微信用户accessToken过期时间
|
|
|
} = {}) {
|
|
|
// 微信公众平台、开放平台refreshToken有效期均为30天(微信没有在网络请求里面返回30天这个值,务必注意未来可能出现调整,需及时更新此处逻辑)。
|
|
|
// 此前QQ开放平台有调整过accessToken的过期时间:[access_token有效期由90天缩短至30天](https://wiki.connect.qq.com/%E3%80%90qq%E4%BA%92%E8%81%94%E3%80%91access_token%E6%9C%89%E6%95%88%E6%9C%9F%E8%B0%83%E6%95%B4)
|
|
|
|
|
|
const appId = this.getUniversalClientInfo().appId
|
|
|
const weixinPlatform = getWeixinPlatform.call(this)
|
|
|
const keyObj = {
|
|
|
dcloudAppid: appId,
|
|
|
openid,
|
|
|
platform: 'weixin-' + weixinPlatform
|
|
|
}
|
|
|
switch (weixinPlatform) {
|
|
|
case 'mp':
|
|
|
await this.uniOpenBridge.setSessionKey(keyObj, {
|
|
|
session_key: sessionKey
|
|
|
}, 30 * 24 * 60 * 60)
|
|
|
break
|
|
|
case 'app':
|
|
|
case 'h5':
|
|
|
case 'web':
|
|
|
await this.uniOpenBridge.setUserAccessToken(keyObj, {
|
|
|
access_token: accessToken,
|
|
|
refresh_token: refreshToken,
|
|
|
access_token_expired: accessTokenExpired
|
|
|
}, 30 * 24 * 60 * 60)
|
|
|
break
|
|
|
default:
|
|
|
break
|
|
|
}
|
|
|
}
|
|
|
|
|
|
async function saveSecureNetworkCache ({
|
|
|
code,
|
|
|
openid,
|
|
|
unionid,
|
|
|
sessionKey
|
|
|
}) {
|
|
|
const {
|
|
|
appId
|
|
|
} = this.getUniversalClientInfo()
|
|
|
const key = `uni-id:${appId}:weixin-mp:code:${code}:secure-network-cache`
|
|
|
const value = JSON.stringify({
|
|
|
openid,
|
|
|
unionid,
|
|
|
session_key: sessionKey
|
|
|
})
|
|
|
// 此处存储的是code的缓存,设置有效期和token一致
|
|
|
const expiredSeconds = this.config.tokenExpiresIn || 3 * 24 * 60 * 60
|
|
|
|
|
|
await openDataCollection.doc(key).set({
|
|
|
value,
|
|
|
expired: Date.now() + expiredSeconds * 1000
|
|
|
})
|
|
|
const isRedisEnable = getRedisEnable()
|
|
|
if (isRedisEnable) {
|
|
|
const redis = uniCloud.redis()
|
|
|
await redis.set(key, value, 'EX', expiredSeconds)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function generateWeixinCache ({
|
|
|
sessionKey, // 微信小程序用户sessionKey
|
|
|
accessToken, // App端微信用户accessToken
|
|
|
refreshToken, // App端微信用户refreshToken
|
|
|
accessTokenExpired // App端微信用户accessToken过期时间
|
|
|
} = {}) {
|
|
|
const platform = getWeixinPlatform.call(this)
|
|
|
let cache
|
|
|
switch (platform) {
|
|
|
case 'app':
|
|
|
case 'h5':
|
|
|
case 'web':
|
|
|
cache = {
|
|
|
access_token: accessToken,
|
|
|
refresh_token: refreshToken,
|
|
|
access_token_expired: accessTokenExpired
|
|
|
}
|
|
|
break
|
|
|
case 'mp':
|
|
|
cache = {
|
|
|
session_key: sessionKey
|
|
|
}
|
|
|
break
|
|
|
default:
|
|
|
throw new Error('Unsupported weixin platform')
|
|
|
}
|
|
|
return {
|
|
|
third_party: {
|
|
|
[`${platform}_weixin`]: cache
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function getWeixinOpenid ({
|
|
|
userRecord
|
|
|
} = {}) {
|
|
|
const weixinPlatform = getWeixinPlatform.call(this)
|
|
|
const appId = this.getUniversalClientInfo().appId
|
|
|
const wxOpenidObj = userRecord.wx_openid
|
|
|
if (!wxOpenidObj) {
|
|
|
return
|
|
|
}
|
|
|
return wxOpenidObj[`${weixinPlatform}_${appId}`] || wxOpenidObj[weixinPlatform]
|
|
|
}
|
|
|
|
|
|
async function getWeixinCacheFallback ({
|
|
|
userRecord,
|
|
|
key
|
|
|
} = {}) {
|
|
|
const platform = getWeixinPlatform.call(this)
|
|
|
const thirdParty = userRecord && userRecord.third_party
|
|
|
if (!thirdParty) {
|
|
|
return
|
|
|
}
|
|
|
const weixinCache = thirdParty[`${platform}_weixin`]
|
|
|
return weixinCache && weixinCache[key]
|
|
|
}
|
|
|
|
|
|
async function getWeixinCache ({
|
|
|
uid,
|
|
|
userRecord,
|
|
|
key
|
|
|
} = {}) {
|
|
|
const weixinPlatform = getWeixinPlatform.call(this)
|
|
|
const appId = this.getUniversalClientInfo().appId
|
|
|
if (!userRecord) {
|
|
|
const getUserRes = await userCollection.doc(uid).get()
|
|
|
userRecord = getUserRes.data[0]
|
|
|
}
|
|
|
if (!userRecord) {
|
|
|
throw {
|
|
|
errCode: ERROR.ACCOUNT_NOT_EXISTS
|
|
|
}
|
|
|
}
|
|
|
const openid = getWeixinOpenid.call(this, {
|
|
|
userRecord
|
|
|
})
|
|
|
const getCacheMethod = weixinPlatform === 'mp' ? 'getSessionKey' : 'getUserAccessToken'
|
|
|
const userKey = await this.uniOpenBridge[getCacheMethod]({
|
|
|
dcloudAppid: appId,
|
|
|
platform: 'weixin-' + weixinPlatform,
|
|
|
openid
|
|
|
})
|
|
|
if (userKey) {
|
|
|
return userKey[key]
|
|
|
}
|
|
|
return getWeixinCacheFallback({
|
|
|
userRecord,
|
|
|
key
|
|
|
})
|
|
|
}
|
|
|
|
|
|
async function getWeixinAccessToken () {
|
|
|
const weixinPlatform = getWeixinPlatform.call(this)
|
|
|
const appId = this.getUniversalClientInfo().appId
|
|
|
|
|
|
const cache = await this.uniOpenBridge.getAccessToken({
|
|
|
dcloudAppid: appId,
|
|
|
platform: 'weixin-' + weixinPlatform
|
|
|
})
|
|
|
|
|
|
return cache.access_token
|
|
|
}
|
|
|
module.exports = {
|
|
|
decryptWeixinData,
|
|
|
getWeixinPlatform,
|
|
|
generateWeixinCache,
|
|
|
getWeixinCache,
|
|
|
saveWeixinUserKey,
|
|
|
getWeixinAccessToken,
|
|
|
saveSecureNetworkCache
|
|
|
}
|