BF-202210271038\Administrator 2 lat temu
rodzic
commit
29db745026
28 zmienionych plików z 1646 dodań i 23 usunięć
  1. 2 2
      .env.dev.js
  2. 2 2
      .env.prod.js
  3. 4 4
      api/login.js
  4. 3 3
      manifest.json
  5. 57 7
      pages/login/localPhoneLogin.vue
  6. 13 2
      pages/login/otherPhoneLogin.vue
  7. 29 3
      service/tools.js
  8. 23 0
      uniCloud-aliyun/cloudfunctions/getPhoneNumber/index.js
  9. 8 0
      uniCloud-aliyun/cloudfunctions/getPhoneNumber/package.json
  10. 6 0
      uni_modules/uni-config-center/changelog.md
  11. 81 0
      uni_modules/uni-config-center/package.json
  12. 93 0
      uni_modules/uni-config-center/readme.md
  13. 0 0
      uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/index.js
  14. 9 0
      uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/package.json
  15. 32 0
      uni_modules/uni-id-common/changelog.md
  16. 84 0
      uni_modules/uni-id-common/package.json
  17. 3 0
      uni_modules/uni-id-common/readme.md
  18. 0 0
      uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/index.js
  19. 16 0
      uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/package.json
  20. 26 0
      uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/bridge-error.js
  21. 124 0
      uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/config.js
  22. 30 0
      uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/consts.js
  23. 317 0
      uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/index.js
  24. 15 0
      uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/package.json
  25. 111 0
      uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/storage.js
  26. 324 0
      uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/uni-cloud-cache.js
  27. 31 0
      uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/validator.js
  28. 203 0
      uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/weixin-server.js

+ 2 - 2
.env.dev.js

@@ -1,6 +1,6 @@
 const config = {
-	baseUrl: 'testapi.jhcs888.com',
-	socketUrl: 'testapi.jhcs888.com',
+	baseUrl: 'www.icoco.tech:9999/admin',
+	socketUrl: 'www.icoco.tech:9999/admin',
     appName:'开发环境'
 }
 module.exports = config;

+ 2 - 2
.env.prod.js

@@ -1,6 +1,6 @@
 const config = {
-    baseUrl: 'testapi.jhcs888.com',
-    socketUrl: 'testapi.jhcs888.com',
+    baseUrl: 'www.icoco.tech:9999/admin',
+    socketUrl: 'www.icoco.tech:9999/admin',
     appName:'正式环境'
 }
 module.exports = config;

+ 4 - 4
api/login.js

@@ -1,6 +1,6 @@
-import {request} from '../service/ajax.js'
+import {request} from '@/service/ajax'
 
-const newsUrl = '/api/user/'
+const newsUrl = '/utility/'
 // 登陆
-export const login = (data) => request(newsUrl + 'login', 'post', { ...data },false)
-export const resetPwd = (data) => request(newsUrl + 'resetpwd', 'post', { ...data },false)
+export const login = (data) => request(newsUrl + 'one_click_login', 'post', { ...data },false)
+export const forgetPassword = (data) => request(newsUrl + 'forget_password', 'post', { ...data },false)

+ 3 - 3
manifest.json

@@ -129,12 +129,12 @@
         "devServer" : {
             "https" : false,
             "proxy" : {
-                "/api" : {
-                    "target" : "lsadmin.test.cc",
+                "/utility" : {
+                    "target" : "http://www.icoco.tech:9999/admin",
                     "changeOrigin" : true,
                     "secure" : false,
                     "pathRewrite" : {
-                        "^/api" : "api"
+                        "^/utility" : "utility"
                     }
                 }
             }

+ 57 - 7
pages/login/localPhoneLogin.vue

@@ -9,7 +9,7 @@
         </view>
         <view class="local-txt sys-color-gray-9">本机号码登录</view>
         <view class="local-phone sys-color-black sys-weight-400">188****4188</view>
-        <view class="login-but sys-color-white sys-background-black" @click="login">一键登录</view>
+        <view class="login-but sys-color-white sys-background-black" >一键登录</view>
         <view @click="goToOther" class="other-phone sys-color-gray-6">其他手机号登录</view>
       </view>
       <view class="login-bottom">
@@ -25,6 +25,7 @@ import EnNav from "@/components/en-utils/en-nav/en-nav";
 import LoginAgreement from "@/pages/login/model/loginAgreement";
 import OtherLogin from "@/pages/login/model/otherLogin";
 import tools from "@/service/tools";
+import {login} from "@/api/login";
 export default {
   name:'localPhoneLogin',
   components: {OtherLogin, LoginAgreement, EnNav},
@@ -106,7 +107,26 @@ export default {
 
     },
     cloudGetPhoneNum(authResult){
+      console.log('-------------')
       tools.showLoading()
+      // uniCloud.getPhoneNumber({
+      //   provider: 'univerify',
+      //   appid: '__UNI__1B420CB', // 客户端callFunction时携带的AppId信息
+      //   apiKey: 'f904a759f52a6981744ed39813894cfc', // 在开发者中心开通服务并获取apiKey
+      //   apiSecret: 'ae475f1ed69608e527047f83c380303a', // 在开发者中心开通服务并获取apiSecret
+      //   access_token: authResult.access_token,
+      //   openid: authResult.openid
+      // }).then(res => {
+      //   tools.hideLoading()
+      //   console.log(res)
+      // }).catch(err=>{
+      //   tools.hideLoading()
+      //   tools.error('手机号码获取失败')
+      //   console.log(err)
+      //   setTimeout(()=>{
+      //     // this.goToOther()
+      //   },1500)
+      // })
       uniCloud.callFunction({
         name: 'getPhoneNumber', // 你的云函数名称
         data: {
@@ -116,25 +136,55 @@ export default {
       }).then(res => {
         tools.hideLoading()
         console.log(res)
+        if(res.result.data.phoneNumber!==undefined){
+          uni.setStorageSync('mobile', res.result.data.phoneNumber)
+          this.oneClickLogin(res.result.data.phoneNumber)
+        }else {
+          tools.error('手机号码获取失败')
+          setTimeout(()=>{
+            this.goToOther()
+          },1500)
+        }
       }).catch(err=>{
         tools.hideLoading()
        tools.error('手机号码获取失败')
+        console.log(err)
         setTimeout(()=>{
             this.goToOther()
         },1500)
       })
     },
+    oneClickLogin(mobile){
+      login({'mobile':mobile}).then((res)=>{
+        console.log(res)
+        if(res.code===0){
+            tools.setLoginData(res.data)
+            setTimeout(()=>{
+              uni.switchTab({
+                'url':'/pages/index/index'
+              })
+            },1500)
+        }else{
+
+            uni.navigateTo({
+              'url':'/pages/perfect/sexAndAge'
+            })
+        }
+      }).catch((e)=>{
+        console.log(e)
+      })
+    },
     setNavHeight(navHeight){
       console.log('navHeight:'+navHeight)
       this.navHeight=navHeight
     },
-    login(){
-      uni.navigateTo({
-        'url':'/pages/perfect/sexAndAge'
-      })
-    },
+    // login(){
+    //   uni.navigateTo({
+    //     'url':'/pages/perfect/sexAndAge'
+    //   })
+    // },
     goToOther(){
-      uni.redirectTo({
+      uni.navigateTo({
         'url':'/pages/login/otherPhoneLogin'
       })
     }

+ 13 - 2
pages/login/otherPhoneLogin.vue

@@ -34,6 +34,7 @@
 import EnNav from "@/components/en-utils/en-nav/en-nav";
 import tools from "@/service/tools";
 import OtherLogin from "@/pages/login/model/otherLogin";
+import {forgetPassword} from "@/api/login";
 export default {
   name:'otherPhoneLogin',
   components: {OtherLogin, EnNav},
@@ -71,9 +72,19 @@ export default {
         tools.vibrate()
         return false
       }
-      uni.switchTab({
-        'url':'/pages/index/index'
+      forgetPassword({'mobile':this.phone,'code':this.code}).then((res)=>{
+        if(res.code===0){
+          tools.success('登陆成功')
+          setTimeout(()=>{
+            uni.switchTab({
+              'url':'/pages/index/index'
+            })
+          },1500)
+        }else {
+          tools.error(res.msg)
+        }
       })
+
     },
     setShake(type){
       if(type===1){

+ 29 - 3
service/tools.js

@@ -279,7 +279,7 @@ tools.leftClick = function () {
 }
 
 /**
- * 自定义 获取指定日期到当前日期的 所有年 or 年月 
+ * 自定义 获取指定日期到当前日期的 所有年 or 年月
  */
 tools.getCustomTimeList = (start,end,type)=>{
 	let timeList = [];
@@ -297,7 +297,7 @@ tools.getCustomTimeList = (start,end,type)=>{
 		if(type === 'y-m'){
 			if (month === 0) {
 				str = (yers - 1) + "-" + 12;
-			} else { 
+			} else {
 				str = yers + "-" + (month < 10 ? ("0" + month) : month);
 			}
 			timeList.push(str);
@@ -305,7 +305,7 @@ tools.getCustomTimeList = (start,end,type)=>{
 		}else if(type === 'y'){
 			if (month === 0) {
 				str = (yers - 1)
-			} else { 
+			} else {
 				str = yers
 			}
 			timeList.push(str);
@@ -330,5 +330,31 @@ tools.getDateYM = ()=>{
 }
 
 
+/**
+ * 记录用户登录信息
+ * @param data
+ * @param type
+ */
+tools.setLoginData = function (data) {
+    uni.setStorageSync('token', data.accessToken)
+    uni.setStorageSync('tokenType', data.tokenType)
+    uni.setStorageSync('refreshToken', data.refreshToken)
+    uni.setStorageSync('mobile', data.mobile)
+    tools.success('登陆成功')
+    // setTimeout(() => {
+    //     if (data.status * 1 === 0) {
+    //         //审核状态跳转至待审核页面
+    //         uni.reLaunch({
+    //             url: '/pages/login/module/await-audit'
+    //         });
+    //     } else {
+    //         uni.reLaunch({
+    //             url: '/pages/index/home'
+    //         });
+    //     }
+    // }, 1500)
+
+}
+
 
 export default tools

+ 23 - 0
uniCloud-aliyun/cloudfunctions/getPhoneNumber/index.js

@@ -0,0 +1,23 @@
+'use strict';
+// const crypto = require('crypto')
+exports.main = async (event, context) => {
+	//event为客户端上传的参数
+	const res = await uniCloud.getPhoneNumber({
+		provider: 'univerify',
+		appid: '__UNI__1B420CB', // 客户端callFunction时携带的AppId信息
+		apiKey: 'f904a759f52a6981744ed39813894cfc', // 在开发者中心开通服务并获取apiKey
+		apiSecret: 'ae475f1ed69608e527047f83c380303a', // 在开发者中心开通服务并获取apiSecret
+		access_token: event.access_token,
+		openid: event.openid
+	})
+
+	// 执行用户信息入库等操作,正常情况下不要把完整手机号返回给前端
+	// 如果数据库在uniCloud上,可以直接入库
+	// 如果数据库不在uniCloud上,可以通过 uniCloud.httpclient API,将手机号通过http方式传递给其他服务器的接口,详见:https://uniapp.dcloud.net.cn/uniCloud/cf-functions?id=httpclient
+	//返回数据给客户端
+	return {
+		code: 0,
+		message: '获取手机号成功',
+		data:res
+	}
+}

+ 8 - 0
uniCloud-aliyun/cloudfunctions/getPhoneNumber/package.json

@@ -0,0 +1,8 @@
+{
+  "name": "getPhoneNumber",
+  "dependencies": {},
+  "extensions": {
+    "uni-cloud-jql": {},
+    "uni-cloud-verify": {}
+  }
+}

+ 6 - 0
uni_modules/uni-config-center/changelog.md

@@ -0,0 +1,6 @@
+## 0.0.3(2022-11-11)
+- 修复 config 方法获取根节点为数组格式配置时错误的转化为了对象的Bug
+## 0.0.2(2021-04-16)
+- 修改插件package信息
+## 0.0.1(2021-03-15)
+- 初始化项目

+ 81 - 0
uni_modules/uni-config-center/package.json

@@ -0,0 +1,81 @@
+{
+  "id": "uni-config-center",
+  "displayName": "uni-config-center",
+  "version": "0.0.3",
+  "description": "uniCloud 配置中心",
+  "keywords": [
+    "配置",
+    "配置中心"
+],
+  "repository": "",
+  "engines": {
+    "HBuilderX": "^3.1.0"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "",
+    "type": "unicloud-template-function"
+  },
+  "directories": {
+    "example": "../../../scripts/dist"
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "u",
+          "app-nvue": "u"
+        },
+        "H5-mobile": {
+          "Safari": "u",
+          "Android Browser": "u",
+          "微信浏览器(Android)": "u",
+          "QQ浏览器(Android)": "u"
+        },
+        "H5-pc": {
+          "Chrome": "u",
+          "IE": "u",
+          "Edge": "u",
+          "Firefox": "u",
+          "Safari": "u"
+        },
+        "小程序": {
+          "微信": "u",
+          "阿里": "u",
+          "百度": "u",
+          "字节跳动": "u",
+          "QQ": "u"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "u"
+        }
+      }
+    }
+  }
+}

+ 93 - 0
uni_modules/uni-config-center/readme.md

@@ -0,0 +1,93 @@
+# 为什么使用uni-config-center
+
+实际开发中很多插件需要配置文件才可以正常运行,如果每个插件都单独进行配置的话就会产生下面这样的目录结构
+
+```bash
+cloudfunctions
+└─────common 公共模块
+        ├─plugin-a // 插件A对应的目录
+        │  ├─index.js
+        │  ├─config.json // plugin-a对应的配置文件
+        │  └─other-file.cert  // plugin-a依赖的其他文件
+        └─plugin-b // plugin-b对应的目录
+           ├─index.js
+           └─config.json // plugin-b对应的配置文件
+```
+
+假设插件作者要发布一个项目模板,里面使用了很多需要配置的插件,无论是作者发布还是用户使用都是一个大麻烦。
+
+uni-config-center就是用了统一管理这些配置文件的,使用uni-config-center后的目录结构如下
+
+```bash
+cloudfunctions
+└─────common 公共模块
+        ├─plugin-a // 插件A对应的目录
+        │  └─index.js
+        ├─plugin-b // plugin-b对应的目录
+        │  └─index.js
+        └─uni-config-center
+           ├─index.js // config-center入口文件
+           ├─plugin-a
+           │  ├─config.json  // plugin-a对应的配置文件
+           │  └─other-file.cert  // plugin-a依赖的其他文件
+           └─plugin-b
+              └─config.json  // plugin-b对应的配置文件
+```
+
+使用uni-config-center后的优势
+
+- 配置文件统一管理,分离插件主体和配置信息,更新插件更方便
+- 支持对config.json设置schema,插件使用者在HBuilderX内编写config.json文件时会有更好的提示(后续HBuilderX会提供支持)
+
+# 用法
+
+在要使用uni-config-center的公共模块或云函数内引入uni-config-center依赖,请参考:[使用公共模块](https://uniapp.dcloud.net.cn/uniCloud/cf-common)
+
+```js
+const createConfig = require('uni-config-center')
+
+const uniIdConfig = createConfig({
+    pluginId: 'uni-id', // 插件id
+    defaultConfig: { // 默认配置
+        tokenExpiresIn: 7200,
+        tokenExpiresThreshold: 600,
+    },
+    customMerge: function(defaultConfig, userConfig) { // 自定义默认配置和用户配置的合并规则,不设置的情况侠会对默认配置和用户配置进行深度合并
+        // defaudltConfig 默认配置
+        // userConfig 用户配置
+        return Object.assign(defaultConfig, userConfig)
+    }
+})
+
+
+// 以如下配置为例
+// {
+//   "tokenExpiresIn": 7200,
+//   "passwordErrorLimit": 6,
+//   "bindTokenToDevice": false,
+//   "passwordErrorRetryTime": 3600,
+//   "app-plus": {
+//     "tokenExpiresIn": 2592000
+//   },
+//   "service": {
+//     "sms": {
+//       "codeExpiresIn": 300
+//     }
+//   }
+// }
+
+// 获取配置
+uniIdConfig.config() // 获取全部配置,注意:uni-config-center内不存在对应插件目录时会返回空对象
+uniIdConfig.config('tokenExpiresIn') // 指定键值获取配置,返回:7200
+uniIdConfig.config('service.sms.codeExpiresIn') // 指定键值获取配置,返回:300
+uniIdConfig.config('tokenExpiresThreshold', 600) // 指定键值获取配置,如果不存在则取传入的默认值,返回:600
+
+// 获取文件绝对路径
+uniIdConfig.resolve('custom-token.js') // 获取uni-config-center/uni-id/custom-token.js文件的路径
+
+// 引用文件(require)
+uniIDConfig.requireFile('custom-token.js') // 使用require方式引用uni-config-center/uni-id/custom-token.js文件。文件不存在时返回undefined,文件内有其他错误导致require失败时会抛出错误。
+
+// 判断是否包含某文件
+uniIDConfig.hasFile('custom-token.js') // 配置目录是否包含某文件,true: 文件存在,false: 文件不存在
+```

Plik diff jest za duży
+ 0 - 0
uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/index.js


+ 9 - 0
uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/package.json

@@ -0,0 +1,9 @@
+{
+  "name": "uni-config-center",
+  "version": "0.0.3",
+  "description": "配置中心",
+  "main": "index.js",
+  "keywords": [],
+  "author": "DCloud",
+  "license": "Apache-2.0"
+}

+ 32 - 0
uni_modules/uni-id-common/changelog.md

@@ -0,0 +1,32 @@
+## 1.0.16(2023-04-25)
+- 新增maxTokenLength配置,用于限制数据库用户记录token数组的最大长度
+## 1.0.15(2023-04-06)
+- 修复部分语言国际化出错的Bug
+## 1.0.14(2023-03-07)
+- 修复 admin用户包含其他角色时未包含在token的Bug
+## 1.0.13(2022-07-21)
+- 修复 创建token时未传角色权限信息生成的token不正确的bug
+## 1.0.12(2022-07-15)
+- 提升与旧版本uni-id的兼容性(补充读取配置文件时回退平台app-plus、h5),但是仍推荐使用新平台名进行配置(app、web)
+## 1.0.11(2022-07-14)
+- 修复 部分情况下报`read property 'reduce' of undefined`的错误
+## 1.0.10(2022-07-11)
+- 将token存储在用户表的token字段内,与旧版本uni-id保持一致
+## 1.0.9(2022-07-01)
+- checkToken兼容token内未缓存角色权限的情况,此时将查库获取角色权限
+## 1.0.8(2022-07-01)
+- 修复clientDB默认依赖时部分情况下获取不到uni-id配置的Bug
+## 1.0.7(2022-06-30)
+- 修复config文件不合法时未抛出具体错误的Bug
+## 1.0.6(2022-06-28)
+- 移除插件内的数据表schema
+## 1.0.5(2022-06-27)
+- 修复使用多应用配置时报`Cannot read property 'appId' of undefined`的Bug
+## 1.0.4(2022-06-27)
+- 修复使用自定义token内容功能报错的Bug [详情](https://ask.dcloud.net.cn/question/147945)
+## 1.0.2(2022-06-23)
+- 对齐旧版本uni-id默认配置
+## 1.0.1(2022-06-22)
+- 补充对uni-config-center的依赖
+## 1.0.0(2022-06-21)
+- 提供uni-id token创建、校验、刷新接口,简化旧版uni-id公共模块

+ 84 - 0
uni_modules/uni-id-common/package.json

@@ -0,0 +1,84 @@
+{
+	"id": "uni-id-common",
+	"displayName": "uni-id-common",
+	"version": "1.0.16",
+	"description": "包含uni-id token生成、校验、刷新功能的云函数公共模块",
+	"keywords": [
+        "uni-id-common",
+        "uniCloud",
+        "token",
+        "权限"
+    ],
+	"repository": "https://gitcode.net/dcloud/uni-id-common",
+	"engines": {
+		"HBuilderX": "^3.1.0"
+	},
+    "dcloudext": {
+        "sale": {
+			"regular": {
+				"price": "0.00"
+			},
+			"sourcecode": {
+				"price": "0.00"
+			}
+		},
+		"contact": {
+			"qq": ""
+		},
+		"declaration": {
+			"ads": "无",
+			"data": "无",
+			"permissions": "无"
+		},
+        "npmurl": "",
+        "type": "unicloud-template-function"
+	},
+	"uni_modules": {
+		"dependencies": ["uni-config-center"],
+		"encrypt": [],
+		"platforms": {
+			"cloud": {
+				"tcb": "y",
+				"aliyun": "y"
+			},
+			"client": {
+				"Vue": {
+					"vue2": "u",
+					"vue3": "u"
+				},
+				"App": {
+					"app-vue": "u",
+					"app-nvue": "u"
+				},
+				"H5-mobile": {
+					"Safari": "u",
+					"Android Browser": "u",
+					"微信浏览器(Android)": "u",
+					"QQ浏览器(Android)": "u"
+				},
+				"H5-pc": {
+					"Chrome": "u",
+					"IE": "u",
+					"Edge": "u",
+					"Firefox": "u",
+					"Safari": "u"
+				},
+				"小程序": {
+					"微信": "u",
+					"阿里": "u",
+					"百度": "u",
+					"字节跳动": "u",
+					"QQ": "u",
+					"钉钉": "u",
+					"快手": "u",
+					"飞书": "u",
+                    "京东": "u"
+				},
+				"快应用": {
+					"华为": "u",
+					"联盟": "u"
+				}
+			}
+		}
+	}
+}

+ 3 - 0
uni_modules/uni-id-common/readme.md

@@ -0,0 +1,3 @@
+# uni-id-common
+
+文档请参考:[uni-id-common](https://uniapp.dcloud.net.cn/uniCloud/uni-id-common.html)

Plik diff jest za duży
+ 0 - 0
uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/index.js


+ 16 - 0
uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/package.json

@@ -0,0 +1,16 @@
+{
+  "name": "uni-id-common",
+  "version": "1.0.16",
+  "description": "uni-id token生成、校验、刷新",
+  "main": "index.js",
+  "homepage": "https://uniapp.dcloud.io/uniCloud/uni-id-common.html",
+  "repository": {
+    "type": "git",
+    "url": "git+https://gitee.com/dcloud/uni-id-common.git"
+  },
+  "author": "DCloud",
+  "license": "Apache-2.0",
+  "dependencies": {
+    "uni-config-center": "file:../../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
+  }
+}

+ 26 - 0
uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/bridge-error.js

@@ -0,0 +1,26 @@
+'use strict';
+
+class BridgeError extends Error {
+
+  constructor(code, message) {
+    super(message)
+
+    this._code = code
+  }
+
+  get code() {
+    return this._code
+  }
+
+  get errCode() {
+    return this._code
+  }
+
+  get errMsg() {
+    return this.message
+  }
+}
+
+module.exports = {
+  BridgeError
+}

+ 124 - 0
uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/config.js

@@ -0,0 +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
+};

+ 30 - 0
uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/consts.js

@@ -0,0 +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
+}

+ 317 - 0
uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/index.js

@@ -0,0 +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
+}

+ 15 - 0
uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/package.json

@@ -0,0 +1,15 @@
+{
+  "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"
+  }
+}

+ 111 - 0
uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/storage.js

@@ -0,0 +1,111 @@
+'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
+};

+ 324 - 0
uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/uni-cloud-cache.js

@@ -0,0 +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
+}

+ 31 - 0
uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/validator.js

@@ -0,0 +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
+}

+ 203 - 0
uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/weixin-server.js

@@ -0,0 +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
+}

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików