success(); } if (!RedisUtil::getInstance(RedisKeyEnum::SMS_MOBILE_CHECK, $mobile)->tryTimes($timeOut,$currentLimit)){ return $this->error('校验过于频繁,已被锁定!'); } if (!$info = self::query()->where(['mobile' => $mobile, 'event' => $event])->orderBy('id', 'desc')->first()) { return $this->error('验证码错误'); } if ($info->createtime < time() - 600) { $this->flush($mobile, $event); return $this->error('验证码已过期'); } if ($info->code != $code) { return $this->error('验证码错误!'); } return $this->success(); } /** * 发送短信 * @param string $mobile * @param $event * @param int $currentLimit * @param int $timeOut * @return bool * @throws \Exception */ public function send(string $mobile, $event = 'default', int $currentLimit = 5, int $timeOut = 300) { $code = rand(1000, 9999); if (!$this->create_code($mobile, $code, $event, $currentLimit, $timeOut)) { return $this->error($this->getMessage()); } // 第三方发送短信 return $this->success('发送成功', [ 'code' => $code ]); } /** * 创建验证码 * @param string $mobile * @param $code * @param $event * @param int $currentLimit * @param int $timeOut * @return bool * @throws \Exception */ private function create_code(string $mobile, $code, $event = 'default', int $currentLimit = 5, int $timeOut = 300) { $time = time(); //验证缓存,如存在则继续限制发送,时间设置 300s if (RedisUtil::getInstance(RedisKeyEnum::SEND_SMS_MOBILE, $mobile)->get()) { return $this->error('您的发送过于频繁!'); } //5分钟之内 次数超过5次,限制发送,并记录缓存 if (!RedisUtil::getInstance(RedisKeyEnum::SEND_SMS_TIMES, $mobile)->tryTimes($timeOut,$currentLimit)) { //每次锁定 递增 锁定时间,达到最大锁定次数则将当日无法发送 $end_time = Common::todayTimeRemain();//设置次日凌晨过期 if (!$times = RedisUtil::getInstance(RedisKeyEnum::SEND_SMS_TIMEOUT_TIMES, $mobile)->tryTimes($end_time, $currentLimit)) { $timeOut = $end_time;//如果达到最大锁定次数,则设置当日过期 } else { $timeOut = $times * $timeOut;//如果未达到最大次数,则依次递增锁定时间 // 如果最大次数过期时间 超过 当日时间,则直接设置当日过期 if ($timeOut > $end_time) { $timeOut = $end_time; } } RedisUtil::getInstance(RedisKeyEnum::SEND_SMS_MOBILE, $mobile)->setex('1', $timeOut); $minutes = $timeOut / 60; return $this->error("发送过于频繁,请{$minutes}分钟后再试"); } $this->flush($mobile, $event); $data = [ 'event' => $event, 'mobile' => $mobile, 'code' => $code, 'createtime' => $time ]; if (!self::query()->insert($data)) { return $this->error('发送失败'); } return $this->success('发送成功'); } /** * 清除短信 * @param $mobile * @param $event * @return bool */ public function flush($mobile, $event = 'default') { self::query()->where(['mobile' => $mobile, 'event' => $event])->delete(); return $this->success(); } }