Commit 503c751b by chenjinjing

no message

parent 281ce506
...@@ -18,4 +18,14 @@ ...@@ -18,4 +18,14 @@
<mysqlPwd>123456</mysqlPwd> <mysqlPwd>123456</mysqlPwd>
<dataBase>xuehui</dataBase> <dataBase>xuehui</dataBase>
</mysqldb> </mysqldb>
<!-- 短信相关配置 -->
<sms>
<sdkAppId>1400799515</sdkAppId>
<appKey>a36634bd106ee72eeea4a4bb4e62a03b</appKey>
<smsSign>会员注册</smsSign>
<!-- 填报提示 -->
<pointOut>1729286</pointOut>
<!-- 单位会员注册 -->
<unitMemberRegister>1729288</unitMemberRegister>
</sms>
</config> </config>
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* 会员逻辑 * 会员逻辑
*/ */
import { MEMBERSTATE, MEMBERLEVEL, DOCUMENTTYPE, NATION, PROFCATEGORY } from "../../config/enum"; import { MEMBERSTATE, MEMBERLEVEL, DOCUMENTTYPE, NATION, PROFCATEGORY, CODETYPE, UNITINFOTYPE, MEMBERTYPE, REGISTERFLOW } from "../../config/enum";
import { ERRORENUM } from "../../config/errorEnum"; import { ERRORENUM } from "../../config/errorEnum";
import { TABLEENUM } from "../../data/models/model"; import { TABLEENUM } from "../../data/models/model";
import { find, findOnce } from "../../data/select"; import { find, findOnce } from "../../data/select";
...@@ -10,7 +10,10 @@ import { updateOneData } from "../../data/update"; ...@@ -10,7 +10,10 @@ import { updateOneData } from "../../data/update";
import { generateSystemId, successResult } from "../../tools/system"; import { generateSystemId, successResult } from "../../tools/system";
import { BizError } from "../../util/bizError"; import { BizError } from "../../util/bizError";
import { extractData } from "../../util/piecemeal"; import { extractData } from "../../util/piecemeal";
import { changeEnumValue } from "../../util/verificationEnum"; import { changeEnumValue, eccEnumValue } from "../../util/verificationEnum";
import * as sysTools from "../../tools/system";
import { sendRegisterCode } from "../sms";
import { addOneData } from "../../data/add";
/** /**
...@@ -70,7 +73,6 @@ export async function unitMemberDetails({userId}) { ...@@ -70,7 +73,6 @@ export async function unitMemberDetails({userId}) {
} }
/** /**
* 单位会员 修改 * 单位会员 修改
* @param userId * @param userId
...@@ -81,12 +83,105 @@ export async function unitMemberUpdate(secureArgs:any) { ...@@ -81,12 +83,105 @@ export async function unitMemberUpdate(secureArgs:any) {
let {userId, form, keyanForm} = secureArgs; let {userId, form, keyanForm} = secureArgs;
let oldInfo = await findOnce(TABLEENUM.用户表, {userId}); let oldInfo = await findOnce(TABLEENUM.用户表, {userId});
if (!oldInfo || !oldInfo.userId) throw new BizError(ERRORENUM.目标数据不存在); if (!oldInfo || !oldInfo.userId) throw new BizError(ERRORENUM.目标数据不存在);
await updateOneData(TABLEENUM.用户表, {userId}, form); await updateOneData(TABLEENUM.用户表, {userId}, form);
let oldKeYanInfo = await find(TABLEENUM.单位所获得科研成果表, {userId});
let dataList = [];
oldKeYanInfo.forEach(info => {
let item:any = extractData(info, ["userId", "memberState", "unitName", "loginId", "phone", "joinTime", "unitMemberLevel", "sheng", "shi", "qu"]);
//todo 等夏先圣回来对一下前端数据怎么传
dataList.push(item);
});
return successResult(); return successResult();
} }
/**
* 单位入会流程1
* @param secureArgs
*/
export async function unitMemberRegister(secureArgs) {
let {form} = secureArgs;
/**校验枚举 */
const EccFuncName = '注册单位会员';
eccEnumValue(EccFuncName, '单位信息类型', UNITINFOTYPE, form.unitInfoType);
let oldData = await findOnce(TABLEENUM.用户表, {"$or":[{loginId:form.loginId}, {phone:form.phone}, {mail:form.mail}] });
if (oldData && oldData.userId) {
if (oldData.loginId == form.loginId) throw new BizError(ERRORENUM.用户名重复, form.loginId );
if (oldData.phone == form.phone) throw new BizError(ERRORENUM.联系人手机号重复, form.phone );
if (oldData.mail == form.mail) throw new BizError(ERRORENUM.邮箱重复, form.loginId );
}
/**校验密码 */
if (form.pwd.search(/^[A-Za-z0-9]{6,18}$/) < 0) throw new BizError(ERRORENUM.密码只能由618位字符和数字组成);
if (form.pwd != form.confirmation) throw new BizError(ERRORENUM.两次密码不一致);
delete form.confirmation;
form.userId = sysTools.generateUserId();
form.memberType = MEMBERTYPE.单位会员;
form.isAdmin = 0;
form.registerFlow = REGISTERFLOW.单位会员注册1;
await addOneData(TABLEENUM.用户表, form);
/**验证码 */
let todayMs = sysTools.getTodayMs();
let todayCodeList = await findOnce(TABLEENUM.验证码表, {userId:form.userId});
if (todayCodeList.length >= 4) throw new BizError(ERRORENUM.发送验证码次数超限制, `${form.userId} 修改密码发送验证码次数超限制4`);
let sendMs = todayMs;
todayCodeList.forEach(info => {
sendMs = Math.max(sendMs, info.sendMs);
});
let now = new Date().valueOf();
if ((now - sendMs) <= (60 * 1000) ) throw new BizError(ERRORENUM.发送验证码频率过快, `${form.userId}`);
let codeId = sysTools.getSMSCodeId(form.userId, todayCodeList.length);
let code = sysTools.getSMSCode();
await sendRegisterCode(form.phone, code);
now = new Date().valueOf();
await addOneData(TABLEENUM.验证码表, {codeId, code, now, phone:form.phone, codeType:CODETYPE.单位会员注册, isUse:true});
return successResult();
}
...@@ -163,6 +258,21 @@ export async function individualMemberDetails({userId}) { ...@@ -163,6 +258,21 @@ export async function individualMemberDetails({userId}) {
} }
/**
* 个人会员 修改
* @param userId
* @param form
* @returns
*/
export async function individualMemberUpdate(secureArgs:any) {
let {userId, form, keyanForm} = secureArgs;
let oldInfo = await findOnce(TABLEENUM.用户表, {userId});
if (!oldInfo || !oldInfo.userId) throw new BizError(ERRORENUM.目标数据不存在);
await updateOneData(TABLEENUM.用户表, {userId}, form);
return successResult();
}
......
/**
* 短信主要逻辑
*/
const tencentcloud = require("tencentcloud-sdk-nodejs");
const smsClient = tencentcloud.sms.v20210111.Client;
import { SMSTYPE } from "../config/enum";
import { ERRORENUM } from "../config/errorEnum";
import { systemConfig } from "../config/serverConfig";
import { BizError } from "../util/bizError";
var client;
export function initSMS() {
client = new smsClient({
credential: {
/* 必填:腾讯云账户密钥对secretId,secretKey。
* 这里采用的是从环境变量读取的方式,需要在环境变量中先设置这两个值。
* 你也可以直接在代码中写死密钥对,但是小心不要将代码复制、上传或者分享给他人,
* 以免泄露密钥对危及你的财产安全。
* SecretId、SecretKey 查询: https://console.cloud.tencent.com/cam/capi */
secretId: "AKIDHUYO0Xq0wc1DD2e1CJ1xpuqYIxQo0yrd",
secretKey: "zl01oOkswmXJ4apnaUJsCW5PivudLtFP",
},
/* 必填:地域信息,可以直接填写字符串ap-guangzhou,支持的地域列表参考 https://cloud.tencent.com/document/api/382/52071#.E5.9C.B0.E5.9F.9F.E5.88.97.E8.A1.A8 */
region: "ap-guangzhou",
/* 非必填:
* 客户端配置对象,可以指定超时时间等配置 */
profile: {
/* SDK默认用TC3-HMAC-SHA256进行签名,非必要请不要修改这个字段 */
signMethod: "HmacSHA256",
httpProfile: {
/* SDK默认使用POST方法。
* 如果你一定要使用GET方法,可以在这里设置。GET方法无法处理一些较大的请求 */
reqMethod: "POST",
/* SDK有默认的超时时间,非必要请不要进行调整
* 如有需要请在代码中查阅以获取最新的默认值 */
reqTimeout: 30,
/**
* 指定接入地域域名,默认就近地域接入域名为 sms.tencentcloudapi.com ,也支持指定地域域名访问,例如广州地域的域名为 sms.ap-guangzhou.tencentcloudapi.com
*/
endpoint: "sms.tencentcloudapi.com"
},
},
})
}
/**
* 给特定账号发送信息
* @param phone 需要发送的电话数组
* @param type 类别
* @param params 参数数组
*/
function sendMsmToPhoneNumber(phone, type:number, params) {
let phoneAreaList = [];
phone.forEach(info => {
phoneAreaList.push(`+86${info}`);
});
let templateId = -1;
if (type == SMSTYPE.单位会员注册) templateId = systemConfig.smsUnitMemberRegister;
const sendParam = {
/* 短信应用ID: 短信SmsSdkAppId在 [短信控制台] 添加应用后生成的实际SmsSdkAppId,示例如1400006666 */
// 应用 ID 可前往 [短信控制台](https://console.cloud.tencent.com/smsv2/app-manage) 查看
SmsSdkAppId: systemConfig.smsSDKId,
/* 短信签名内容: 使用 UTF-8 编码,必须填写已审核通过的签名 */
// 签名信息可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-sign) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-sign) 的签名管理查看
SignName: systemConfig.smsSign,
/* 模板 ID: 必须填写已审核通过的模板 ID */
// 模板 ID 可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-template) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-template) 的正文模板管理查看
TemplateId: templateId,
/* 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致,若无模板参数,则设置为空 */
TemplateParamSet: params,
/* 下发手机号码,采用 e.164 标准,+[国家或地区码][手机号]
/* 用户的 session 内容(无需要可忽略): 可以携带用户侧 ID 等上下文信息,server 会原样返回 */
SessionContext: "",
PhoneNumberSet: phoneAreaList,
/* 短信码号扩展号(无需要可忽略): 默认未开通,如需开通请联系 [腾讯云短信小助手] */
ExtendCode: "",
/* 国际/港澳台短信 senderid(无需要可忽略): 国内短信填空,默认未开通,如需开通请联系 [腾讯云短信小助手] */
SenderId: "",
}
return new Promise( (resolve, reject) => {
client.SendSms(sendParam, function (err, response) {
let isError = false;
let msg = "";
if (err) {
msg = err;
isError = true;
}
resolve({isError, msg});
});
})
}
/**
* 发送单位会员注册的短信验证码
* @param phone
* @param code
*/
export async function sendRegisterCode(phone:string, code:string) {
let sendPhoneList = [phone];
let params = [code];
let sendRes:any = await sendMsmToPhoneNumber(sendPhoneList, SMSTYPE.单位会员注册, params);
return sendRes.isError;
}
...@@ -353,4 +353,30 @@ export enum CERTIFICATETYPE { ...@@ -353,4 +353,30 @@ export enum CERTIFICATETYPE {
} }
/**
* 验证码类型
*/
export enum CODETYPE {
单位会员注册 = 1,
}
/**
* 短信类型
*/
export enum SMSTYPE {
单位会员注册 = 1,
信息填报提醒,
}
/**
* 会员注册流程
*/
export enum REGISTERFLOW {
单位会员注册1 = 1,
单位会员注册2,
单位会员注册3
}
...@@ -19,7 +19,9 @@ export enum ERRORENUM { ...@@ -19,7 +19,9 @@ export enum ERRORENUM {
联系人手机号重复, 联系人手机号重复,
邮箱重复, 邮箱重复,
两次密码不一致, 两次密码不一致,
密码只能由618位字符和数字组成 密码只能由618位字符和数字组成,
发送验证码次数超限制,
发送验证码频率过快
} }
export enum ERRORCODEENUM { export enum ERRORCODEENUM {
......
...@@ -14,5 +14,10 @@ export class ServerConfig { ...@@ -14,5 +14,10 @@ export class ServerConfig {
user:string, user:string,
pwd:string, pwd:string,
dataBase:string dataBase:string
} };
/**短信相关配置 */
smsSDKId:number;
smsAppKey:string;
smsSign:string;
smsUnitMemberRegister:number;
} }
\ No newline at end of file
...@@ -84,6 +84,7 @@ enum TABLEENUM { ...@@ -84,6 +84,7 @@ enum TABLEENUM {
文字资料 = 'wenZiZiLiao', 文字资料 = 'wenZiZiLiao',
订单表 = 'order', 订单表 = 'order',
单位所获得科研成果表 = " scientificResearch", 单位所获得科研成果表 = " scientificResearch",
验证码表 = "code",
} }
const ModelArray = [ const ModelArray = [
...@@ -348,11 +349,12 @@ const ModelArray = [ ...@@ -348,11 +349,12 @@ const ModelArray = [
shi:'String',//市 shi:'String',//市
qu:'String',//区 qu:'String',//区
addres:'String',//通信地址 addres:'String',//通信地址
photoUrl:'String',//证件照图片地址 photoUrl:'String',//证件照图片地址 蓝底证件照
workUnit:'String',//工作单位 workUnit:'String',//工作单位
workDuties:'String',//职务 workDuties:'String',//职务
workTitle:'String',//职称 workTitle:'String',//职称
userRegisterState:{type:'Number', default:USERREGISTERSTATE.待审核, index:true},//用户注册状态 枚举 userRegisterState:{type:'Number', default:USERREGISTERSTATE.待审核, index:true},//用户注册状态 枚举
registerFlow:'Number',//会员注册流程 枚举
auditTime:'Number',//审核时间 auditTime:'Number',//审核时间
memberState:{type:'Number', default:MEMBERSTATE.正常, index:true},//会员状态 枚举 memberState:{type:'Number', default:MEMBERSTATE.正常, index:true},//会员状态 枚举
joinTime:'Number',//入会时间 joinTime:'Number',//入会时间
...@@ -377,7 +379,7 @@ const ModelArray = [ ...@@ -377,7 +379,7 @@ const ModelArray = [
personInChargeDesc:'String',//单位主要负责人或负责人集体描述 personInChargeDesc:'String',//单位主要负责人或负责人集体描述
/**单位会员信息 */ /**单位会员信息 */
unitInfoType:'Number',//单位信息类型 枚举 unitInfoType:'Number',//单位信息类型 枚举‘ ’
yuanXiaoBanXueLeiXing:'String',//院校办学类型 yuanXiaoBanXueLeiXing:'String',//院校办学类型
yuanXiaoZhuGuanBuMen:'String',//院校主管部门 yuanXiaoZhuGuanBuMen:'String',//院校主管部门
yuanXiaoFuZeRen:'String',//院校主要负责人 yuanXiaoFuZeRen:'String',//院校主要负责人
...@@ -439,6 +441,18 @@ const ModelArray = [ ...@@ -439,6 +441,18 @@ const ModelArray = [
} }
}, },
{
tableName:TABLEENUM.验证码表,
source:TABLESOURCEENUM.mongo,
schema:{
codeId:{type:'String', index:true},
code:String,
sendMs:Number,//下发时间 时间戳
phone:{type:String, index:true},//用户电话
type:Number,//验证码类型
isUse:{type:Boolean, default:false},//是否使用 默认false
}
},
]; ];
......
...@@ -39,4 +39,39 @@ export function generateToken(userId:string) { ...@@ -39,4 +39,39 @@ export function generateToken(userId:string) {
*/ */
export function generateUserId() { export function generateUserId() {
return md5(`${Math.random() * 100}${new Date().valueOf()}${Math.random() * 10000}`); return md5(`${Math.random() * 100}${new Date().valueOf()}${Math.random() * 10000}`);
} }
\ No newline at end of file
/**
* 获取code的id
* @param userId 用户Id
* @param todaySendCount 今日发送次数
* @returns ''
*/
export function getSMSCodeId(userId:string, todaySendCount:number) {
return md5(`${userId}${todaySendCount}${new Date().valueOf()}`);
}
/**
* 获取一个随机6位数的验证码
* @returns
*/
export function getSMSCode() {
let code = ``;
for (let i =0; i < 6; i++) {
code += Math.floor(Math.random() * 10)
}
return code;
}
/**
* 获取今天开始时刻的时间戳 0时0分
* @returns
*/
export function getTodayMs() {
let t =`${ moment().format("YYYY-MM-DD")} 00:00:00`;
return new Date(t).valueOf();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment