123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- <?php
- declare(strict_types=1);
- namespace App\Model\Arts;
- use App\Master\Enum\RedisKeyEnum;
- use App\Master\Framework\Library\AliCloud\AliSms;
- use App\Master\Framework\Library\Twilio\Sms;
- use App\Model\Model;
- use App\Utils\Common;
- use App\Utils\RedisUtil;
- use function Hyperf\Coroutine\co;
- class SmsCodeModel extends Model
- {
- /**
- * The table associated with the model.
- *
- * @var ?string
- */
- protected ?string $table = 'sms';
- protected ?string $dateFormat = 'U';
- public bool $timestamps = false;
- protected int $is_status_search = 1;// 默认使用 status = 1 筛选
- protected int $is_delete_search = 1;// 默认使用 is_delete = 0 筛选
- /**
- * 默认查询字段
- *
- * @var array|string[]
- */
- public array $select = [
- '*'
- ];
- /**
- * 验证码
- * @param $mobile
- * @param $code
- * @param string $event
- * @return bool
- */
- public function check($mobile, $code, string $event = 'default', int $currentLimit = 5, int $timeOut = 300)
- {
- // 测试验证码
- if ($code == 1212) {
- return $this->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();
- }
- }
|