提交 25fedfb9 编写于 作者: Anne_LXM's avatar Anne_LXM

更新 依赖的uni-id-pages的版本为1.1.22

上级 826ff3a2
## 1.1.22(2024-09-13)
- 注册登录时去除字符串两端的空白字符
- 删除static目录下重复资源
## 1.1.21(2024-08-02)
- uni-id-co 修复联登更新用户信息接口存在手机号或者邮箱时没有设置认证状态
## 1.1.20(2024-04-28)
......
......@@ -2,7 +2,7 @@
<view>
<uni-captcha :focus="focusCaptchaInput" ref="captcha" scene="send-sms-code" v-model="captcha" />
<view class="box">
<uni-easyinput :focus="focusSmsCodeInput" @blur="focusSmsCodeInput = false" type="number" class="input-box" :inputBorder="false" v-model="modelValue" maxlength="6" :clearable="false"
<uni-easyinput :focus="focusSmsCodeInput" @blur="focusSmsCodeInput = false" type="number" class="input-box" :inputBorder="false" v-model="modelValue" maxlength="6" :clearable="false" trim="both"
placeholder="请输入短信验证码">
</uni-easyinput>
<view class="short-code-btn" hover-class="hover" @click="start">
......
{
"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": {
......
......@@ -21,7 +21,7 @@
<text class="tip">未注册的账号验证通过后将自动注册</text>
<view class="phone-box">
<view @click="chooseArea" class="area">+86</view>
<uni-easyinput :focus="focusPhone" @blur="focusPhone = false" class="input-box" type="number"
<uni-easyinput trim="both" :focus="focusPhone" @blur="focusPhone = false" class="input-box" type="number"
:inputBorder="false" v-model="phone" maxlength="11" placeholder="请输入手机号" />
</view>
<uni-id-pages-agreements scope="register" ref="agreements"></uni-id-pages-agreements>
......
......@@ -9,11 +9,11 @@
<uni-forms>
<uni-forms-item name="username">
<uni-easyinput :focus="focusUsername" @blur="focusUsername = false" class="input-box"
:inputBorder="false" v-model="username" placeholder="请输入手机号/用户名/邮箱" />
:inputBorder="false" v-model="username" placeholder="请输入手机号/用户名/邮箱" trim="all" />
</uni-forms-item>
<uni-forms-item name="password">
<uni-easyinput :focus="focusPassword" @blur="focusPassword = false" class="input-box" clearable
type="password" :inputBorder="false" v-model="password" placeholder="请输入密码" />
type="password" :inputBorder="false" v-model="password" placeholder="请输入密码" trim="all" />
</uni-forms-item>
</uni-forms>
<uni-captcha v-if="needCaptcha" focus ref="captcha" scene="login-by-pwd" v-model="captcha" />
......
......@@ -10,7 +10,7 @@
</match-media>
<uni-forms ref="form" :value="formData" err-show-type="toast">
<uni-forms-item name="email">
<uni-easyinput :focus="focusEmail" @blur="focusEmail = false" class="input-box" :disabled="lock" :inputBorder="false"
<uni-easyinput :focus="focusEmail" @blur="focusEmail = false" class="input-box" :disabled="lock" :inputBorder="false" trim="both"
v-model="formData.email" placeholder="请输入邮箱">
</uni-easyinput>
</uni-forms-item>
......@@ -19,11 +19,11 @@
</uni-id-pages-email-form>
</uni-forms-item>
<uni-forms-item name="password">
<uni-easyinput :focus="focusPassword" @blur="focusPassword = false" class="input-box" type="password" :inputBorder="false" v-model="formData.password"
<uni-easyinput :focus="focusPassword" @blur="focusPassword = false" class="input-box" type="password" :inputBorder="false" v-model="formData.password" trim="both"
placeholder="请输入新密码"></uni-easyinput>
</uni-forms-item>
<uni-forms-item name="password2">
<uni-easyinput :focus="focusPassword2" @blur="focusPassword2 = false" class="input-box" type="password" :inputBorder="false" v-model="formData.password2"
<uni-easyinput :focus="focusPassword2" @blur="focusPassword2 = false" class="input-box" type="password" :inputBorder="false" v-model="formData.password2" trim="both"
placeholder="请再次输入新密码"></uni-easyinput>
</uni-forms-item>
<button class="uni-btn send-btn-box" type="primary" @click="submit">提交</button>
......
......@@ -10,7 +10,7 @@
</match-media>
<uni-forms ref="form" :value="formData" err-show-type="toast">
<uni-forms-item name="phone">
<uni-easyinput :focus="focusPhone" @blur="focusPhone = false" class="input-box" :disabled="lock" type="number" :inputBorder="false"
<uni-easyinput :focus="focusPhone" @blur="focusPhone = false" class="input-box" :disabled="lock" type="number" :inputBorder="false" trim="both"
v-model="formData.phone" maxlength="11" placeholder="请输入手机号">
</uni-easyinput>
</uni-forms-item>
......@@ -19,11 +19,11 @@
</uni-id-pages-sms-form>
</uni-forms-item>
<uni-forms-item name="password">
<uni-easyinput :focus="focusPassword" @blur="focusPassword = false" class="input-box" type="password" :inputBorder="false" v-model="formData.password"
<uni-easyinput :focus="focusPassword" @blur="focusPassword = false" class="input-box" type="password" :inputBorder="false" v-model="formData.password" trim="both"
placeholder="请输入新密码"></uni-easyinput>
</uni-forms-item>
<uni-forms-item name="password2">
<uni-easyinput :focus="focusPassword2" @blur="focusPassword2 = false" class="input-box" type="password" :inputBorder="false" v-model="formData.password2"
<uni-easyinput :focus="focusPassword2" @blur="focusPassword2 = false" class="input-box" type="password" :inputBorder="false" v-model="formData.password2" trim="both"
placeholder="请再次输入新密码"></uni-easyinput>
</uni-forms-item>
<button class="uni-btn send-btn-box" type="primary" @click="submit">提交</button>
......
......@@ -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"
}
\ No newline at end of file
## 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)
......
{
"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": {
......
# 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)
'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
}
'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
'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
}
'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
}
{
"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
'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
};
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
}
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
}
'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
}
// 文档教程: 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": "过期时间"
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册