简介:使用nodejs接入封装第三方短信验证码工具类
-
第三方短信运营商接入
- 安装axios
yarn add axios@1.1.3
- 安装axios
-
配置
- 在项目的config文件夹新建一个文件,命名为接入短信验证码平台的名字,例如aliyunMessage.js,具体配置如下
const axios = require('axios') const sendMsgCode = (phone,randomCode) => { return axios({ method:'post', url:`http(s)://jmsms.market.alicloudapi.com/sms/send`, //短信验证码平台接入的url data:{ appid:'ATB3w4hJl7xqs9P2ty', //appid可以在开通的短信验证码平台控制台即可查到 appSecret:'J5ByBB287o1Cipvc01U2eOgV0diXYuT8', // appSecret可以在开通的短信验证码平台控制台即可查到 code:randomCode, //要发送的随机数,需要自己定义 phoneNum:phone, // 接收短信验证码的手机号 templateCode: "SMS_168781429" // 额外的参数,需要结合短信验证码平台来编写,如不需要去掉即可 } }) } // 测试调试发送短信 (async()=>{ console.log((await sendMsgCode(13800138000,'5201')).data); })() // 进行导出 module.exports = sendMsgCode;
- 在项目的config文件夹新建一个文件,命名为接入短信验证码平台的名字,例如aliyunMessage.js,具体配置如下
-
随机生成四位数封装(路径:utils/randomTool.js)
class RandomTool{ static randomCode(){ return Math.floor(Math.random()*(9999-1000)+1000) } } module.exports = RandomTool
-
数据层代码逻辑
- 优化方案(方案二)
- 必须保证两个redis操作的原子性:事务具有原子性指的是,数据库将事务中的多个操作当作一个整体来执行,服务器要么就执行事务中的所有操作,要么就一个操作也不执行。
- 同时减少命名空间的浪费
// 获取手机验证码逻辑处理 sendCode: async (phone,captcha,type,key,randomCode) =>{ // 60秒内不能重新获取 // ------>方案一 // if(await redisConfig.exists(`${type}:over:`+phone)) { // return { code: -1, msg: '60秒内不能重复获取'} // } // ------->方案二 if(await redisConfig.exists(`${type}:code:`+phone)){ let dateRedis = dayjs(Number((await redisConfig.get(`${type}:code:`+phone)).split('_')[0])) if(dayjs(Date.now()).diff(dateRedis,'second')<=60) { return {code:-1,msg:'60秒内不能重复获取'} } } // 是否已经填写图形验证码 if (!(await redisConfig.exists(`${type}:captcha:`+key))) { return { code: -1, msg: '请发送图形验证码' } } // 对比用户的图形验证码和redis缓存中的是否一致 let captchaRedis = await redisConfig.get(`${type}:captcha:`+key) if(!(captcha.toLowerCase() === captchaRedis.toLowerCase())) { return { code: -1,msg:'图形验证码填写错误'} } // 发送手机验证码 let CodeRes = (await aliyunMessage(phone,randomCode)).data // ------->方案一 // // 验证码存入redis // redisConfig.set(`${type}:code`+phone,randomCode,600) // // 存60秒判断 // redisConfig.set(`${type}:over:`+phone,'1',60) // ------->方案二 // 获取当前时间拼接验证码 let randomCodeTime = `${Date.now()}_${randomCode}` redisConfig.set(`${type}:code:`+phone,randomCodeTime,600) // 删除图形验证码 redisConfig.del(`${type}:captcha:`+key) if(CodeRes.code == 0) return {code:0,msg:'验证码发送成功'} else {return {code:-1,msg:'验证码发送失败'}} }
- 优化方案(方案二)
-
对用户的ip和设备进行md5加密,文件路径:controller/NotifyController.js
const NotifyService = require('../service/NotifyService') const GetUserInfoTool = require('../utils/GetUserInfoTool') const SecretTool = require('../utils/SecretTool') const randomTool = require('../utils/randomTool') const NotifyController = { sendCode: async(req,res)=>{ let {phone,captcha,type} = req.body; // 用户的ip+设备md5加密 let _key = SecretTool.md5(GetUserInfoTool.getIp(req)+GetUserInfoTool.getUserAgent(req)) let handleRes = await NotifyService.sendCode(phone,captcha,type,_key,randomTool.randomCode()) res.send(handleRes) } } module.exports = NotifyController
-
在router文件夹里面编写接口路径,以及调用的方法
const express = require('express') const router = express.Router() const NotifyController = require('../controller/NotifyController') // 图形验证码接口 router.get('/captcha',NotifyController.captcha) // 手机验证码接口 router.post('/sendCode',NotifyController.sendCode) module.exports = router
-
大功告成,可以在apifox上进行调用,需要先请求图形验证码接口,图形验证码如何编写可以看我以往的文章
-
手机上也收到了对应的短信验证码