otpService = $otpService; } /** * OTP 入力フォームを表示 * * ログイン直後、ユーザーに6桁の OTP コードを入力させるページを表示します * メールアドレスはマスク表示(例:a***@example.com) */ public function show(Request $request) { /** @var Ope */ $user = $request->user(); // メールアドレスをマスク(最初の1文字のみ表示) $maskedEmail = $this->otpService->maskEmail($user->ope_mail); // 次の重発までの待機時間 $resendWaitSeconds = $this->otpService->getResendWaitSeconds($user); return view('auth.otp', [ 'maskedEmail' => $maskedEmail, 'resendWaitSeconds' => $resendWaitSeconds, ]); } /** * OTP コード検証 * * ユーザーが入力した6桁のコードを検証します * * 成功時:email_otp_verified_at を更新し、ホームページにリダイレクト * 失敗時:エラーメッセージと共に OTP 入力フォームに戻す */ public function verify(Request $request) { // 入力値を検証 $validated = $this->validate($request, [ 'code' => ['required', 'string', 'size:6', 'regex:/^\d{6}$/'], ], [ 'code.required' => 'OTPコードは必須です。', 'code.size' => 'OTPコードは6桁である必要があります。', 'code.regex' => 'OTPコードは6桁の数字である必要があります。', ]); /** @var Ope */ $user = $request->user(); // OTP コードを検証 if ($this->otpService->verify($user, $validated['code'])) { // 検証成功:ホームページにリダイレクト return redirect()->intended(route('home')) ->with('success', 'OTP認証が完了しました。'); } // 検証失敗:エラーメッセージと共に戻す return back() ->withInput() ->with('error', '無効なまたは有効期限切れのOTPコードです。'); } /** * OTP コード再送 * * ユーザーが OTP コード再送をリクエストした場合に実行 * 60秒以内の連続再送はブロックします */ public function resend(Request $request) { /** @var Ope */ $user = $request->user(); // 重発可能か確認 if (!$this->otpService->canResend($user)) { $waitSeconds = $this->otpService->getResendWaitSeconds($user); return back()->with('error', "後 {$waitSeconds} 秒待機してからリクエストしてください。"); } try { // 新しい OTP コードを発行 $otpCode = $this->otpService->issue($user); // ope_mail はセミコロン区切りで複数アドレスを保持する可能性があるため、最初のアドレスのみ抽出 $operatorEmails = explode(';', trim($user->ope_mail)); $primaryEmail = trim($operatorEmails[0] ?? $user->ope_mail); Log::info('OTP 再送メール送信開始: ' . $primaryEmail); // メール送信 Mail::to($primaryEmail)->send(new EmailOtpMail( $otpCode, $user->name ?? 'ユーザー' )); Log::info('OTP 再送メール送信完了: ' . $primaryEmail); return back()->with('success', 'OTPコードを再送信しました。'); } catch (\Exception $e) { Log::error('OTP resend error: ' . $e->getMessage(), [ 'exception' => $e, 'user_id' => $user->ope_id ?? null, 'user_email' => $user->ope_mail ?? null, ]); return back()->with('error', 'OTP送信に失敗しました。もう一度お試しください。'); } } }