1、本文借鉴的是[https://www.cnblogs.com/blogforly/p/5841811.html]
(https://www.cnblogs.com/blogforly/p/5841811.html)
2、监听一个手机号一天只能发送6次验证码。
时间间隔为:第一次发送验证码后,间隔1分钟之后可以重发。第二次发送验证码后,间隔5分钟之后可以重发。第三次发送验证码后,间隔10分钟之后可以重发。第四次发送验证后,间隔20分钟后可以重发。第五次发送验证码后,间隔30分钟后可以重发。第六次发送验证后,间隔24小时后可以重发。
3、思路:每一天,在项目的指定路径下,写一个文件,该文件记录所有当天发送了验证码的手机号。在每一次用户发送验证码时,从该文件取出用户手机号在该文件夹下,存在几次记录,做相应的处理。
代码如下:
<?php
namespace app\home\model\v2;
use think\Exception;
/**
* 记录当前用户,当天请求了多少次验证码接口
* Class ReMod
* @package app\home\controller\v2
*/
class ReMod
{
//定义全局变量,用于设置记录文件的路径
protected $Root = null;
public function __construct()
{
$this->Root = "data/msg_logs/";//自己定义的文件存放位置 /public/data/msg_logs 路径
}
//检测Tel在文件中出现的次数
public function checkTel($data)
{
$fileName = "Tel_" . date("Ymd", time()) . ".dat";
$filePath = ($this->Root) . $fileName;
$c_sum = 0;
if (file_exists($filePath)) {
$arr = file_get_contents($filePath);
$row = explode("|", $arr);
//如果当前文件中,有当前手机号
if(in_array($data,$row)){
//计算每一个value有多少个,并且将value当键,将多少个当值,组成一个新的数组
$countArr = array_count_values($row);
//查询当前手机号的对应的值
$c_sum = $countArr[$data];
if ($c_sum < 6) {
$this->wirteFile($filePath, $data . "|");
}
return $c_sum;
}else{
$this->wirteFile($filePath, $data . "|");
return $c_sum;
}
} else {
$this->wirteFile($filePath, $data . "|");
return $c_sum;
}
}
/**
* 105 * 将数据写入本地文件
* 106 * @param string $filePath 要写入文件的路径
* 107 * @param string $data 写入的数据
* 108 */
public function wirteFile($filePath, $data)
{
try {
if (!is_dir($this->Root)) {//判断文件所在目录是否存在,不存在就创建
mkdir($this->Root, 0777, true);
}
if ($filePath == "") {//此处是不发送验证码时,记录日志创建的文件
$filePath = ($this->Root) . "N" . date("Ymd", time()) . ".dat";
}
//写入文件操作
$fp = fopen($filePath, "a+");//得到指针
fwrite($fp, $data);//写
fclose($fp);//关闭
} catch (Exception $e) {
print $e->getMessage();
}
}
}
在发送验证码接口,添加一个方法
public function actionSendSms(Request $request)
{
(new MobileVaildate())->apiCheck();
$param = $request->only(['mobile', 'time', 'sign']);
//验证验签
Safe::vaildateSign($param);
//电话
$tel = $param['mobile'];
//判断当前用户的手机号今日发送了几次请求
$tel_num = (new ReMod)->checkTel($tel);
$JUid = Cache::get('JU_ID_CODE');
//从redis中获取下一次最早发送验证码的时间
$redis = new RedisPro();
$time = $redis->get($param['mobile'] . 'login_code' . 'time');
//当缓存中不存在这个时间点,并且当前小于这个时间点,则给出提示
if ($time !== false && time() < $time) {
return reply(10500, '请于' . date('Y-m-d H:i:s', $time) . '之后发送!');
}
//判断手机号 如果是当天第 1 次发送 则 1 分钟之后发送
if ($tel_num == 0) {
// dump('今天第一次进来');
(new Send())->sendMessage($param['mobile'], $JUid, 'login_code', 1 * 60);
// 如果是当天第 2 次发送 则 5 分钟之后发送
} else if ($tel_num == 1) {
// dump('今天第2次进来');
(new Send())->sendMessage($param['mobile'], $JUid, 'login_code', 5 * 60);
// 如果是当天第 3 次发送 则 10 分钟之后发送
} else if ($tel_num == 2) {
// dump('今天第3次进来');
(new Send())->sendMessage($param['mobile'], $JUid, 'login_code', 10 * 60);
// 如果是当天第 4 次发送 则 20 分钟之后发送
} else if ($tel_num == 3) {
// dump('今天第4次进来');
(new Send())->sendMessage($param['mobile'], $JUid, 'login_code', 20 * 60);
// 如果是当天第 5 次发送 则 30 分钟之后发送
} else if ($tel_num == 4) {
// dump('今天第5次进来');
(new Send())->sendMessage($param['mobile'], $JUid, 'login_code', 30 * 60);
// 如果是当天第 6 次发送 则 24小时之后发送
} else if ($tel_num == 5) {
// dump('今天第6次进来');
(new Send())->sendMessage($param['mobile'], $JUid, 'login_code', 24 * 60 * 60);
} else if ($tel_num > 5) {
// dump('今天第7次或以上进来');
//当不发送验证码时,将数据存入文件,用于方便查询
// $data = $tel . "|";
// if ($tel_num > 5) {
// $data = $data . "B@";
// }
// (new ReMod)->wirteFile("", $data);
return reply(10501, '您今日获取短信验证码的次数已达到6次,请明日再试!');//给用户返回信息
}
return reply(10200, '短信验证码发送成功');
}