| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- <?php
- namespace App\Module\Sms\Services;
- use App\Module\Sms\Enums\Code;
- use App\Module\Sms\Enums\CODE_TYPE;
- use App\Module\Sms\Gateway\MyGateway;
- use App\Module\Sms\Models\SmsCode;
- use App\Module\System\Services\Config;
- use Carbon\Carbon;
- use Overtrue\EasySms\EasySms;
- use Overtrue\EasySms\Exceptions\InvalidArgumentException;
- use Overtrue\EasySms\Exceptions\NoGatewayAvailableException;
- use UCore\Exception\LogicException;
- use UCore\Helper\Logger;
- /**
- * 短信服务类
- */
- class SmsService
- {
- /**
- * 验证码有效期(秒)
- */
- public const CODE_EXPIRE_TIME = 600;
- /**
- * @var EasySms
- */
- protected $easySms;
- /**
- * 构造函数
- */
- public function __construct()
- {
- $this->initEasySms();
- }
- /**
- * 初始化 EasySms 实例
- */
- protected function initEasySms(): void
- {
- // 获取短信配置
- $list = \App\Module\System\Services\ConfigService::getByGroup("短信配置");
- $gateways = [];
- $gatewayConfigs = [];
- foreach ($list as $item) {
- if($item['is_open']){
- $gateways[] = $item['driver'];
- $gatewayConfigs[$item['driver']] = $item;
- }
- }
- // 获取基础配置
- $config = config('easysms');
- $config['default']['gateways'] = $gateways;
- $config['gateways'] = $gatewayConfigs;
- // 创建实例
- $this->easySms = new EasySms($config);
- // 注册自定义网关
- $this->easySms->extend('mygateway', function ($gatewayConfig) {
- return new MyGateway($gatewayConfig);
- });
- }
- /**
- * 发送验证码
- *
- * @param CODE_TYPE $type 验证码类型
- * @param string $phone 手机号
- * @param string $token 令牌
- * @return bool
- * @throws LogicException
- * @throws InvalidArgumentException
- */
- public function sendCode(CODE_TYPE $type, string $phone, string $token): bool
- {
- // 验证类型
- if (!Code::isValid($type)) {
- throw new LogicException('不存在的验证码类型');
- }
- // 生成验证码
- $code = mt_rand(100000, 999999);
- // 获取消息类
- $messageClass = Code::getTemplateClass($type);
- if (!$messageClass) {
- throw new LogicException('未找到对应的消息模板');
- }
- try {
- // 发送短信
- $result = $this->easySms->send($phone, new $messageClass([
- 'code' => $code,
- 'phone' => $phone
- ]));
- // 记录日志
- Logger::debug('sms.send', $result);
- // 保存验证码
- $smsCode = new SmsCode();
- $smsCode->mobile = $phone;
- $smsCode->token = $token;
- $smsCode->code_value = $code;
- $smsCode->type = $type->value;
- $smsCode->save();
- return true;
- } catch (NoGatewayAvailableException $e) {
- // 记录错误日志
- Logger::error('sms.error', [
- 'message' => $e->getLastException()->getMessage(),
- 'trace' => $e->getLastException()->getTraceAsString()
- ]);
- throw new LogicException('短信发送失败');
- }
- }
- /**
- * 验证短信验证码
- *
- * @param CODE_TYPE|int $type 验证码类型
- * @param string $phone 手机号
- * @param string $code 验证码
- * @return bool
- */
- public function verifyCode(CODE_TYPE|int $type, string $phone, string $code): bool
- {
- if (empty($phone) || empty($code)) {
- return false;
- }
- $typeValue = $type instanceof CODE_TYPE ? $type->value : $type;
- // 获取最新的验证码记录
- $smsCode = SmsCode::query()
- ->where('mobile', $phone)
- ->where('type', $typeValue)
- ->orderByDesc('id')
- ->first();
- if (!$smsCode) {
- return false;
- }
- // 检查验证码是否过期
- if ($smsCode->created_at->lt(Carbon::now()->subSeconds(self::CODE_EXPIRE_TIME))) {
- $smsCode->forceDelete();
- return false;
- }
- // 验证码匹配检查
- if ($smsCode->code_value === $code) {
- $smsCode->forceDelete();
- return true;
- }
- return false;
- }
- }
|