whereNull('verified_at') ->delete(); $code = (string) random_int(100000, 999999); OtpCode::create([ 'identifier' => $identifier, 'code' => $code, 'expires_at' => Carbon::now()->addMinutes($expiryMinutes), ]); return $code; } /** * Verify the OTP code. */ public function verify(string $identifier, string $code): bool { $otp = OtpCode::where('identifier', $identifier) ->where('code', $code) ->whereNull('verified_at') ->where('expires_at', '>', Carbon::now()) ->latest() ->first(); if ($otp) { $otp->update(['verified_at' => Carbon::now()]); return true; } return false; } /** * Clear expired codes. */ public function cleanup(): void { OtpCode::where('expires_at', '<', Carbon::now()) ->whereNull('verified_at') ->delete(); } }