*/ private array $endpoints = [ 'payone' => 'https://api.pay1.de/post-gateway/', ]; public function handle(): int { Log::channel('payment')->info('COMMAND [payment:check-uptime] started.'); foreach ($this->endpoints as $provider => $url) { $this->checkProvider($provider, $url); } Log::channel('payment')->info('COMMAND [payment:check-uptime] finished.'); return self::SUCCESS; } private function checkProvider(string $provider, string $url): void { $startMs = now()->valueOf(); try { $response = Http::timeout(10)->head($url); $responseTimeMs = now()->valueOf() - $startMs; $isUp = $response->successful() || $response->status() < 500; $errorMessage = $isUp ? null : 'HTTP '.$response->status(); } catch (\Exception $e) { $responseTimeMs = now()->valueOf() - $startMs; $isUp = false; $errorMessage = $e->getMessage(); } ProviderUptimeLog::create([ 'provider' => $provider, 'is_up' => $isUp, 'response_time_ms' => (int) $responseTimeMs, 'error_message' => $errorMessage, 'checked_at' => now(), ]); $status = $isUp ? 'UP' : 'DOWN'; $this->line("[{$provider}] {$status} ({$responseTimeMs}ms)"); Log::channel('payment')->info("[payment:check-uptime] {$provider} {$status}", [ 'response_time_ms' => $responseTimeMs, 'error_message' => $errorMessage, ]); if (! $isUp) { $this->handleOutage($provider, $errorMessage); } else { $this->handleRecovery($provider); } } private function handleOutage(string $provider, ?string $errorMessage): void { $incident = PaymentIncident::firstOrCreate( [ 'provider' => $provider, 'type' => 'outage', 'status' => 'open', ], [ 'title' => 'Automatisch: '.strtoupper($provider).' nicht erreichbar', 'description' => 'Uptime-Check hat einen Ausfall erkannt.', 'severity' => 'critical', 'detected_at' => now()->startOfHour(), ] ); IncidentActivity::create([ 'incident_id' => $incident->id, 'type' => 'note', 'title' => 'Uptime-Check: '.strtoupper($provider).' DOWN', 'content' => $errorMessage, 'author' => 'System', ]); Log::channel('payment')->error("[payment:check-uptime] Outage-Incident #{$incident->id} für {$provider}."); } private function handleRecovery(string $provider): void { $openOutages = PaymentIncident::where('provider', $provider) ->where('type', 'outage') ->whereIn('status', ['open', 'in_progress']) ->get(); foreach ($openOutages as $incident) { $incident->update([ 'status' => 'resolved', 'resolved_at' => now(), ]); IncidentActivity::create([ 'incident_id' => $incident->id, 'type' => 'status_change', 'title' => 'Automatisch aufgelöst: '.strtoupper($provider).' ist wieder erreichbar', 'author' => 'System', ]); Log::channel('payment')->info("[payment:check-uptime] Incident #{$incident->id} für {$provider} automatisch aufgelöst."); } } }