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; } }