SmsCodeModel.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Model\Arts;
  4. use App\Master\Enum\RedisKeyEnum;
  5. use App\Master\Framework\Library\AliCloud\AliSms;
  6. use App\Master\Framework\Library\Twilio\Sms;
  7. use App\Model\Model;
  8. use App\Utils\Common;
  9. use App\Utils\RedisUtil;
  10. class SmsCodeModel extends Model
  11. {
  12. /**
  13. * The table associated with the model.
  14. *
  15. * @var ?string
  16. */
  17. protected ?string $table = 'sms_code';
  18. protected ?string $dateFormat = 'U';
  19. public bool $timestamps = false;
  20. protected int $is_status_search = 1;// 默认使用 status = 1 筛选
  21. protected int $is_delete_search = 1;// 默认使用 is_delete = 0 筛选
  22. /**
  23. * 默认查询字段
  24. *
  25. * @var array|string[]
  26. */
  27. public array $select = [
  28. '*'
  29. ];
  30. /**
  31. * 验证码
  32. * @param $phone
  33. * @param $code
  34. * @return array
  35. */
  36. public static function AuthCode($phone, $code): array
  37. {
  38. if ($code == 1212){
  39. return ['code' => 200, 'msg' => 'success'];
  40. }
  41. $code = self::query()->where('phone', $phone)->where('code', $code)->where('status', 1)->where('is_delete', 0)->first();
  42. if (!$code) return ['code' => 201, 'msg' => '验证码错误'];
  43. if ($code->created_at < time() - 600) return ['code' => 201, 'msg' => '验证码已过期'];
  44. $code->status = 2;
  45. $code->updated_at = time();
  46. $code->save();
  47. return ['code' => 200, 'msg' => 'success'];
  48. }
  49. /**
  50. * 记录验证码
  51. * @param string $phone
  52. * @param int $code
  53. * @param int $currentLimit 限制次数
  54. * @param int $timeOut 限制时间
  55. * @return array
  56. */
  57. public static function CreateCode(string $phone, int $code, int $currentLimit = 5, int $timeOut = 300): array
  58. {
  59. $time = time();
  60. $times = self::query()->where('phone', $phone)->whereBetween('created_at', [$time - $timeOut, $time])->count();
  61. //验证缓存,如存在则继续限制发送,时间设置 300s
  62. if (RedisUtil::getInstance(RedisKeyEnum::SEND_SMS_MOBILE, $phone)->get()) {
  63. return ['code' => 201, 'msg' => '您的发送过于频繁!'];
  64. }
  65. //5分钟之内 次数超过5次,限制发送,并记录缓存
  66. if ($times > $currentLimit) {
  67. //每次锁定 递增 锁定时间,达到最大锁定次数则将当日无法发送
  68. $end_time = Common::todayTimeRemain();//设置次日凌晨过期
  69. if (!$times = RedisUtil::getInstance(RedisKeyEnum::SEND_SMS_TIMEOUT_TIMES, $phone)->tryTimes($end_time, $currentLimit)) {
  70. $timeOut = $end_time;//如果达到最大锁定次数,则设置当日过期
  71. } else {
  72. $timeOut = $times * $timeOut;//如果未达到最大次数,则依次递增锁定时间
  73. // 如果最大次数过期时间 超过 当日时间,则直接设置当日过期
  74. if ($timeOut > $end_time) {
  75. $timeOut = $end_time;
  76. }
  77. }
  78. RedisUtil::getInstance(RedisKeyEnum::SEND_SMS_MOBILE, $phone)->setex('1',$timeOut);
  79. $minutes = $timeOut / 60;
  80. return ['code' => 201, 'msg' => "发送过于频繁,请{$minutes}分钟后再试"];
  81. }
  82. $code = self::query()->insert([
  83. 'phone' => $phone,
  84. 'code' => $code,
  85. 'status' => 1,
  86. 'created_at' => time(),
  87. 'updated_at' => time(),
  88. ]);
  89. if (!$code) return ['code' => 201, 'msg' => '发送失败'];
  90. return ['code' => 200, 'msg' => 'success'];
  91. }
  92. /**
  93. * 发送短信
  94. * @param string $phone
  95. * @param int $code
  96. * @return bool
  97. * @throws \Twilio\Exceptions\ConfigurationException
  98. * @throws \Twilio\Exceptions\TwilioException
  99. */
  100. public function send(string $phone, int $code, string $area_code = '+86')
  101. {
  102. if ($area_code == '+86'){
  103. $sms = new AliSms();
  104. if (!$sms->send($phone,['code' => $code])){
  105. return $this->error($sms->getMessage() ?? '发送失败',$sms->getData());
  106. }
  107. }else{
  108. // 国外短信
  109. $text = "【好滴用车】验证码:{$code},您正在使用好滴用车,此验证码10分钟内有效。";
  110. $sms = new Sms();
  111. if (!$sms->send("{$area_code}{$phone}",$text)){
  112. return $this->error($sms->getMessage() ?? '发送失败');
  113. }
  114. }
  115. return $this->success('发送成功',$sms->getData());
  116. }
  117. }