'use strict'; const { PlatformType, ProviderType, ErrorCodeType } = require('./consts.js') const { AppConfig } = require('./config.js') const { Storage } = require('./storage.js') const { BridgeError } = require('./bridge-error.js') const { WeixinServer } = require('./weixin-server.js') const appConfig = new AppConfig() class AccessToken extends Storage { constructor() { super('access-token', ['provider', 'appid']) } async update(key) { super.update(key) const result = await this.getByWeixinServer(key) return this.set(key, result.value, result.duration) } async fallback(key) { return this.getByWeixinServer(key) } async getByWeixinServer(key) { const oauthConfig = appConfig.get(key.dcloudAppid, key.provider) let methodName if (key.provider === ProviderType.WEIXIN_MP) { methodName = 'GetMPAccessTokenData' } else if (key.provider === ProviderType.WEIXIN_H5) { methodName = 'GetH5AccessTokenData' } else { throw new BridgeError(ErrorCodeType.SYSTEM_ERROR, "provider invalid") } const responseData = await WeixinServer[methodName](oauthConfig) const duration = responseData.expires_in || (60 * 60 * 2) delete responseData.expires_in return { value: responseData, duration } } } class UserAccessToken extends Storage { constructor() { super('user-access-token', ['provider', 'appid', 'openid']) } } class SessionKey extends Storage { constructor() { super('session-key', ['provider', 'appid', 'openid']) } } class Encryptkey extends Storage { constructor() { super('encrypt-key', ['provider', 'appid', 'openid']) } async update(key) { super.update(key) const result = await this.getByWeixinServer(key) return this.set(key, result.value, result.duration) } getKeyString(key) { return `${super.getKeyString(key)}-${key.version}` } getExpiresIn(value) { if (value <= 0) { return 60 } return value } async fallback(key) { return this.getByWeixinServer(key) } async getByWeixinServer(key) { const accessToken = await Factory.Get(AccessToken, key) const userSession = await Factory.Get(SessionKey, key) const responseData = await WeixinServer.GetUserEncryptKeyData({ openid: key.openid, access_token: accessToken.access_token, session_key: userSession.session_key }) const keyInfo = responseData.key_info_list.find((item) => { return item.version === key.version }) if (!keyInfo) { throw new BridgeError(ErrorCodeType.SYSTEM_ERROR, 'key version invalid') } const value = { encrypt_key: keyInfo.encrypt_key, iv: keyInfo.iv } return { value, duration: keyInfo.expire_in } } } class Ticket extends Storage { constructor() { super('ticket', ['provider', 'appid']) } async update(key) { super.update(key) const result = await this.getByWeixinServer(key) return this.set(key, result.value, result.duration) } async fallback(key) { return this.getByWeixinServer(key) } async getByWeixinServer(key) { const accessToken = await Factory.Get(AccessToken, { dcloudAppid: key.dcloudAppid, provider: ProviderType.WEIXIN_H5 }) const responseData = await WeixinServer.GetH5TicketData(accessToken) const duration = responseData.expires_in || (60 * 60 * 2) delete responseData.expires_in delete responseData.errcode delete responseData.errmsg return { value: responseData, duration } } } const Factory = { async Get(T, key, fallback) { Factory.FixOldKey(key) return Factory.MakeUnique(T).get(key, fallback) }, async Set(T, key, value, expiresIn) { Factory.FixOldKey(key) return Factory.MakeUnique(T).set(key, value, expiresIn) }, async Remove(T, key) { Factory.FixOldKey(key) return Factory.MakeUnique(T).remove(key) }, async Update(T, key) { Factory.FixOldKey(key) return Factory.MakeUnique(T).update(key) }, FixOldKey(key) { if (!key.provider) { key.provider = key.platform } const configData = appConfig.get(key.dcloudAppid, key.provider) if (!configData) { throw new BridgeError(ErrorCodeType.SYSTEM_ERROR, 'appid or provider invalid') } key.appid = configData.appid }, MakeUnique(T) { return new T() } } // exports async function getAccessToken(key, fallback) { return Factory.Get(AccessToken, key, fallback) } async function setAccessToken(key, value, expiresIn) { return Factory.Set(AccessToken, key, value, expiresIn) } async function removeAccessToken(key) { return Factory.Remove(AccessToken, key) } async function updateAccessToken(key) { return Factory.Update(AccessToken, key) } async function getUserAccessToken(key, fallback) { return Factory.Get(UserAccessToken, key, fallback) } async function setUserAccessToken(key, value, expiresIn) { return Factory.Set(UserAccessToken, key, value, expiresIn) } async function removeUserAccessToken(key) { return Factory.Remove(UserAccessToken, key) } async function getSessionKey(key, fallback) { return Factory.Get(SessionKey, key, fallback) } async function setSessionKey(key, value, expiresIn) { return Factory.Set(SessionKey, key, value, expiresIn) } async function removeSessionKey(key) { return Factory.Remove(SessionKey, key) } async function getEncryptKey(key, fallback) { return Factory.Get(Encryptkey, key, fallback) } async function setEncryptKey(key, value, expiresIn) { return Factory.Set(Encryptkey, key, value, expiresIn) } async function removeEncryptKey(key) { return Factory.Remove(Encryptkey, key) } async function updateEncryptKey(key) { return Factory.Update(Encryptkey, key) } async function getTicket(key, fallback) { return Factory.Get(Ticket, key, fallback) } async function setTicket(key, value, expiresIn) { return Factory.Set(Ticket, key, value, expiresIn) } async function removeTicket(key) { return Factory.Remove(Ticket, key) } async function updateTicket(key) { return Factory.Update(Ticket, key) } module.exports = { getAccessToken, setAccessToken, removeAccessToken, updateAccessToken, getUserAccessToken, setUserAccessToken, removeUserAccessToken, getSessionKey, setSessionKey, removeSessionKey, getEncryptKey, setEncryptKey, removeEncryptKey, updateEncryptKey, getTicket, setTicket, removeTicket, updateTicket, ProviderType, PlatformType, WeixinServer, ErrorCodeType }