From 4762d3c67fa924ffaecb92ecb0a5eb5587e43fc9 Mon Sep 17 00:00:00 2001 From: Anne_LXM Date: Fri, 13 Sep 2024 17:53:00 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E7=9A=84uni-id-pages=E7=9A=84=E7=89=88=E6=9C=AC=E4=B8=BA1.1.22?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- uni_modules/uni-id-pages/changelog.md | 3 + .../uni-id-pages-sms-form.vue | 2 +- uni_modules/uni-id-pages/package.json | 4 +- .../pages/login/login-withoutpwd.vue | 2 +- .../pages/login/login-withpwd.vue | 4 +- .../pages/retrieve/retrieve-by-email.vue | 6 +- .../uni-id-pages/pages/retrieve/retrieve.vue | 6 +- .../cloudfunctions/uni-id-co/package.json | 4 +- .../uni-open-bridge-common/changelog.md | 4 +- .../uni-open-bridge-common/package.json | 6 +- uni_modules/uni-open-bridge-common/readme.md | 10 +- .../uni-open-bridge-common/bridge-error.js | 8 +- .../common/uni-open-bridge-common/config.js | 246 +++---- .../common/uni-open-bridge-common/consts.js | 58 +- .../common/uni-open-bridge-common/index.js | 632 ++++++++--------- .../uni-open-bridge-common/package.json | 30 +- .../common/uni-open-bridge-common/storage.js | 225 +++--- .../uni-open-bridge-common/uni-cloud-cache.js | 646 +++++++++--------- .../uni-open-bridge-common/validator.js | 60 +- .../uni-open-bridge-common/weixin-server.js | 404 +++++------ .../database/opendb-open-data.schema.json | 36 +- 21 files changed, 1206 insertions(+), 1190 deletions(-) diff --git a/uni_modules/uni-id-pages/changelog.md b/uni_modules/uni-id-pages/changelog.md index 60be677..1d5ca1a 100644 --- a/uni_modules/uni-id-pages/changelog.md +++ b/uni_modules/uni-id-pages/changelog.md @@ -1,3 +1,6 @@ +## 1.1.22(2024-09-13) +- 注册登录时去除字符串两端的空白字符 +- 删除static目录下重复资源 ## 1.1.21(2024-08-02) - uni-id-co 修复联登更新用户信息接口存在手机号或者邮箱时没有设置认证状态 ## 1.1.20(2024-04-28) diff --git a/uni_modules/uni-id-pages/components/uni-id-pages-sms-form/uni-id-pages-sms-form.vue b/uni_modules/uni-id-pages/components/uni-id-pages-sms-form/uni-id-pages-sms-form.vue index 0a4eba3..a91ecbf 100644 --- a/uni_modules/uni-id-pages/components/uni-id-pages-sms-form/uni-id-pages-sms-form.vue +++ b/uni_modules/uni-id-pages/components/uni-id-pages-sms-form/uni-id-pages-sms-form.vue @@ -2,7 +2,7 @@ - diff --git a/uni_modules/uni-id-pages/package.json b/uni_modules/uni-id-pages/package.json index 606c01a..246be09 100644 --- a/uni_modules/uni-id-pages/package.json +++ b/uni_modules/uni-id-pages/package.json @@ -1,7 +1,7 @@ { "id": "uni-id-pages", "displayName": "uni-id-pages", - "version": "1.1.21", + "version": "1.1.22", "description": "云端一体简单、统一、可扩展的用户中心页面模版", "keywords": [ "用户管理", @@ -12,7 +12,7 @@ ], "repository": "https://gitcode.net/dcloud/hello_uni-id-pages", "engines": { - "HBuilderX": "^3.4.17" + "HBuilderX": "^4.15" }, "dcloudext": { "sale": { diff --git a/uni_modules/uni-id-pages/pages/login/login-withoutpwd.vue b/uni_modules/uni-id-pages/pages/login/login-withoutpwd.vue index 64a6bcf..7631d7a 100644 --- a/uni_modules/uni-id-pages/pages/login/login-withoutpwd.vue +++ b/uni_modules/uni-id-pages/pages/login/login-withoutpwd.vue @@ -21,7 +21,7 @@ 未注册的账号验证通过后将自动注册 +86 - diff --git a/uni_modules/uni-id-pages/pages/login/login-withpwd.vue b/uni_modules/uni-id-pages/pages/login/login-withpwd.vue index 3fc4b95..42ae09a 100644 --- a/uni_modules/uni-id-pages/pages/login/login-withpwd.vue +++ b/uni_modules/uni-id-pages/pages/login/login-withpwd.vue @@ -9,11 +9,11 @@ + :inputBorder="false" v-model="username" placeholder="请输入手机号/用户名/邮箱" trim="all" /> + type="password" :inputBorder="false" v-model="password" placeholder="请输入密码" trim="all" /> diff --git a/uni_modules/uni-id-pages/pages/retrieve/retrieve-by-email.vue b/uni_modules/uni-id-pages/pages/retrieve/retrieve-by-email.vue index bf30c76..83a9716 100644 --- a/uni_modules/uni-id-pages/pages/retrieve/retrieve-by-email.vue +++ b/uni_modules/uni-id-pages/pages/retrieve/retrieve-by-email.vue @@ -10,7 +10,7 @@ - @@ -19,11 +19,11 @@ - - diff --git a/uni_modules/uni-id-pages/pages/retrieve/retrieve.vue b/uni_modules/uni-id-pages/pages/retrieve/retrieve.vue index 73cfa36..2c06a6e 100644 --- a/uni_modules/uni-id-pages/pages/retrieve/retrieve.vue +++ b/uni_modules/uni-id-pages/pages/retrieve/retrieve.vue @@ -10,7 +10,7 @@ - @@ -19,11 +19,11 @@ - - diff --git a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/package.json b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/package.json index 61cc2ba..5183ca6 100644 --- a/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/package.json +++ b/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/package.json @@ -20,6 +20,8 @@ "cloudfunction-config": { "keepRunningAfterReturn": false }, + "origin-plugin-dev-name": "uni-id-pages", + "origin-plugin-version": "1.1.22", "plugin-dev-name": "uni-id-pages", - "plugin-version": "1.1.21" + "plugin-version": "1.1.22" } diff --git a/uni_modules/uni-open-bridge-common/changelog.md b/uni_modules/uni-open-bridge-common/changelog.md index e97c535..2468437 100644 --- a/uni_modules/uni-open-bridge-common/changelog.md +++ b/uni_modules/uni-open-bridge-common/changelog.md @@ -1,5 +1,7 @@ +## 1.2.1(2024-09-13) +- 修复 微信小程序平台 当微信的服务器返回`encrypt_key`的过期时间`expire_in`为`0`时特殊处理为`1`天,否者可能无法验证客户端请求携带的版本 ## 1.2.0(2023-04-27) -- 优化 微信小程序平台 使用微信新增 API getStableAccessToken 获取 access_token, access_token 有效期内重复调用该接口不会更新 access_token, [详情](https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getStableAccessToken.html) +- 重要 微信小程序平台 使用微信新增 API getStableAccessToken 获取 access_token, access_token 有效期内重复调用该接口不会更新 access_token, [详情](https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getStableAccessToken.html) ## 1.1.5(2023-03-27) - 修复 微信小程序平台 某些情况下 encrypt_key 插入错误的问题 ## 1.1.4(2023-03-13) diff --git a/uni_modules/uni-open-bridge-common/package.json b/uni_modules/uni-open-bridge-common/package.json index 30f2620..d89290f 100644 --- a/uni_modules/uni-open-bridge-common/package.json +++ b/uni_modules/uni-open-bridge-common/package.json @@ -1,10 +1,9 @@ { "id": "uni-open-bridge-common", "displayName": "uni-open-bridge-common", - "version": "1.2.0", + "version": "1.2.1", "description": "统一接管微信等三方平台认证凭据", "keywords": [ - "uni-open-bridge-common", "access_token", "session_key", "ticket" @@ -39,7 +38,8 @@ "platforms": { "cloud": { "tcb": "y", - "aliyun": "y" + "aliyun": "y", + "alipay": "n" }, "client": { "Vue": { diff --git a/uni_modules/uni-open-bridge-common/readme.md b/uni_modules/uni-open-bridge-common/readme.md index de28c36..3892384 100644 --- a/uni_modules/uni-open-bridge-common/readme.md +++ b/uni_modules/uni-open-bridge-common/readme.md @@ -1,5 +1,5 @@ -# uni-open-bridge-common - -`uni-open-bridge-common` 是统一接管微信等三方平台认证凭据(包括但不限于`access_token`、`session_key`、`encrypt_key`、`ticket`)的开源库。 - -文档链接 [https://uniapp.dcloud.net.cn/uniCloud/uni-open-bridge#common](https://uniapp.dcloud.net.cn/uniCloud/uni-open-bridge#common) +# uni-open-bridge-common + +`uni-open-bridge-common` 是统一接管微信等三方平台认证凭据(包括但不限于`access_token`、`session_key`、`encrypt_key`、`ticket`)的开源库。 + +文档链接 [https://uniapp.dcloud.net.cn/uniCloud/uni-open-bridge#common](https://uniapp.dcloud.net.cn/uniCloud/uni-open-bridge#common) diff --git a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/bridge-error.js b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/bridge-error.js index b6cfe66..95160a4 100644 --- a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/bridge-error.js +++ b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/bridge-error.js @@ -1,4 +1,4 @@ -'use strict'; +'use strict'; class BridgeError extends Error { @@ -20,7 +20,7 @@ class BridgeError extends Error { return this.message } } - -module.exports = { - BridgeError + +module.exports = { + BridgeError } diff --git a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/config.js b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/config.js index 063c746..d083f00 100644 --- a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/config.js +++ b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/config.js @@ -1,124 +1,124 @@ -'use strict'; - -const { - ProviderType -} = require('./consts.js') - -const configCenter = require('uni-config-center') - -// 多维数据为兼容uni-id以前版本配置 -const OauthConfig = { - 'weixin-app': [ - ['app', 'oauth', 'weixin'], - ['app-plus', 'oauth', 'weixin'] - ], - 'weixin-mp': [ - ['mp-weixin', 'oauth', 'weixin'] - ], - 'weixin-h5': [ - ['web', 'oauth', 'weixin-h5'], - ['h5-weixin', 'oauth', 'weixin'], - ['h5', 'oauth', 'weixin'] - ], - 'weixin-web': [ - ['web', 'oauth', 'weixin-web'] - ], - 'qq-app': [ - ['app', 'oauth', 'qq'], - ['app-plus', 'oauth', 'qq'] - ], - 'qq-mp': [ - ['mp-qq', 'oauth', 'qq'] - ] -} - -const Support_Platforms = [ - ProviderType.WEIXIN_MP, - ProviderType.WEIXIN_H5, - ProviderType.WEIXIN_APP, - ProviderType.WEIXIN_WEB, - ProviderType.QQ_MP, - ProviderType.QQ_APP -] - -class ConfigBase { - - constructor() { - const uniIdConfigCenter = configCenter({ - pluginId: 'uni-id' - }) - - this._uniIdConfig = uniIdConfigCenter.config() - } - - getAppConfig(appid) { - if (Array.isArray(this._uniIdConfig)) { - return this._uniIdConfig.find((item) => { - return (item.dcloudAppid === appid) - }) - } - return this._uniIdConfig - } -} - -class AppConfig extends ConfigBase { - - constructor() { - super() - } - - get(appid, platform) { - if (!this.isSupport(platform)) { - return null - } - - let appConfig = this.getAppConfig(appid) - if (!appConfig) { - return null - } - - return this.getOauthConfig(appConfig, platform) - } - - isSupport(platformName) { - return (Support_Platforms.indexOf(platformName) >= 0) - } - - getOauthConfig(appConfig, platformName) { - let treePath = OauthConfig[platformName] - let node = this.findNode(appConfig, treePath) - if (node && node.appid && node.appsecret) { - return { - appid: node.appid, - secret: node.appsecret - } - } - return null - } - - findNode(treeNode, arrayPath) { - let node = treeNode - for (let treePath of arrayPath) { - for (let name of treePath) { - const currentNode = node[name] - if (currentNode) { - node = currentNode - } else { - node = null - break - } - } - if (node === null) { - node = treeNode - } else { - break - } - } - return node - } -} - - -module.exports = { - AppConfig +'use strict'; + +const { + ProviderType +} = require('./consts.js') + +const configCenter = require('uni-config-center') + +// 多维数据为兼容uni-id以前版本配置 +const OauthConfig = { + 'weixin-app': [ + ['app', 'oauth', 'weixin'], + ['app-plus', 'oauth', 'weixin'] + ], + 'weixin-mp': [ + ['mp-weixin', 'oauth', 'weixin'] + ], + 'weixin-h5': [ + ['web', 'oauth', 'weixin-h5'], + ['h5-weixin', 'oauth', 'weixin'], + ['h5', 'oauth', 'weixin'] + ], + 'weixin-web': [ + ['web', 'oauth', 'weixin-web'] + ], + 'qq-app': [ + ['app', 'oauth', 'qq'], + ['app-plus', 'oauth', 'qq'] + ], + 'qq-mp': [ + ['mp-qq', 'oauth', 'qq'] + ] +} + +const Support_Platforms = [ + ProviderType.WEIXIN_MP, + ProviderType.WEIXIN_H5, + ProviderType.WEIXIN_APP, + ProviderType.WEIXIN_WEB, + ProviderType.QQ_MP, + ProviderType.QQ_APP +] + +class ConfigBase { + + constructor() { + const uniIdConfigCenter = configCenter({ + pluginId: 'uni-id' + }) + + this._uniIdConfig = uniIdConfigCenter.config() + } + + getAppConfig(appid) { + if (Array.isArray(this._uniIdConfig)) { + return this._uniIdConfig.find((item) => { + return (item.dcloudAppid === appid) + }) + } + return this._uniIdConfig + } +} + +class AppConfig extends ConfigBase { + + constructor() { + super() + } + + get(appid, platform) { + if (!this.isSupport(platform)) { + return null + } + + let appConfig = this.getAppConfig(appid) + if (!appConfig) { + return null + } + + return this.getOauthConfig(appConfig, platform) + } + + isSupport(platformName) { + return (Support_Platforms.indexOf(platformName) >= 0) + } + + getOauthConfig(appConfig, platformName) { + let treePath = OauthConfig[platformName] + let node = this.findNode(appConfig, treePath) + if (node && node.appid && node.appsecret) { + return { + appid: node.appid, + secret: node.appsecret + } + } + return null + } + + findNode(treeNode, arrayPath) { + let node = treeNode + for (let treePath of arrayPath) { + for (let name of treePath) { + const currentNode = node[name] + if (currentNode) { + node = currentNode + } else { + node = null + break + } + } + if (node === null) { + node = treeNode + } else { + break + } + } + return node + } +} + + +module.exports = { + AppConfig }; \ No newline at end of file diff --git a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/consts.js b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/consts.js index d89a5c1..4c666e9 100644 --- a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/consts.js +++ b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/consts.js @@ -1,30 +1,30 @@ -'use strict'; - -const TAG = "UNI_OPEN_BRIDGE" - -const HTTP_STATUS = { - SUCCESS: 200 -} - -const ProviderType = { - WEIXIN_MP: 'weixin-mp', - WEIXIN_H5: 'weixin-h5', - WEIXIN_APP: 'weixin-app', - WEIXIN_WEB: 'weixin-web', - QQ_MP: 'qq-mp', - QQ_APP: 'qq-app' -} - -// old -const PlatformType = ProviderType - -const ErrorCodeType = { - SYSTEM_ERROR: TAG + "_SYSTEM_ERROR" -} - -module.exports = { - HTTP_STATUS, - ProviderType, - PlatformType, - ErrorCodeType +'use strict'; + +const TAG = "UNI_OPEN_BRIDGE" + +const HTTP_STATUS = { + SUCCESS: 200 +} + +const ProviderType = { + WEIXIN_MP: 'weixin-mp', + WEIXIN_H5: 'weixin-h5', + WEIXIN_APP: 'weixin-app', + WEIXIN_WEB: 'weixin-web', + QQ_MP: 'qq-mp', + QQ_APP: 'qq-app' +} + +// old +const PlatformType = ProviderType + +const ErrorCodeType = { + SYSTEM_ERROR: TAG + "_SYSTEM_ERROR" +} + +module.exports = { + HTTP_STATUS, + ProviderType, + PlatformType, + ErrorCodeType } diff --git a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/index.js b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/index.js index a8dba4b..1b5a340 100644 --- a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/index.js +++ b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/index.js @@ -1,317 +1,317 @@ -'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 +'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 || (24 * 60 * 60) + } + } +} + +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 } diff --git a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/package.json b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/package.json index a017b49..e277061 100644 --- a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/package.json +++ b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/package.json @@ -1,15 +1,19 @@ { - "name": "uni-open-bridge-common", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "", - "license": "ISC", - "dependencies": { - "uni-config-center": "file:../../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center" - } + "name": "uni-open-bridge-common", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "uni-config-center": "file:..\/..\/..\/..\/..\/uni-config-center\/uniCloud\/cloudfunctions\/common\/uni-config-center" + }, + "origin-plugin-dev-name": "uni-open-bridge-common", + "origin-plugin-version": "1.2.1", + "plugin-dev-name": "uni-open-bridge-common", + "plugin-version": "1.2.1" } \ No newline at end of file diff --git a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/storage.js b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/storage.js index 61e2fb3..b1665cc 100644 --- a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/storage.js +++ b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/storage.js @@ -1,111 +1,116 @@ -'use strict'; - -const { - Validator -} = require('./validator.js') - -const { - CacheKeyCascade -} = require('./uni-cloud-cache.js') - -const { - BridgeError -} = require('./bridge-error.js') - -class Storage { - - constructor(type, keys) { - this._type = type || null - this._keys = keys || [] - } - - async get(key, fallback) { - this.validateKey(key) - const result = await this.create(key, fallback).get() - return result.value - } - - async set(key, value, expiresIn) { - this.validateKey(key) - this.validateValue(value) - const expires_in = this.getExpiresIn(expiresIn) - if (expires_in !== 0) { - await this.create(key).set(this.getValue(value), expires_in) - } - } - - async remove(key) { - this.validateKey(key) - await this.create(key).remove() - } - - // virtual - async update(key) { - this.validateKey(key) - } - - async ttl(key) { - this.validateKey(key) - // 后续考虑支持 - } - - async fallback(key) {} - - getKeyString(key) { - const keyArray = [Storage.Prefix] - this._keys.forEach((name) => { - keyArray.push(key[name]) - }) - keyArray.push(this._type) - return keyArray.join(':') - } - - getValue(value) { - return value - } - - getExpiresIn(value) { - if (value !== undefined) { - return value - } - return -1 - } - - validateKey(key) { - Validator.Key(this._keys, key) - } - - validateValue(value) { - Validator.Value(value) - } - - create(key, fallback) { - const keyString = this.getKeyString(key) - const options = { - layers: [{ - type: 'database', - key: keyString - }, { - type: 'redis', - key: keyString - }] - } - - const _this = this - return new CacheKeyCascade({ - ...options, - fallback: async function() { - if (fallback) { - return fallback(key) - } else if (_this.fallback) { - return _this.fallback(key) - } - } - }) - } -} -Storage.Prefix = "uni-id" - -module.exports = { - Storage +'use strict'; + +const { + Validator +} = require('./validator.js') + +const { + CacheKeyCascade +} = require('./uni-cloud-cache.js') + +const { + BridgeError +} = require('./bridge-error.js') + +class Storage { + + constructor(type, keys) { + this._type = type || null + this._keys = keys || [] + } + + async get(key, fallback) { + this.validateKey(key) + const result = await this.create(key, fallback).get() + return result.value + } + + async set(key, value, expiresIn) { + this.validateKey(key) + this.validateValue(value) + const expires_in = this.getExpiresIn(expiresIn) + if (expires_in !== 0) { + await this.create(key).set(this.getValue(value), expires_in) + } + } + + async remove(key) { + this.validateKey(key) + await this.create(key).remove() + } + + // virtual + async update(key) { + this.validateKey(key) + } + + async ttl(key) { + this.validateKey(key) + // 后续考虑支持 + } + + async fallback(key) { + return { + value: null, + duration: -1 + } + } + + getKeyString(key) { + const keyArray = [Storage.Prefix] + this._keys.forEach((name) => { + keyArray.push(key[name]) + }) + keyArray.push(this._type) + return keyArray.join(':') + } + + getValue(value) { + return value + } + + getExpiresIn(value) { + if (value !== undefined) { + return value + } + return -1 + } + + validateKey(key) { + Validator.Key(this._keys, key) + } + + validateValue(value) { + Validator.Value(value) + } + + create(key, fallback) { + const keyString = this.getKeyString(key) + const options = { + layers: [{ + type: 'database', + key: keyString + }, { + type: 'redis', + key: keyString + }] + } + + const _this = this + return new CacheKeyCascade({ + ...options, + fallback: async function() { + if (fallback) { + return fallback(key) + } else if (_this.fallback) { + return _this.fallback(key) + } + } + }) + } +} +Storage.Prefix = "uni-id" + +module.exports = { + Storage }; diff --git a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/uni-cloud-cache.js b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/uni-cloud-cache.js index bde572e..2e4286b 100644 --- a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/uni-cloud-cache.js +++ b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/uni-cloud-cache.js @@ -1,324 +1,324 @@ -const db = uniCloud.database() - -function getType(value) { - return Object.prototype.toString.call(value).slice(8, -1).toLowerCase() -} - -const validator = { - key: function(value) { - const err = new Error('Invalid key') - if (typeof value !== 'string') { - throw err - } - const valueTrim = value.trim() - if (!valueTrim || valueTrim !== value) { - throw err - } - }, - value: function(value) { - // 仅作简单校验 - const type = getType(value) - const validValueType = ['null', 'number', 'string', 'array', 'object'] - if (validValueType.indexOf(type) === -1) { - throw new Error('Invalid value type') - } - }, - duration: function(value) { - const err = new Error('Invalid duration') - if (value === undefined) { - return - } - if (typeof value !== 'number' || value === 0) { - throw err - } - } -} - -/** - * 入库时 expired 为过期时间对应的时间戳,永不过期用-1表示 - * 返回结果时 与redis对齐,-1表示永不过期,-2表示已过期或不存在 - */ -class DatabaseCache { - constructor({ - collection = 'opendb-open-data' - } = {}) { - this.type = 'db' - this.collection = db.collection(collection) - } - - _serializeValue(value) { - return value === undefined ? null : JSON.stringify(value) - } - - _deserializeValue(value) { - return value ? JSON.parse(value) : value - } - - async set(key, value, duration) { - validator.key(key) - validator.value(value) - validator.duration(duration) - value = this._serializeValue(value) - await this.collection.doc(key).set({ - value, - expired: duration && duration !== -1 ? Date.now() + (duration * 1000) : -1 - }) - } - - async _getWithDuration(key) { - const getKeyRes = await this.collection.doc(key).get() - const record = getKeyRes.data[0] - if (!record) { - return { - value: null, - duration: -2 - } - } - const value = this._deserializeValue(record.value) - const expired = record.expired - if (expired === -1) { - return { - value, - duration: -1 - } - } - const duration = expired - Date.now() - if (duration <= 0) { - await this.remove(key) - return { - value: null, - duration: -2 - } - } - return { - value, - duration: Math.floor(duration / 1000) - } - } - - async get(key, { - withDuration = true - } = {}) { - const result = await this._getWithDuration(key) - if (!withDuration) { - delete result.duration - } - return result - } - - async remove(key) { - await this.collection.doc(key).remove() - } -} - -class RedisCache { - constructor() { - this.type = 'redis' - this.redis = uniCloud.redis() - } - - _serializeValue(value) { - return value === undefined ? null : JSON.stringify(value) - } - - _deserializeValue(value) { - return value ? JSON.parse(value) : value - } - - async set(key, value, duration) { - validator.key(key) - validator.value(value) - validator.duration(duration) - value = this._serializeValue(value) - if (!duration || duration === -1) { - await this.redis.set(key, value) - } else { - await this.redis.set(key, value, 'EX', duration) - } - } - - async get(key, { - withDuration = false - } = {}) { - let value = await this.redis.get(key) - value = this._deserializeValue(value) - if (!withDuration) { - return { - value - } - } - const durationSecond = await this.redis.ttl(key) - let duration - switch (durationSecond) { - case -1: - duration = -1 - break - case -2: - duration = -2 - break - default: - duration = durationSecond - break - } - return { - value, - duration - } - } - - async remove(key) { - await this.redis.del(key) - } -} - -class Cache { - constructor({ - type, - collection - } = {}) { - if (type === 'database') { - return new DatabaseCache({ - collection - }) - } else if (type === 'redis') { - return new RedisCache() - } else { - throw new Error('Invalid cache type') - } - } -} - -class CacheKey { - constructor({ - type, - collection, - cache, - key, - fallback - } = {}) { - this.cache = cache || new Cache({ - type, - collection - }) - this.key = key - this.fallback = fallback - } - - async set(value, duration) { - await this.cache.set(this.key, value, duration) - } - - async setWithSync(value, duration, syncMethod) { - await Promise.all([ - this.set(this.key, value, duration), - syncMethod(value, duration) - ]) - } - - async get() { - let { - value, - duration - } = await this.cache.get(this.key) - if (value !== null && value !== undefined) { - return { - value, - duration - } - } - if (!this.fallback) { - return { - value: null, - duration: -2 - } - } - const fallbackResult = await this.fallback() - value = fallbackResult.value - duration = fallbackResult.duration - if (value !== null && duration !== undefined) { - await this.cache.set(this.key, value, duration) - } - return { - value, - duration - } - } - - async remove() { - await this.cache.remove(this.key) - } -} - -class CacheKeyCascade { - constructor({ - layers, // [{cache, type, collection, key}] 从低级到高级排序,[DbCacheKey, RedisCacheKey] - fallback - } = {}) { - this.layers = layers - this.cacheLayers = [] - let lastCacheKey - for (let i = 0; i < layers.length; i++) { - const { - type, - cache, - collection, - key - } = layers[i] - const lastCacheKeyTemp = lastCacheKey - try { - const currentCacheKey = new CacheKey({ - type, - collection, - cache, - key, - fallback: i === 0 ? fallback : function() { - return lastCacheKeyTemp.get() - } - }) - this.cacheLayers.push(currentCacheKey) - lastCacheKey = currentCacheKey - } catch (e) {} - } - this.highLevelCache = lastCacheKey - } - - async set(value, duration) { - return Promise.all( - this.cacheLayers.map(item => { - return item.set(value, duration) - }) - ) - } - - async setWithSync(value, duration, syncMethod) { - const setPromise = this.cacheLayers.map(item => { - return item.set(value, duration) - }) - return Promise.all( - [ - ...setPromise, - syncMethod(value, duration) - ] - ) - } - - async get() { - return this.highLevelCache.get() - } - - async remove() { - await Promise.all( - this.cacheLayers.map(cacheKeyItem => { - return cacheKeyItem.remove() - }) - ) - } -} - -module.exports = { - Cache, - DatabaseCache, - RedisCache, - CacheKey, - CacheKeyCascade +const db = uniCloud.database() + +function getType(value) { + return Object.prototype.toString.call(value).slice(8, -1).toLowerCase() +} + +const validator = { + key: function(value) { + const err = new Error('Invalid key') + if (typeof value !== 'string') { + throw err + } + const valueTrim = value.trim() + if (!valueTrim || valueTrim !== value) { + throw err + } + }, + value: function(value) { + // 仅作简单校验 + const type = getType(value) + const validValueType = ['null', 'number', 'string', 'array', 'object'] + if (validValueType.indexOf(type) === -1) { + throw new Error('Invalid value type') + } + }, + duration: function(value) { + const err = new Error('Invalid duration') + if (value === undefined) { + return + } + if (typeof value !== 'number' || value === 0) { + throw err + } + } +} + +/** + * 入库时 expired 为过期时间对应的时间戳,永不过期用-1表示 + * 返回结果时 与redis对齐,-1表示永不过期,-2表示已过期或不存在 + */ +class DatabaseCache { + constructor({ + collection = 'opendb-open-data' + } = {}) { + this.type = 'db' + this.collection = db.collection(collection) + } + + _serializeValue(value) { + return value === undefined ? null : JSON.stringify(value) + } + + _deserializeValue(value) { + return value ? JSON.parse(value) : value + } + + async set(key, value, duration) { + validator.key(key) + validator.value(value) + validator.duration(duration) + value = this._serializeValue(value) + await this.collection.doc(key).set({ + value, + expired: duration && duration !== -1 ? Date.now() + (duration * 1000) : -1 + }) + } + + async _getWithDuration(key) { + const getKeyRes = await this.collection.doc(key).get() + const record = getKeyRes.data[0] + if (!record) { + return { + value: null, + duration: -2 + } + } + const value = this._deserializeValue(record.value) + const expired = record.expired + if (expired === -1) { + return { + value, + duration: -1 + } + } + const duration = expired - Date.now() + if (duration <= 0) { + await this.remove(key) + return { + value: null, + duration: -2 + } + } + return { + value, + duration: Math.floor(duration / 1000) + } + } + + async get(key, { + withDuration = true + } = {}) { + const result = await this._getWithDuration(key) + if (!withDuration) { + delete result.duration + } + return result + } + + async remove(key) { + await this.collection.doc(key).remove() + } +} + +class RedisCache { + constructor() { + this.type = 'redis' + this.redis = uniCloud.redis() + } + + _serializeValue(value) { + return value === undefined ? null : JSON.stringify(value) + } + + _deserializeValue(value) { + return value ? JSON.parse(value) : value + } + + async set(key, value, duration) { + validator.key(key) + validator.value(value) + validator.duration(duration) + value = this._serializeValue(value) + if (!duration || duration === -1) { + await this.redis.set(key, value) + } else { + await this.redis.set(key, value, 'EX', duration) + } + } + + async get(key, { + withDuration = false + } = {}) { + let value = await this.redis.get(key) + value = this._deserializeValue(value) + if (!withDuration) { + return { + value + } + } + const durationSecond = await this.redis.ttl(key) + let duration + switch (durationSecond) { + case -1: + duration = -1 + break + case -2: + duration = -2 + break + default: + duration = durationSecond + break + } + return { + value, + duration + } + } + + async remove(key) { + await this.redis.del(key) + } +} + +class Cache { + constructor({ + type, + collection + } = {}) { + if (type === 'database') { + return new DatabaseCache({ + collection + }) + } else if (type === 'redis') { + return new RedisCache() + } else { + throw new Error('Invalid cache type') + } + } +} + +class CacheKey { + constructor({ + type, + collection, + cache, + key, + fallback + } = {}) { + this.cache = cache || new Cache({ + type, + collection + }) + this.key = key + this.fallback = fallback + } + + async set(value, duration) { + await this.cache.set(this.key, value, duration) + } + + async setWithSync(value, duration, syncMethod) { + await Promise.all([ + this.set(this.key, value, duration), + syncMethod(value, duration) + ]) + } + + async get() { + let { + value, + duration + } = await this.cache.get(this.key) + if (value !== null && value !== undefined) { + return { + value, + duration + } + } + if (!this.fallback) { + return { + value: null, + duration: -2 + } + } + const fallbackResult = await this.fallback() + value = fallbackResult.value + duration = fallbackResult.duration + if (value !== null && duration !== undefined) { + await this.cache.set(this.key, value, duration) + } + return { + value, + duration + } + } + + async remove() { + await this.cache.remove(this.key) + } +} + +class CacheKeyCascade { + constructor({ + layers, // [{cache, type, collection, key}] 从低级到高级排序,[DbCacheKey, RedisCacheKey] + fallback + } = {}) { + this.layers = layers + this.cacheLayers = [] + let lastCacheKey + for (let i = 0; i < layers.length; i++) { + const { + type, + cache, + collection, + key + } = layers[i] + const lastCacheKeyTemp = lastCacheKey + try { + const currentCacheKey = new CacheKey({ + type, + collection, + cache, + key, + fallback: i === 0 ? fallback : function() { + return lastCacheKeyTemp.get() + } + }) + this.cacheLayers.push(currentCacheKey) + lastCacheKey = currentCacheKey + } catch (e) {} + } + this.highLevelCache = lastCacheKey + } + + async set(value, duration) { + return Promise.all( + this.cacheLayers.map(item => { + return item.set(value, duration) + }) + ) + } + + async setWithSync(value, duration, syncMethod) { + const setPromise = this.cacheLayers.map(item => { + return item.set(value, duration) + }) + return Promise.all( + [ + ...setPromise, + syncMethod(value, duration) + ] + ) + } + + async get() { + return this.highLevelCache.get() + } + + async remove() { + await Promise.all( + this.cacheLayers.map(cacheKeyItem => { + return cacheKeyItem.remove() + }) + ) + } +} + +module.exports = { + Cache, + DatabaseCache, + RedisCache, + CacheKey, + CacheKeyCascade } diff --git a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/validator.js b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/validator.js index 231dc8b..47a455b 100644 --- a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/validator.js +++ b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/validator.js @@ -1,31 +1,31 @@ -const Validator = { - - Key(keyArray, parameters) { - for (let i = 0; i < keyArray.length; i++) { - const keyName = keyArray[i] - if (typeof parameters[keyName] !== 'string') { - Validator.ThrowNewError(`Invalid ${keyName}`) - } - if (parameters[keyName].length < 1) { - Validator.ThrowNewError(`Invalid ${keyName}`) - } - } - }, - - Value(value) { - if (value === undefined) { - Validator.ThrowNewError('Invalid Value') - } - if (typeof value !== 'object') { - Validator.ThrowNewError('Invalid Value Type') - } - }, - - ThrowNewError(message) { - throw new Error(message) - } -} - -module.exports = { - Validator +const Validator = { + + Key(keyArray, parameters) { + for (let i = 0; i < keyArray.length; i++) { + const keyName = keyArray[i] + if (typeof parameters[keyName] !== 'string') { + Validator.ThrowNewError(`Invalid ${keyName}`) + } + if (parameters[keyName].length < 1) { + Validator.ThrowNewError(`Invalid ${keyName}`) + } + } + }, + + Value(value) { + if (value === undefined) { + Validator.ThrowNewError('Invalid Value') + } + if (typeof value !== 'object') { + Validator.ThrowNewError('Invalid Value Type') + } + }, + + ThrowNewError(message) { + throw new Error(message) + } +} + +module.exports = { + Validator } diff --git a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/weixin-server.js b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/weixin-server.js index d45e906..ef476f1 100644 --- a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/weixin-server.js +++ b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/weixin-server.js @@ -1,203 +1,203 @@ -'use strict'; - -const crypto = require('crypto') - -const { - HTTP_STATUS -} = require('./consts.js') - -const { - BridgeError -} = require('./bridge-error.js') - -class WeixinServer { - - constructor(options = {}) { - this._appid = options.appid - this._secret = options.secret - } - - getAccessToken() { - return uniCloud.httpclient.request(WeixinServer.AccessToken_Url, { - dataType: 'json', - method: 'POST', - contentType: 'json', - data: { - appid: this._appid, - secret: this._secret, - grant_type: "client_credential" - } - }) - } - - // 使用客户端获取的 code 从微信服务器换取 openid,code 仅可使用一次 - codeToSession(code) { - return uniCloud.httpclient.request(WeixinServer.Code2Session_Url, { - dataType: 'json', - data: { - appid: this._appid, - secret: this._secret, - js_code: code, - grant_type: 'authorization_code' - } - }) - } - - getUserEncryptKey({ - access_token, - openid, - session_key - }) { - console.log(access_token, openid, session_key); - const signature = crypto.createHmac('sha256', session_key).update('').digest('hex') - return uniCloud.httpclient.request(WeixinServer.User_Encrypt_Key_Url, { - dataType: 'json', - method: 'POST', - dataAsQueryString: true, - data: { - access_token, - openid: openid, - signature: signature, - sig_method: 'hmac_sha256' - } - }) - } - - getH5AccessToken() { - return uniCloud.httpclient.request(WeixinServer.AccessToken_H5_Url, { - dataType: 'json', - method: 'GET', - data: { - appid: this._appid, - secret: this._secret, - grant_type: "client_credential" - } - }) - } - - getH5Ticket(access_token) { - return uniCloud.httpclient.request(WeixinServer.Ticket_Url, { - dataType: 'json', - dataAsQueryString: true, - method: 'POST', - data: { - access_token - } - }) - } - - getH5AccessTokenForEip() { - return uniCloud.httpProxyForEip.postForm(WeixinServer.AccessToken_H5_Url, { - appid: this._appid, - secret: this._secret, - grant_type: "client_credential" - }, { - dataType: 'json' - }) - } - - getH5TicketForEip(access_token) { - return uniCloud.httpProxyForEip.postForm(WeixinServer.Ticket_Url, { - access_token - }, { - dataType: 'json', - dataAsQueryString: true - }) - } -} - -WeixinServer.AccessToken_Url = 'https://api.weixin.qq.com/cgi-bin/stable_token' -WeixinServer.Code2Session_Url = 'https://api.weixin.qq.com/sns/jscode2session' -WeixinServer.User_Encrypt_Key_Url = 'https://api.weixin.qq.com/wxa/business/getuserencryptkey' -WeixinServer.AccessToken_H5_Url = 'https://api.weixin.qq.com/cgi-bin/token' -WeixinServer.Ticket_Url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi' - -WeixinServer.GetMPAccessToken = function(options) { - return new WeixinServer(options).getAccessToken() -} - -WeixinServer.GetCodeToSession = function(options) { - return new WeixinServer(options).codeToSession(options.code) -} - -WeixinServer.GetUserEncryptKey = function(options) { - return new WeixinServer(options).getUserEncryptKey(options) -} - -WeixinServer.GetH5AccessToken = function(options) { - return new WeixinServer(options).getH5AccessToken() -} - -WeixinServer.GetH5Ticket = function(options) { - return new WeixinServer(options).getH5Ticket(options.access_token) -} - -//////////////////////////////////////////////////////////////// - -function isAliyun() { - return (uniCloud.getCloudInfos()[0].provider === 'aliyun') -} - -WeixinServer.GetResponseData = function(response) { - console.log("WeixinServer::response", response) - - if (!(response.status === HTTP_STATUS.SUCCESS || response.statusCodeValue === HTTP_STATUS.SUCCESS)) { - throw new BridgeError(response.status || response.statusCodeValue, response.status || response.statusCodeValue) - } - - const responseData = response.data || response.body - - if (responseData.errcode !== undefined && responseData.errcode !== 0) { - throw new BridgeError(responseData.errcode, responseData.errmsg) - } - - return responseData -} - -WeixinServer.GetMPAccessTokenData = async function(options) { - const response = await new WeixinServer(options).getAccessToken() - return WeixinServer.GetResponseData(response) -} - -WeixinServer.GetCodeToSessionData = async function(options) { - const response = await new WeixinServer(options).codeToSession(options.code) - return WeixinServer.GetResponseData(response) -} - -WeixinServer.GetUserEncryptKeyData = async function(options) { - const response = await new WeixinServer(options).getUserEncryptKey(options) - return WeixinServer.GetResponseData(response) -} - -WeixinServer.GetH5AccessTokenData = async function(options) { - const ws = new WeixinServer(options) - let response - if (isAliyun()) { - response = await ws.getH5AccessTokenForEip() - if (typeof response === 'string') { - response = JSON.parse(response) - } - } else { - response = await ws.getH5AccessToken() - } - return WeixinServer.GetResponseData(response) -} - -WeixinServer.GetH5TicketData = async function(options) { - const ws = new WeixinServer(options) - let response - if (isAliyun()) { - response = await ws.getH5TicketForEip(options.access_token) - if (typeof response === 'string') { - response = JSON.parse(response) - } - } else { - response = await ws.getH5Ticket(options.access_token) - } - return WeixinServer.GetResponseData(response) -} - - -module.exports = { - WeixinServer +'use strict'; + +const crypto = require('crypto') + +const { + HTTP_STATUS +} = require('./consts.js') + +const { + BridgeError +} = require('./bridge-error.js') + +class WeixinServer { + + constructor(options = {}) { + this._appid = options.appid + this._secret = options.secret + } + + getAccessToken() { + return uniCloud.httpclient.request(WeixinServer.AccessToken_Url, { + dataType: 'json', + method: 'POST', + contentType: 'json', + data: { + appid: this._appid, + secret: this._secret, + grant_type: "client_credential" + } + }) + } + + // 使用客户端获取的 code 从微信服务器换取 openid,code 仅可使用一次 + codeToSession(code) { + return uniCloud.httpclient.request(WeixinServer.Code2Session_Url, { + dataType: 'json', + data: { + appid: this._appid, + secret: this._secret, + js_code: code, + grant_type: 'authorization_code' + } + }) + } + + getUserEncryptKey({ + access_token, + openid, + session_key + }) { + console.log(access_token, openid, session_key); + const signature = crypto.createHmac('sha256', session_key).update('').digest('hex') + return uniCloud.httpclient.request(WeixinServer.User_Encrypt_Key_Url, { + dataType: 'json', + method: 'POST', + dataAsQueryString: true, + data: { + access_token, + openid: openid, + signature: signature, + sig_method: 'hmac_sha256' + } + }) + } + + getH5AccessToken() { + return uniCloud.httpclient.request(WeixinServer.AccessToken_H5_Url, { + dataType: 'json', + method: 'GET', + data: { + appid: this._appid, + secret: this._secret, + grant_type: "client_credential" + } + }) + } + + getH5Ticket(access_token) { + return uniCloud.httpclient.request(WeixinServer.Ticket_Url, { + dataType: 'json', + dataAsQueryString: true, + method: 'POST', + data: { + access_token + } + }) + } + + getH5AccessTokenForEip() { + return uniCloud.httpProxyForEip.postForm(WeixinServer.AccessToken_H5_Url, { + appid: this._appid, + secret: this._secret, + grant_type: "client_credential" + }, { + dataType: 'json' + }) + } + + getH5TicketForEip(access_token) { + return uniCloud.httpProxyForEip.postForm(WeixinServer.Ticket_Url, { + access_token + }, { + dataType: 'json', + dataAsQueryString: true + }) + } +} + +WeixinServer.AccessToken_Url = 'https://api.weixin.qq.com/cgi-bin/stable_token' +WeixinServer.Code2Session_Url = 'https://api.weixin.qq.com/sns/jscode2session' +WeixinServer.User_Encrypt_Key_Url = 'https://api.weixin.qq.com/wxa/business/getuserencryptkey' +WeixinServer.AccessToken_H5_Url = 'https://api.weixin.qq.com/cgi-bin/token' +WeixinServer.Ticket_Url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi' + +WeixinServer.GetMPAccessToken = function(options) { + return new WeixinServer(options).getAccessToken() +} + +WeixinServer.GetCodeToSession = function(options) { + return new WeixinServer(options).codeToSession(options.code) +} + +WeixinServer.GetUserEncryptKey = function(options) { + return new WeixinServer(options).getUserEncryptKey(options) +} + +WeixinServer.GetH5AccessToken = function(options) { + return new WeixinServer(options).getH5AccessToken() +} + +WeixinServer.GetH5Ticket = function(options) { + return new WeixinServer(options).getH5Ticket(options.access_token) +} + +//////////////////////////////////////////////////////////////// + +function isAliyun() { + return (uniCloud.getCloudInfos()[0].provider === 'aliyun') +} + +WeixinServer.GetResponseData = function(response) { + console.log("WeixinServer::response", response) + + if (!(response.status === HTTP_STATUS.SUCCESS || response.statusCodeValue === HTTP_STATUS.SUCCESS)) { + throw new BridgeError(response.status || response.statusCodeValue, response.status || response.statusCodeValue) + } + + const responseData = response.data || response.body + + if (responseData.errcode !== undefined && responseData.errcode !== 0) { + throw new BridgeError(responseData.errcode, responseData.errmsg) + } + + return responseData +} + +WeixinServer.GetMPAccessTokenData = async function(options) { + const response = await new WeixinServer(options).getAccessToken() + return WeixinServer.GetResponseData(response) +} + +WeixinServer.GetCodeToSessionData = async function(options) { + const response = await new WeixinServer(options).codeToSession(options.code) + return WeixinServer.GetResponseData(response) +} + +WeixinServer.GetUserEncryptKeyData = async function(options) { + const response = await new WeixinServer(options).getUserEncryptKey(options) + return WeixinServer.GetResponseData(response) +} + +WeixinServer.GetH5AccessTokenData = async function(options) { + const ws = new WeixinServer(options) + let response + if (isAliyun()) { + response = await ws.getH5AccessTokenForEip() + if (typeof response === 'string') { + response = JSON.parse(response) + } + } else { + response = await ws.getH5AccessToken() + } + return WeixinServer.GetResponseData(response) +} + +WeixinServer.GetH5TicketData = async function(options) { + const ws = new WeixinServer(options) + let response + if (isAliyun()) { + response = await ws.getH5TicketForEip(options.access_token) + if (typeof response === 'string') { + response = JSON.parse(response) + } + } else { + response = await ws.getH5Ticket(options.access_token) + } + return WeixinServer.GetResponseData(response) +} + + +module.exports = { + WeixinServer } diff --git a/uni_modules/uni-open-bridge-common/uniCloud/database/opendb-open-data.schema.json b/uni_modules/uni-open-bridge-common/uniCloud/database/opendb-open-data.schema.json index e7774df..bc25098 100644 --- a/uni_modules/uni-open-bridge-common/uniCloud/database/opendb-open-data.schema.json +++ b/uni_modules/uni-open-bridge-common/uniCloud/database/opendb-open-data.schema.json @@ -1,19 +1,19 @@ -// 文档教程: https://uniapp.dcloud.net.cn/uniCloud/schema -{ - "bsonType": "object", - "required": ["_id", "value"], - "properties": { - "_id": { - "bsonType": "string", - "description": "key,格式:uni-id:[provider]:[appid]:[openid]:[access-token|user-access-token|session-key|encrypt-key-version|ticket]" - }, - "value": { - "bsonType": "object", - "description": "字段_id对应的值" - }, - "expired": { - "bsonType": "date", - "description": "过期时间" - } - } +// 文档教程: https://uniapp.dcloud.net.cn/uniCloud/schema +{ + "bsonType": "object", + "required": ["_id", "value"], + "properties": { + "_id": { + "bsonType": "string", + "description": "key,格式:uni-id:[provider]:[appid]:[openid]:[access-token|user-access-token|session-key|encrypt-key-version|ticket]" + }, + "value": { + "bsonType": "object", + "description": "字段_id对应的值" + }, + "expired": { + "bsonType": "date", + "description": "过期时间" + } + } } -- GitLab