20261008
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* 验证token是否有效
|
||||
* @url user/pub/checkToken 前端调用的url参数地址
|
||||
* @description 验证token是否有效(会返回uid)
|
||||
* @param {String} uniIdToken 用户token
|
||||
* res 返回参数说明
|
||||
* @param {Number} code 错误码,0表示成功
|
||||
* @param {String} msg 详细信息
|
||||
* @param {String} uid 当前token对应的用户uid
|
||||
* @param {Object} userInfo 当前用户信息
|
||||
* @param {Array} role 当前用户角色
|
||||
* @param {Array} permission 当前用户权限
|
||||
*/
|
||||
main: async (event) => {
|
||||
let { util } = event;
|
||||
let { uniID } = util;
|
||||
let res = {};
|
||||
// 业务逻辑开始-----------------------------------------------------------
|
||||
res = await uniID.checkToken(event.uniIdToken,{
|
||||
needPermission:true,
|
||||
needUserInfo:true
|
||||
});
|
||||
// 业务逻辑结束-----------------------------------------------------------
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
const platform_Android = 'Android';
|
||||
const platform_iOS = 'iOS';
|
||||
const package_app = 'native_app';
|
||||
const package_wgt = 'wgt';
|
||||
const app_version_db_name = 'opendb-app-versions'
|
||||
module.exports = {
|
||||
/**
|
||||
* App升级中心 - 检测是当前版本是否需要升级
|
||||
* @url user/pub/checkVersion 前端调用的url参数地址
|
||||
* @description 验证token是否有效(会返回uid)
|
||||
* @param {String} uniIdToken 用户token
|
||||
* res 返回参数说明
|
||||
* @param {Number} code 错误码,0表示成功
|
||||
* @param {String} msg 详细信息
|
||||
* @param {String} uid 当前token对应的用户uid
|
||||
* @param {Object} userInfo 当前用户信息
|
||||
* @param {Array} role 当前用户角色
|
||||
* @param {Array} permission 当前用户权限
|
||||
*/
|
||||
main: async (event) => {
|
||||
let { data = {}, userInfo, util, originalParam } = event;
|
||||
let { customUtil, config, pubFun, vk, db, _ } = util;
|
||||
let { uid } = data;
|
||||
let res = { code: 0, msg: "" };
|
||||
let { context } = originalParam;
|
||||
// 业务逻辑开始-----------------------------------------------------------
|
||||
/**
|
||||
* 检测升级 使用说明
|
||||
* 上传包:
|
||||
* 1. 根据传参,先检测传参是否完整,appid appVersion wgtVersion 必传
|
||||
* 2. 先从数据库取出所有该平台(从上下文读取平台信息,默认 Andriod)的所有线上发行更新
|
||||
* 3. 再从所有线上发行更新中取出版本最大的一版。如果可以,尽量先检测wgt的线上发行版更新
|
||||
* 4. 使用上步取出的版本包的版本号 和传参 appVersion、wgtVersion 来检测是否有更新,必须同时大于这两项,否则返回暂无更新
|
||||
* 5. 如果库中 wgt包 版本大于传参 appVersion,但是不满足 min_uni_version < appVersion,则不会使用wgt更新,会接着判断库中 app包version 是否大于 appVersion
|
||||
*/
|
||||
let {
|
||||
appid,
|
||||
appVersion,
|
||||
wgtVersion,
|
||||
} = data;
|
||||
|
||||
let platform = context.OS === 'ios' ? platform_iOS : platform_Android;
|
||||
|
||||
// 参数非空检测
|
||||
let nullKey = vk.pubfn.isNullOneByObject({ appid, appVersion, wgtVersion, platform });
|
||||
if (nullKey) return { code: -102, msg: '参数 ' + nullKey + ' 不能为空' };
|
||||
|
||||
let versionList = await vk.baseDao.select({
|
||||
dbName: app_version_db_name,
|
||||
getCount: false,
|
||||
pageIndex: 1,
|
||||
pageSize: 500,
|
||||
getMain: true,
|
||||
whereJson: {
|
||||
appid,
|
||||
platform,
|
||||
stable_publish: true
|
||||
},
|
||||
sortArr: [{ name: "create_date", type: "desc" }],
|
||||
});
|
||||
if (vk.pubfn.isNull(versionList)) return { code: -101, msg: "暂无更新或检查appid是否填写正确" };
|
||||
|
||||
const appVersionInDb = versionList.find(item => item.type === package_app) || {};
|
||||
const wgtVersionInDb = versionList.find(item => item.type === package_wgt) || {};
|
||||
const hasAppPackage = !!Object.keys(appVersionInDb).length;
|
||||
const hasWgtPackage = !!Object.keys(wgtVersionInDb).length;
|
||||
|
||||
// 取两个版本中版本号最大的包,版本一样,使用wgt包
|
||||
let stablePublishDb = hasAppPackage ?
|
||||
hasWgtPackage ?
|
||||
compare(wgtVersionInDb.version, appVersionInDb.version) >= 0 ?
|
||||
wgtVersionInDb :
|
||||
appVersionInDb :
|
||||
appVersionInDb :
|
||||
wgtVersionInDb;
|
||||
|
||||
const {
|
||||
version,
|
||||
min_uni_version
|
||||
} = stablePublishDb;
|
||||
|
||||
// 库中的version必须满足同时大于appVersion和wgtVersion才行,因为上次更新可能是wgt更新
|
||||
const appUpdate = compare(version, appVersion) === 1; // app包可用更新
|
||||
const wgtUpdate = compare(version, wgtVersion) === 1; // wgt包可用更新
|
||||
|
||||
if (Object.keys(stablePublishDb).length && appUpdate && wgtUpdate) {
|
||||
// 判断是否可用wgt更新
|
||||
if (min_uni_version && compare(min_uni_version, appVersion) < 1) {
|
||||
return {
|
||||
code: 101,
|
||||
msg: 'wgt更新',
|
||||
...stablePublishDb
|
||||
};
|
||||
} else if (hasAppPackage && compare(appVersionInDb.version, appVersion) === 1) {
|
||||
return {
|
||||
code: 102,
|
||||
msg: '整包更新',
|
||||
...appVersionInDb
|
||||
};
|
||||
}
|
||||
} else {
|
||||
return { code: 0, msg: '当前版本已经是最新的,不需要更新' };
|
||||
}
|
||||
// 业务逻辑结束-----------------------------------------------------------
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 对比版本号,如需要,请自行修改判断规则
|
||||
* 支持比对 ("3.0.0.0.0.1.0.1", "3.0.0.0.0.1") ("3.0.0.1", "3.0") ("3.1.1", "3.1.1.1") 之类的
|
||||
* @param {Object} v1
|
||||
* @param {Object} v2
|
||||
* v1 > v2 return 1
|
||||
* v1 < v2 return -1
|
||||
* v1 == v2 return 0
|
||||
*/
|
||||
function compare(v1 = '0', v2 = '0') {
|
||||
v1 = String(v1).split('.')
|
||||
v2 = String(v2).split('.')
|
||||
const minVersionLens = Math.min(v1.length, v2.length);
|
||||
|
||||
let result = 0;
|
||||
for (let i = 0; i < minVersionLens; i++) {
|
||||
const curV1 = Number(v1[i])
|
||||
const curV2 = Number(v2[i])
|
||||
|
||||
if (curV1 > curV2) {
|
||||
result = 1
|
||||
break;
|
||||
} else if (curV1 < curV2) {
|
||||
result = -1
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result === 0 && (v1.length !== v2.length)) {
|
||||
const v1BiggerThenv2 = v1.length > v2.length;
|
||||
const maxLensVersion = v1BiggerThenv2 ? v1 : v2;
|
||||
for (let i = minVersionLens; i < maxLensVersion.length; i++) {
|
||||
const curVersion = Number(maxLensVersion[i])
|
||||
if (curVersion > 0) {
|
||||
v1BiggerThenv2 ? result = 1 : result = -1
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* 获取支付宝openid
|
||||
* @url user/pub/code2SessionAlipay 前端调用的url参数地址
|
||||
* data 请求参数 说明
|
||||
* @param {String} code 支付宝登录返回的code
|
||||
* @param {String} platform 客户端类型:mp-weixin、app-plus,默认uni-id会自动取客户端类型,但是在云函数url化等场景无法取到客户端类型,可以使用此参数指定
|
||||
* res 返回参数说明
|
||||
* @param {Number} code 错误码,0表示成功
|
||||
* @param {String} msg 详细信息
|
||||
* @param {String} openid 用户openid
|
||||
* @param {String} accessToken 客户端为APP时返回
|
||||
* @param {String} expiresIn 客户端为APP时返回,accessToken 接口调用凭证超时时间,单位(秒)
|
||||
* @param {String} refreshToken 客户端为APP时返回,用于刷新accessToken
|
||||
* @param {String} reExpiresIn refreshToken超时时间,单位(秒)
|
||||
*/
|
||||
main: async (event) => {
|
||||
let { data = {}, userInfo, util, originalParam } = event;
|
||||
let { uniID, vk } = util;
|
||||
let { uid } = data;
|
||||
let res = { code: 0, msg: '' };
|
||||
// 业务逻辑开始-----------------------------------------------------------
|
||||
// 用户登录(账号+密码)
|
||||
res = await uniID.code2SessionAlipay(data);
|
||||
if (res.code === 0) {
|
||||
let encrypted = vk.crypto.aes.encrypt({
|
||||
data: res
|
||||
});
|
||||
delete res.sessionKey; // 删除明文sessionKey
|
||||
delete res.accessToken; // 删除明文accessToken
|
||||
delete res.refreshToken; // 删除明文refreshToken
|
||||
res.encryptedKey = encrypted; // 返回前端加密内容
|
||||
}
|
||||
// 业务逻辑结束-----------------------------------------------------------
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* 获取微信openid
|
||||
* @url user/pub/code2SessionWeixin 前端调用的url参数地址
|
||||
* @description 支持APP、微信小程序、微信公众号
|
||||
* data 请求参数 说明
|
||||
* @param {String} code 微信登录返回的code
|
||||
* @param {String} platform 客户端类型:mp-weixin、app-plus、h5-weixin,默认会自动取客户端类型,但是在云函数url化等场景无法取到客户端类型,可以使用此参数指定
|
||||
* res 返回参数说明
|
||||
* @param {Number} code 错误码,0表示成功
|
||||
* @param {String} msg 详细信息
|
||||
* @param {String} openid 用户openid
|
||||
* @param {String} unionid 用户unionid,可以取到此值时返回
|
||||
* @param {String} sessionKey 客户端为微信小程序时返回
|
||||
* @param {String} accessToken 客户端为APP时返回
|
||||
* @param {String} expiresIn 客户端为APP时返回,accessToken 接口调用凭证超时时间,单位(秒)
|
||||
* @param {String} refreshToken 客户端为APP时返回,用于刷新accessToken
|
||||
*/
|
||||
main: async (event) => {
|
||||
let { data = {}, userInfo, util, originalParam } = event;
|
||||
let { uniID, vk } = util;
|
||||
let { uid } = data;
|
||||
let res = { code: 0, msg: '' };
|
||||
// 业务逻辑开始-----------------------------------------------------------
|
||||
let {
|
||||
code,
|
||||
platform,
|
||||
appid,
|
||||
needCache
|
||||
} = data;
|
||||
if (!platform) platform = originalParam.context.PLATFORM;
|
||||
res = await vk.openapi.weixin.auth.code2Session({
|
||||
context: originalParam.context,
|
||||
appid,
|
||||
code,
|
||||
needKey: false, // 是否需要返回明文的sessionKey或accessToken(为了安全期间,建议设置false)
|
||||
});
|
||||
// 业务逻辑结束-----------------------------------------------------------
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
module.exports = {
|
||||
/**
|
||||
* 获取用户微信绑定的手机号
|
||||
* 微信小程序API更新了,现在只需传code可以代替encryptedData和iv
|
||||
* @url user/pub/getPhoneNumber 前端调用的url参数地址
|
||||
* data 请求参数
|
||||
* @param {String} code 通过 getphonenumber 事件获取到的code(code和encryptedData+iv二选一)
|
||||
* @param {String} encryptedData(code和encryptedData+iv二选一)
|
||||
* @param {String} iv(code和encryptedData+iv二选一)
|
||||
* @param {String} encryptedKey code2SessionWeixin 接口返回的encryptedKey
|
||||
*/
|
||||
main: async (event) => {
|
||||
let { data = {}, userInfo, util, originalParam } = event;
|
||||
let { customUtil, config, pubFun, vk, db, _ } = util;
|
||||
let { uid } = data;
|
||||
let res = { code: 0, msg: '' };
|
||||
// 业务逻辑开始-----------------------------------------------------------
|
||||
res = await vk.openapi.weixin.decrypt.getPhoneNumber(data);
|
||||
// 业务逻辑结束-----------------------------------------------------------
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
'use strict';
|
||||
module.exports = {
|
||||
/**
|
||||
* 根据邀请码获取用户社交信息
|
||||
* @url user/pub/getUserInfoByInviteCode 前端调用的url参数地址
|
||||
* data 请求参数
|
||||
* @param {String} code
|
||||
*/
|
||||
main: async (event) => {
|
||||
let { data = {}, util, originalParam } = event;
|
||||
let { customUtil, config, pubFun, vk, db, _ } = util;
|
||||
let { uid } = data;
|
||||
let res = { code : 0, msg : '' };
|
||||
// 业务逻辑开始-----------------------------------------------------------
|
||||
let { code } = data;
|
||||
// 参数非空检测
|
||||
let nullKey = vk.pubfn.isNullOneByObject({ code });
|
||||
if(nullKey) return { code:-1, msg:'参数 '+nullKey+' 不能为空' };
|
||||
res.userInfo = await vk.baseDao.findByWhereJson({
|
||||
dbName:"uni-id-users",
|
||||
fieldJson:{
|
||||
_id:true,
|
||||
nickname:true,
|
||||
gender:true,
|
||||
avatar:true,
|
||||
my_invite_code:true,
|
||||
social_info:true
|
||||
},
|
||||
whereJson:{
|
||||
my_invite_code : code
|
||||
}
|
||||
});
|
||||
return res;
|
||||
// 业务逻辑结束-----------------------------------------------------------
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* 用户登录(账号+密码)
|
||||
* @url user/pub/login 前端调用的url参数地址
|
||||
* @description 用户登录(账号+密码)
|
||||
* data 请求参数 说明
|
||||
* @param {String} username 用户名
|
||||
* @param {String} password 密码
|
||||
* res 返回参数说明
|
||||
* @param {Number} code 错误码,0表示成功
|
||||
* @param {String} msg 详细信息
|
||||
* @param {String} token 登录成功之后返回的token信息
|
||||
* @param {String} tokenExpired token过期时间
|
||||
*/
|
||||
main: async (event) => {
|
||||
let { data = {}, util, originalParam } = event;
|
||||
let { uniID, config, pubFun, vk, db, _ } = util;
|
||||
let { uid } = data;
|
||||
let res = {};
|
||||
// 业务逻辑开始-----------------------------------------------------------
|
||||
// 用户登录(账号+密码)
|
||||
if (typeof data.username === "number") data.username = String(data.username).trim();
|
||||
if (typeof data.password === "number") data.password = String(data.password).trim();
|
||||
|
||||
let {
|
||||
needPermission,
|
||||
username,
|
||||
password,
|
||||
queryField = ['username', 'email', 'mobile'], // 不指定queryField的情况下只会查询username
|
||||
} = data;
|
||||
|
||||
res = await uniID.login({
|
||||
username,
|
||||
password,
|
||||
needPermission,
|
||||
queryField
|
||||
});
|
||||
if (res.token) {
|
||||
if (!res.msg) {
|
||||
res.msg = res.type === "register" ? "注册成功" : "登录成功";
|
||||
}
|
||||
// 日志服务
|
||||
const loginLogService = vk.require("service/user/util/login_log");
|
||||
await loginLogService.add({
|
||||
type: "login",
|
||||
login_type: "password",
|
||||
user_id: res.uid,
|
||||
context: originalParam.context
|
||||
}, util);
|
||||
}
|
||||
// 业务逻辑结束-----------------------------------------------------------
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* 用户登录(支付宝授权)
|
||||
* @url user/pub/loginByAlipay 前端调用的url参数地址
|
||||
* @description 用户登录(支付宝授权)
|
||||
* data 请求参数 说明
|
||||
* @param {String} code 支付宝登录返回的code
|
||||
* @param {String} type login:登录 register:注册
|
||||
* res 返回参数说明
|
||||
* @param {Number} code 错误码,0表示成功
|
||||
* @param {String} msg 详细信息
|
||||
* @param {String} token 登录成功之后返回的token信息
|
||||
* @param {String} tokenExpired token过期时间
|
||||
*/
|
||||
main: async (event) => {
|
||||
let { data = {}, util, originalParam } = event;
|
||||
let { uniID, config, pubFun, vk, db, _ } = util;
|
||||
let { uid } = data;
|
||||
let res = {};
|
||||
// 业务逻辑开始-----------------------------------------------------------
|
||||
let {
|
||||
code,
|
||||
type,
|
||||
myInviteCode,
|
||||
needPermission
|
||||
} = data;
|
||||
res = await uniID.loginByAlipay({
|
||||
code,
|
||||
type,
|
||||
myInviteCode,
|
||||
needPermission
|
||||
});
|
||||
if (res.token) {
|
||||
if (!res.msg) {
|
||||
res.msg = res.type === "register" ? "注册成功" : "登录成功";
|
||||
}
|
||||
let encrypted = vk.crypto.aes.encrypt({
|
||||
data: res
|
||||
});
|
||||
delete res.sessionKey; // 删除明文sessionKey
|
||||
delete res.accessToken; // 删除明文accessToken
|
||||
res.encryptedKey = encrypted; // 返回前端加密内容
|
||||
// 日志服务
|
||||
const loginLogService = vk.require("service/user/util/login_log");
|
||||
await loginLogService.add({
|
||||
type: "login",
|
||||
login_type: "alipay",
|
||||
user_id: res.uid,
|
||||
context: originalParam.context
|
||||
}, util);
|
||||
}
|
||||
// 业务逻辑结束-----------------------------------------------------------
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* 用户登录(邮箱+验证码登录)
|
||||
* @url user/pub/loginByEmail 前端调用的url参数地址
|
||||
* data 请求参数 说明
|
||||
* @param {String} email 邮箱
|
||||
* @param {String} code 邮箱收到的验证码
|
||||
* @param {String} type 指定操作类型,不传:存在则登录不存在则注册 login:只能登录 register:只能注册
|
||||
* @param {String} password 密码,当前用户为新注册时生效
|
||||
* @param {String} myInviteCode 设置当前注册用户自己的邀请码,当前用户为新注册时生效(不传会自动生成)
|
||||
* @param {Boolean} needPermission 设置为true时会在checkToken时返回用户权限(permission),如果是在admin端,需传true
|
||||
* res 返回参数说明
|
||||
* @param {Number} code 错误码,0表示成功
|
||||
* @param {String} msg 详细信息
|
||||
* @param {String} token 登录成功之后返回的token信息
|
||||
* @param {String} tokenExpired token过期时间
|
||||
*/
|
||||
main: async (event) => {
|
||||
let { data = {}, util, originalParam } = event;
|
||||
let { uniID, config, pubFun, vk, db, _ } = util;
|
||||
let { uid } = data;
|
||||
let res = {};
|
||||
// 业务逻辑开始-----------------------------------------------------------
|
||||
let {
|
||||
email,
|
||||
code,
|
||||
type,
|
||||
password,
|
||||
needPermission,
|
||||
myInviteCode
|
||||
} = data;
|
||||
res = await uniID.loginByEmail({
|
||||
email,
|
||||
code,
|
||||
type,
|
||||
password,
|
||||
myInviteCode,
|
||||
needPermission
|
||||
});
|
||||
if (res.token) {
|
||||
if (!res.msg) {
|
||||
res.msg = res.type === "register" ? "注册成功" : "登录成功";
|
||||
}
|
||||
// 日志服务
|
||||
const loginLogService = vk.require("service/user/util/login_log");
|
||||
await loginLogService.add({
|
||||
type: "login",
|
||||
login_type: "email",
|
||||
user_id: res.uid,
|
||||
context: originalParam.context
|
||||
}, util);
|
||||
}
|
||||
// 业务逻辑结束-----------------------------------------------------------
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* QQ授权登录
|
||||
* @url user/pub/loginByQQ 前端调用的url参数地址
|
||||
* data 请求参数 说明
|
||||
* @param {String} code QQ小程序登录返回的code
|
||||
* @param {String} accessToken QQ APP登录返回的access_token
|
||||
* @param {String} type login:登录 register:注册
|
||||
* res 返回参数说明
|
||||
* @param {Number} code 错误码,0表示成功
|
||||
* @param {String} msg 详细信息
|
||||
* @param {String} token 登录成功之后返回的token信息
|
||||
* @param {String} tokenExpired token过期时间
|
||||
*/
|
||||
main: async (event) => {
|
||||
let { data = {}, util, originalParam } = event;
|
||||
let { uniID, config, pubFun, vk, db, _ } = util;
|
||||
let { uid } = data;
|
||||
let res = {};
|
||||
// 业务逻辑开始-----------------------------------------------------------
|
||||
let {
|
||||
code,
|
||||
accessToken,
|
||||
type,
|
||||
myInviteCode,
|
||||
needPermission
|
||||
} = data;
|
||||
res = await uniID.loginByQQ({
|
||||
code,
|
||||
accessToken,
|
||||
type,
|
||||
myInviteCode,
|
||||
needPermission
|
||||
});
|
||||
if (res.token) {
|
||||
if (!res.msg) {
|
||||
res.msg = res.type === "register" ? "注册成功" : "登录成功";
|
||||
}
|
||||
let encrypted = vk.crypto.aes.encrypt({
|
||||
data: res
|
||||
});
|
||||
delete res.sessionKey; // 删除明文sessionKey
|
||||
delete res.accessToken; // 删除明文accessToken
|
||||
delete res.refreshToken; // 删除明文refreshToken
|
||||
res.encryptedKey = encrypted; // 返回前端加密内容
|
||||
// 日志服务
|
||||
const loginLogService = vk.require("service/user/util/login_log");
|
||||
await loginLogService.add({
|
||||
type: "login",
|
||||
login_type: "qq",
|
||||
user_id: res.uid,
|
||||
context: originalParam.context
|
||||
}, util);
|
||||
}
|
||||
// 业务逻辑结束-----------------------------------------------------------
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* 手机号登陆(手机号+手机验证码)
|
||||
* @url user/pub/loginBySms 前端调用的url参数地址
|
||||
* @description 手机号登陆(手机号+手机验证码)
|
||||
* data 请求参数 说明
|
||||
* @param {String} mobile 手机号
|
||||
* @param {String} code 验证码
|
||||
* @param {String} type 指定操作类型,不传:存在则登录不存在则注册 login:只能登录 register:只能注册
|
||||
* @param {String} password 密码,当前用户为新注册时生效
|
||||
* @param {String} inviteCode 邀请人的邀请码,当前用户为新注册时生效
|
||||
* @param {String} myInviteCode 设置当前注册用户自己的邀请码,当前用户为新注册时生效(不传会自动生成)
|
||||
* @param {Boolean} needPermission 设置为true时会在checkToken时返回用户权限(permission),如果是在admin端,需传true
|
||||
* res 返回参数说明
|
||||
* @param {Number} code 错误码,0表示成功
|
||||
* @param {String} msg 详细信息
|
||||
* @param {String} token 登录成功之后返回的token信息
|
||||
* @param {String} tokenExpired token过期时间
|
||||
*/
|
||||
main: async (event) => {
|
||||
let { data = {}, util, originalParam } = event;
|
||||
let { uniID, config, pubFun, vk, db, _ } = util;
|
||||
let { uid } = data;
|
||||
let res = {};
|
||||
// 业务逻辑开始-----------------------------------------------------------
|
||||
let {
|
||||
mobile,
|
||||
code,
|
||||
type,
|
||||
password,
|
||||
inviteCode,
|
||||
myInviteCode,
|
||||
needPermission
|
||||
} = data;
|
||||
res = await uniID.loginBySms({
|
||||
mobile,
|
||||
code,
|
||||
type,
|
||||
password,
|
||||
inviteCode,
|
||||
myInviteCode,
|
||||
needPermission
|
||||
});
|
||||
// 修改用户昵称为:手机尾号xxxx用户
|
||||
if (res.token) {
|
||||
if (!res.msg) {
|
||||
res.msg = res.type === "register" ? "注册成功" : "登录成功";
|
||||
}
|
||||
let mobileStr = mobile.substring(7);
|
||||
await vk.baseDao.update({
|
||||
dbName: "uni-id-users",
|
||||
whereJson: {
|
||||
_id: res.uid,
|
||||
nickname: null
|
||||
},
|
||||
dataJson: {
|
||||
nickname: `手机尾号${mobileStr}用户`
|
||||
}
|
||||
});
|
||||
// 日志服务
|
||||
const loginLogService = vk.require("service/user/util/login_log");
|
||||
await loginLogService.add({
|
||||
type: "login",
|
||||
login_type: "sms",
|
||||
user_id: res.uid,
|
||||
context: originalParam.context
|
||||
}, util);
|
||||
}
|
||||
// 业务逻辑结束-----------------------------------------------------------
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* APP端 手机一键登录
|
||||
* @url user/pub/loginByUniverify 前端调用的url参数地址
|
||||
* @param {String} access_token uni.login登录成功后,返回的access_token参数
|
||||
* @param {String} openid uni.login登录成功后,返回的openid参数
|
||||
* @param {String} type 指定操作类型,可选值为login、register,不传此参数时表现为手机号已注册则登录,手机号未注册则进行注册
|
||||
* @param {String} password 密码,type为register时生效
|
||||
* @param {String} inviteCode 邀请人的邀请码,type为register时生效
|
||||
* @param {String} myInviteCode 设置当前注册用户自己的邀请码,type为register时生效
|
||||
* @param {Boolean} needPermission 设置为true时会在checkToken时返回用户权限(permission),建议在管理控制台中使用
|
||||
* res 返回参数说明
|
||||
* @param {Number} code 错误码,0表示成功
|
||||
* @param {String} msg 详细信息
|
||||
* @param {String} uid 当前token对应的用户uid
|
||||
* @param {String} type 操作类型,login为登录、register为注册
|
||||
* @param {String} mobile 登录者手机号
|
||||
* @param {String} userInfo 用户全部信息
|
||||
* @param {String} token 登录成功之后返回的token信息
|
||||
* @param {String} tokenExpired token过期时间
|
||||
*/
|
||||
main: async (event) => {
|
||||
let { data = {}, userInfo, util, originalParam } = event;
|
||||
let { customUtil, uniID, config, pubFun, vk, db, _ } = util;
|
||||
let { uid } = data;
|
||||
let res = { code: 0, msg: '' };
|
||||
// 业务逻辑开始-----------------------------------------------------------
|
||||
let {
|
||||
access_token,
|
||||
openid,
|
||||
type,
|
||||
password,
|
||||
inviteCode,
|
||||
myInviteCode,
|
||||
needPermission
|
||||
} = data;
|
||||
res = await uniID.loginByUniverify({
|
||||
access_token,
|
||||
openid,
|
||||
type,
|
||||
password,
|
||||
inviteCode,
|
||||
myInviteCode,
|
||||
needPermission
|
||||
});
|
||||
if (res.token) {
|
||||
if (!res.msg) {
|
||||
res.msg = res.type === "register" ? "注册成功" : "登录成功";
|
||||
}
|
||||
if (res.type === "register") {
|
||||
let mobileStr = res.userInfo.mobile.substring(7);
|
||||
res.userInfo = await vk.baseDao.updateAndReturn({
|
||||
dbName: "uni-id-users",
|
||||
whereJson: {
|
||||
_id: res.uid
|
||||
},
|
||||
dataJson: {
|
||||
nickname: data.nickname || `手机尾号${mobileStr}用户`,
|
||||
},
|
||||
});
|
||||
}
|
||||
// 日志服务
|
||||
const loginLogService = vk.require("service/user/util/login_log");
|
||||
await loginLogService.add({
|
||||
type: "login",
|
||||
login_type: "univerify",
|
||||
user_id: res.uid,
|
||||
context: originalParam.context
|
||||
}, util);
|
||||
}
|
||||
// 业务逻辑结束-----------------------------------------------------------
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* 用户登录(微信授权)
|
||||
* @url user/pub/loginByWeixin 前端调用的url参数地址
|
||||
* @description 支持APP、微信小程序、微信公众号
|
||||
* data 请求参数 说明
|
||||
* @param {String} code 微信登录返回的code
|
||||
* @param {String} type login:登录 register:注册
|
||||
* res 返回参数说明
|
||||
* @param {Number} code 错误码,0表示成功
|
||||
* @param {String} msg 详细信息
|
||||
* @param {String} token 登录成功之后返回的token信息
|
||||
* @param {String} tokenExpired token过期时间
|
||||
* @param {Object} userInfo 用户信息
|
||||
*/
|
||||
main: async (event) => {
|
||||
let { data = {}, util, originalParam } = event;
|
||||
let { uniID, config, pubFun, vk, db, _ } = util;
|
||||
let { uid } = data;
|
||||
let res = {};
|
||||
// 业务逻辑开始-----------------------------------------------------------
|
||||
// 额外写入的自定义字段数据(可以自己增加,建议只传一些显示的信息,不要传余额字段等,因为前端不可信任)
|
||||
// 注意:app的微信登录已经支持自动获取昵称和头像,前端无需再传昵称和头像。
|
||||
let custom = {
|
||||
nickname: data.nickname,
|
||||
avatar: data.avatar
|
||||
};
|
||||
/**
|
||||
* 支持多小程序登录
|
||||
* 此处data可以额外接收appid和appsecret参数(appid可以从前端传,而appsecret可以配置在全局配置中(common/uni-config-center/vk-unicloud/index.js),也可以自己从数据库获取)
|
||||
* 如果不传appid,则默认使用uni-id的配置信息
|
||||
* 特别注意:如果使用多小程序登录,则同一用户(同一个微信号)在不同小程序登录时,会分别创建不同的用户(除非小程序绑定在同一个开放平台下)。
|
||||
*/
|
||||
|
||||
// 打开下方注释,动态赋值appid和appsecret即可支持多小程序登录
|
||||
// data.appid = "xxxx";
|
||||
// data.appsecret = "xxxx";
|
||||
|
||||
res = await vk.openapi.weixin.loginByWeixin({
|
||||
data,
|
||||
context: originalParam.context,
|
||||
custom,
|
||||
needKey: false, // 是否需要返回明文的sessionKey或accessToken(为了安全期间,建议设置false)
|
||||
});
|
||||
if (res.token) {
|
||||
// 日志服务
|
||||
const loginLogService = vk.require("service/user/util/login_log");
|
||||
await loginLogService.add({
|
||||
type: "login",
|
||||
login_type: "weixin",
|
||||
user_id: res.uid,
|
||||
context: originalParam.context
|
||||
}, util);
|
||||
}
|
||||
// 业务逻辑结束-----------------------------------------------------------
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* 用户登录(微信手机号授权)
|
||||
* @url user/pub/loginByWeixinPhoneNumber 前端调用的url参数地址
|
||||
* @description 用户登录(微信授权)
|
||||
* data 请求参数 说明
|
||||
* @param {String} code 通过 getphonenumber 事件获取到的code(code和encryptedData+iv二选一)
|
||||
* @param {String} encryptedData(code和encryptedData+iv二选一)
|
||||
* @param {String} iv(code和encryptedData+iv二选一)
|
||||
* @param {String} encryptedKey code2SessionWeixin 接口返回的encryptedKey
|
||||
* res 返回参数说明
|
||||
* @param {Number} code 错误码,0表示成功
|
||||
* @param {String} msg 详细信息
|
||||
* @param {String} token 登录成功之后返回的token信息
|
||||
* @param {String} tokenExpired token过期时间
|
||||
*/
|
||||
main: async (event) => {
|
||||
let { data = {}, util, originalParam } = event;
|
||||
let { uniID, config, pubFun, vk, db, _ } = util;
|
||||
let { uid } = data;
|
||||
let res = {};
|
||||
// 业务逻辑开始-----------------------------------------------------------
|
||||
let {
|
||||
nickname,
|
||||
avatar,
|
||||
gender,
|
||||
inviteCode,
|
||||
encryptedKey,
|
||||
code,
|
||||
encryptedData,
|
||||
iv
|
||||
} = data;
|
||||
|
||||
// 获取微信绑定的手机号
|
||||
res = await vk.openapi.weixin.decrypt.getPhoneNumber({
|
||||
encryptedKey,
|
||||
code,
|
||||
encryptedData,
|
||||
iv
|
||||
});
|
||||
if (res.code !== 0) return res;
|
||||
let {
|
||||
mobile
|
||||
} = res;
|
||||
let mobileCode = vk.pubfn.random(6);
|
||||
// 指定操作类型,可选值为login、register,不传此参数时表现为手机号已注册则登录,手机号未注册则进行注册
|
||||
let type;
|
||||
// 通过手机号登录
|
||||
await uniID.setVerifyCode({ mobile, code: mobileCode, expiresIn: 60, type: "login" });
|
||||
res = await uniID.loginBySms({ mobile, code: mobileCode, type, inviteCode });
|
||||
if (!res.token) return res;
|
||||
if (!res.msg) {
|
||||
res.msg = res.type === "register" ? "注册成功" : "登录成功";
|
||||
}
|
||||
if (res.type === "register") {
|
||||
// 解密获得openid和unionid
|
||||
let decryptedRes = vk.crypto.aes.decrypt({
|
||||
data: encryptedKey, // 待解密的原文
|
||||
});
|
||||
let wx_openid = {};
|
||||
let wx_unionid = decryptedRes.unionid;
|
||||
wx_openid["mp-weixin"] = decryptedRes.openid;
|
||||
// 查询openid或unionid是否已经存在,如果存在,则不绑定微信.
|
||||
let queryUserInfo = await vk.daoCenter.userDao.findByUserInfo({
|
||||
"wx_openid.mp-weixin": wx_openid["mp-weixin"],
|
||||
"wx_unionid": wx_unionid
|
||||
});
|
||||
res.bindWeixin = vk.pubfn.isNull(queryUserInfo) ? true : false;
|
||||
// 需要额外添加的字段
|
||||
let mobileStr = mobile.substring(7);
|
||||
let dataJson = {
|
||||
nickname: nickname || `手机尾号${mobileStr}用户`,
|
||||
avatar,
|
||||
gender
|
||||
};
|
||||
if (res.bindWeixin) {
|
||||
dataJson["wx_openid"] = wx_openid;
|
||||
dataJson["wx_unionid"] = wx_unionid;
|
||||
}
|
||||
res.userInfo = await vk.baseDao.updateAndReturn({
|
||||
dbName: "uni-id-users",
|
||||
whereJson: {
|
||||
_id: res.uid
|
||||
},
|
||||
dataJson
|
||||
});
|
||||
}
|
||||
// 日志服务
|
||||
const loginLogService = vk.require("service/user/util/login_log");
|
||||
await loginLogService.add({
|
||||
type: res.type,
|
||||
login_type: "weixinPhoneNumber",
|
||||
user_id: res.uid,
|
||||
context: originalParam.context
|
||||
}, util);
|
||||
// 业务逻辑结束-----------------------------------------------------------
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* 用户退出登录
|
||||
* @url user/pub/logout 前端调用的url参数地址
|
||||
* @description 用户退出登录
|
||||
* res 返回参数说明
|
||||
* @param {Number} code 错误码,0表示成功
|
||||
* @param {String} msg 详细信息
|
||||
*/
|
||||
main: async (event) => {
|
||||
let { util } = event;
|
||||
let { uniID } = util;
|
||||
let res = {};
|
||||
// 业务逻辑开始-----------------------------------------------------------
|
||||
if(event.uniIdToken){
|
||||
res = await uniID.logout(event.uniIdToken);
|
||||
}else{
|
||||
res.code = 0;
|
||||
res.msg = "未登录";
|
||||
}
|
||||
// 业务逻辑结束-----------------------------------------------------------
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* 用户注册(账号+密码)
|
||||
* @url user/pub/register 前端调用的url参数地址
|
||||
* @description 用户注册(账号+密码)
|
||||
* data 请求参数 说明
|
||||
* @param {String} username 用户名,唯一
|
||||
* @param {String} password 密码
|
||||
* res 返回参数说明
|
||||
* @param {Number} code 错误码,0表示成功
|
||||
* @param {String} msg 详细信息
|
||||
* @param {String} token 注册完成自动登录之后返回的token信息
|
||||
* @param {String} tokenExpired token过期时间
|
||||
* @param {Object} userInfo 用户信息
|
||||
*/
|
||||
main: async (event) => {
|
||||
let { data = {}, userInfo, util, originalParam } = event;
|
||||
let { uniID, config, pubFun, vk, db, _ } = util;
|
||||
let { uid } = data;
|
||||
let res = { code: -1, msg: '' };
|
||||
// 业务逻辑开始-----------------------------------------------------------
|
||||
if (typeof data.username === "number") data.username = String(data.username).trim();
|
||||
if (typeof data.password === "number") data.password = String(data.password).trim();
|
||||
|
||||
let {
|
||||
username,
|
||||
password,
|
||||
needPermission,
|
||||
myInviteCode
|
||||
} = data;
|
||||
|
||||
// 验证规则开始 -----------------------------------------------------------
|
||||
let rules = {
|
||||
username: [
|
||||
{ required: true, validator: vk.pubfn.validator("username"), message: '用户名以字母开头,长度在3~32之间,只能包含字母、数字和下划线', trigger: ['blur', 'change'] }
|
||||
],
|
||||
password: [
|
||||
{ validator: vk.pubfn.validator("password"), message: '密码长度在6~18之间,只能包含字母、数字和下划线', trigger: 'blur' }
|
||||
]
|
||||
};
|
||||
// 验证规则结束 -----------------------------------------------------------
|
||||
// 开始进行验证
|
||||
let formRulesRes = vk.pubfn.formValidate({
|
||||
data: data,
|
||||
rules: rules
|
||||
});
|
||||
if (formRulesRes.code !== 0) {
|
||||
// 表单验证未通过
|
||||
return formRulesRes;
|
||||
}
|
||||
// 表单验证通过,下面写自己的业务逻辑
|
||||
res = await uniID.register({
|
||||
username,
|
||||
password,
|
||||
needPermission,
|
||||
myInviteCode
|
||||
});
|
||||
// 业务逻辑结束-----------------------------------------------------------
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* 根据邮箱+验证码重置密码
|
||||
* @url user/pub/resetPasswordByEmail 前端调用的url参数地址
|
||||
* data 请求参数 说明
|
||||
* @param {String} password 重置后的密码
|
||||
* @param {String} code 验证码
|
||||
* @param {String} email 邮箱号码
|
||||
* res 返回参数说明
|
||||
* @param {Number} code 错误码,0表示成功
|
||||
* @param {String} msg 详细信息
|
||||
*/
|
||||
main: async (event) => {
|
||||
let { data = {}, util, originalParam } = event;
|
||||
let { uniID, config, pubFun, vk , db, _ } = util;
|
||||
let {
|
||||
_id,
|
||||
password,
|
||||
code,
|
||||
email
|
||||
} = data;
|
||||
let res = { code : -1, msg : '' };
|
||||
// 业务逻辑开始-----------------------------------------------------------
|
||||
// 可写与数据库的交互逻辑等等
|
||||
// 检查验证码是否正确
|
||||
res = await uniID.verifyCode({
|
||||
email,
|
||||
code,
|
||||
type: 'reset-pwd', // 自2022-08-13起,以从reset改为reset-pwd,与官方uni-id对齐
|
||||
});
|
||||
if(res.code !== 0){
|
||||
return res;
|
||||
}
|
||||
// 根据email查询用户是否存在
|
||||
let userInfo = await vk.baseDao.findByWhereJson({
|
||||
dbName:"uni-id-users",
|
||||
whereJson:{
|
||||
email
|
||||
}
|
||||
});
|
||||
if(!userInfo){
|
||||
return { code : -1, msg : '邮箱号未注册!' };
|
||||
}
|
||||
// 重置密码
|
||||
res = await uniID.resetPwd({
|
||||
uid: userInfo._id,
|
||||
password
|
||||
});
|
||||
// 业务逻辑结束-----------------------------------------------------------
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* 根据手机+验证码重置密码
|
||||
* @url user/pub/resetPasswordByMobile 前端调用的url参数地址
|
||||
* data 请求参数 说明
|
||||
* @param {String} password 重置后的密码
|
||||
* @param {String} code 验证码
|
||||
* @param {String} mobile 手机号
|
||||
* res 返回参数说明
|
||||
* @param {Number} code 错误码,0表示成功
|
||||
* @param {String} msg 详细信息
|
||||
*/
|
||||
main: async (event) => {
|
||||
let { data = {}, util, originalParam } = event;
|
||||
let { uniID, config, pubFun, vk , db, _ } = util;
|
||||
let {
|
||||
_id,
|
||||
password,
|
||||
code,
|
||||
mobile
|
||||
} = data;
|
||||
let res = { code : -1, msg : '' };
|
||||
// 业务逻辑开始-----------------------------------------------------------
|
||||
// 可写与数据库的交互逻辑等等
|
||||
// 检查验证码是否正确
|
||||
res = await uniID.verifyCode({
|
||||
mobile,
|
||||
code,
|
||||
type: 'reset-pwd', // 自2022-08-13起,以从reset改为reset-pwd,与官方uni-id对齐
|
||||
});
|
||||
if(res.code !== 0){
|
||||
return res;
|
||||
}
|
||||
// 根据mobile查询用户是否存在
|
||||
let userInfo = await vk.baseDao.findByWhereJson({
|
||||
dbName:"uni-id-users",
|
||||
whereJson:{
|
||||
mobile
|
||||
}
|
||||
});
|
||||
if(!userInfo){
|
||||
return { code : -1, msg : '手机号未注册!' };
|
||||
}
|
||||
// 重置密码
|
||||
res = await uniID.resetPwd({
|
||||
uid: userInfo._id,
|
||||
password
|
||||
});
|
||||
// 业务逻辑结束-----------------------------------------------------------
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
var vkmail;
|
||||
try {
|
||||
vkmail = require('vk-mail');
|
||||
} catch (err) {
|
||||
console.error("请先添加公共模块:vk-mail(右键对应的云函数,点击管理公共模块或扩展库依赖,勾选vk-mail依赖)");
|
||||
}
|
||||
var everyDaylimit = 30; // 限制同一个邮箱每天次数
|
||||
module.exports = {
|
||||
/**
|
||||
* 发送邮箱验证码
|
||||
* @url user/pub/sendEmailCode 前端调用的url参数地址
|
||||
* @description 发送邮箱验证码
|
||||
* data 请求参数 说明
|
||||
* @param {String} email 邮箱
|
||||
* @param {String} type 验证码类型
|
||||
* @param {String} serviceType 邮件服务类型,默认为qq
|
||||
* @param {Boolean|String} checkUserExist 是否需要检测邮箱对应的账号是否存在或不存在,默认不检测,若为exists代表邮箱必须已注册,若为!exists代表邮箱必须未注册
|
||||
* res 返回参数说明
|
||||
* @param {Number} code 错误码,0表示成功
|
||||
* @param {String} msg 详细信息
|
||||
*/
|
||||
main: async (event) => {
|
||||
let { data = {}, util } = event;
|
||||
let { uniID, config } = util;
|
||||
let {
|
||||
email,
|
||||
type,
|
||||
serviceType = "qq",
|
||||
checkUserExist = false
|
||||
} = data;
|
||||
let res = { code: 0, msg: 'ok' };
|
||||
// 业务逻辑开始-----------------------------------------------------------
|
||||
if (!vkmail) {
|
||||
return { code: -1, msg: "请先添加公共模块:vk-mail(右键对应的云函数,点击管理公共模块或扩展库依赖,勾选vk-mail依赖)" };
|
||||
}
|
||||
// 参数非空检测
|
||||
let nullKey = vk.pubfn.isNullOneByObject({ email, type });
|
||||
if (nullKey) return { code: -1, msg: '参数 ' + nullKey + ' 不能为空' };
|
||||
|
||||
if (!vk.pubfn.test(email, "email")) return { code: -1, msg: "邮箱格式错误" };
|
||||
if (vk.pubfn.isNull(type)) return { code: -1, msg: "type不能为空" };
|
||||
|
||||
if (checkUserExist) {
|
||||
let dcloud_appid = originalParam.context.appId;
|
||||
// 检测邮箱对应的账号是否存在
|
||||
let num = await vk.daoCenter.userDao.count({
|
||||
email,
|
||||
dcloud_appid: _.or(_.eq(dcloud_appid), _.exists(false))
|
||||
});
|
||||
if (checkUserExist === true || checkUserExist === "exists") {
|
||||
// 邮箱必须已注册用户,如果邮箱未注册,则不发短信
|
||||
if (num === 0) {
|
||||
return { code: -1, msg: `邮箱:${email} 未注册`, notExists: true };
|
||||
}
|
||||
} else if (checkUserExist === "!exists") {
|
||||
// 邮箱必须未注册用户,如果邮箱已注册,则不发短信
|
||||
if (num > 0) {
|
||||
return { code: -1, msg: `邮箱:${email} 已注册`, exists: true };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 针对同一个邮箱,发送验证码每天有次数限制
|
||||
const cacheKey = `sys.sendEmailCode.everyDaylimit-${email}`;
|
||||
let currNum = await vk.globalDataCache.get(cacheKey);
|
||||
if (!currNum) currNum = 0;
|
||||
if (currNum >= everyDaylimit) {
|
||||
return { code: -1, msg: "此邮箱今日已超最大次数限制,请明日再试" };
|
||||
}
|
||||
|
||||
let code = vk.pubfn.random(6, "0123456789");
|
||||
let param = {
|
||||
code,
|
||||
type,
|
||||
email
|
||||
};
|
||||
// 发送验证码开始
|
||||
let emailConfig = config.vk.service.email;
|
||||
// 如果配置设置了过期时间,则使用配置的过期时间,否则默认180秒
|
||||
param.expiresIn = emailConfig.codeExpiresIn || 180;
|
||||
let emailService = vkmail.createTransport({
|
||||
"host": emailConfig[serviceType].host,
|
||||
"port": emailConfig[serviceType].port,
|
||||
"secure": emailConfig[serviceType].secure, // use SSL
|
||||
"auth": emailConfig[serviceType].auth
|
||||
});
|
||||
try {
|
||||
// 发送邮件
|
||||
await emailService.sendMail({
|
||||
"from": emailConfig[serviceType].auth.user,
|
||||
"to": data.email,
|
||||
"cc": emailConfig[serviceType].auth.user, // 由于邮件可能会被当成垃圾邮件,但只要把邮件抄送给自己一份,就不会被当成垃圾邮件。
|
||||
"subject": data.subject || `验证码是${code}`, // 邮件的标题
|
||||
"text": `您的验证码是${code},打死也不要告诉别人哦!`, // 邮件的内容
|
||||
});
|
||||
// 发送验证码成功后,设置验证码
|
||||
await uniID.setVerifyCode(param);
|
||||
|
||||
currNum++;
|
||||
let { startTime } = vk.pubfn.getDayOffsetStartAndEnd(1, new Date());
|
||||
let second = vk.pubfn.toDecimal((startTime - Date.now()) / 1000, 0)
|
||||
await vk.globalDataCache.set(cacheKey, currNum, second);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return { code: -1, msg: "邮件发送失败", err };
|
||||
}
|
||||
// 发送验证码结束
|
||||
|
||||
// 业务逻辑结束-----------------------------------------------------------
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
var everyDaylimit = 12; // 限制同一个手机号每天次数
|
||||
module.exports = {
|
||||
/**
|
||||
* 发送短信的验证码
|
||||
* @url user/pub/sendSmsCode 前端调用的url参数地址
|
||||
* @description 发送验证码
|
||||
* data 请求参数 说明
|
||||
* @param {String} mobile 手机号
|
||||
* @param {String} type 验证码类型
|
||||
* @param {Boolean|String} checkUserExist 是否需要检测手机号对应的账号是否存在或不存在,默认不检测,若为exists代表手机号必须已注册,若为!exists代表手机号必须未注册
|
||||
*
|
||||
* res 返回参数说明
|
||||
* @param {Number} code 错误码,0表示成功
|
||||
* @param {String} msg 详细信息
|
||||
* @param {Object} requestRes 原始返回数据
|
||||
* @param {Object} requestParam 包含服务供应商和发送的手机号
|
||||
*/
|
||||
main: async (event) => {
|
||||
let { data = {}, userInfo, util, originalParam } = event;
|
||||
let { uniID, config, pubFun, vk, db, _ } = util;
|
||||
let { uid } = data;
|
||||
let res = { code: 0, msg: '' };
|
||||
// 业务逻辑开始-----------------------------------------------------------
|
||||
let {
|
||||
mobile,
|
||||
type,
|
||||
checkUserExist = false
|
||||
} = data;
|
||||
if (vk.pubfn.isNull(mobile)) {
|
||||
return { code: -1, msg: '手机号不能为空' };
|
||||
}
|
||||
if (!vk.pubfn.test(mobile, 'mobile')) {
|
||||
return { code: -1, msg: "手机号格式错误" };
|
||||
}
|
||||
|
||||
if (checkUserExist) {
|
||||
let dcloud_appid = originalParam.context.appId;
|
||||
// 检测手机号对应的账号是否存在
|
||||
let num = await vk.daoCenter.userDao.count({
|
||||
mobile,
|
||||
dcloud_appid: _.or(_.eq(dcloud_appid), _.exists(false))
|
||||
});
|
||||
if (checkUserExist === true || checkUserExist === "exists") {
|
||||
// 手机号必须已注册用户,如果手机号未注册,则不发短信
|
||||
if (num === 0) {
|
||||
return { code: -1, msg: `手机号:${mobile} 未注册`, notExists: true };
|
||||
}
|
||||
} else if (checkUserExist === "!exists") {
|
||||
// 手机号必须未注册用户,如果手机号已注册,则不发短信
|
||||
if (num > 0) {
|
||||
return { code: -1, msg: `手机号:${mobile} 已注册`, exists: true };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 针对同一个手机号,发送验证码每天有次数限制
|
||||
const cacheKey = `sys.sendSmsCode.everyDaylimit-${mobile}`;
|
||||
let currNum = await vk.globalDataCache.get(cacheKey);
|
||||
if (!currNum) currNum = 0;
|
||||
if (currNum >= everyDaylimit) {
|
||||
return { code: -1, msg: "此手机号今日已超最大次数限制,请明日再试" };
|
||||
}
|
||||
|
||||
|
||||
let code = vk.pubfn.random(6, "0123456789");
|
||||
let provider = "unicloud";
|
||||
if (vk.pubfn.getData(config, "vk.service.sms.aliyun.enable")) {
|
||||
provider = "aliyun";
|
||||
}
|
||||
res = await vk.system.smsUtil.sendSmsVerifyCode({
|
||||
provider,
|
||||
code,
|
||||
type,
|
||||
phone: mobile,
|
||||
expiresIn: 180, // 验证码实际有效时间,必须是60的倍数
|
||||
});
|
||||
if (res.code == 0) {
|
||||
currNum++;
|
||||
let { startTime } = vk.pubfn.getDayOffsetStartAndEnd(1, new Date());
|
||||
let second = vk.pubfn.toDecimal((startTime - Date.now()) / 1000, 0)
|
||||
await vk.globalDataCache.set(cacheKey, currNum, second);
|
||||
}
|
||||
// 业务逻辑结束-----------------------------------------------------------
|
||||
return res;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user