active() ->get() ->filter(fn (IhWebhookEndpoint $endpoint) => $endpoint->listensTo($eventName)); $delivered = 0; foreach ($endpoints as $endpoint) { if ($this->deliver($endpoint, $eventName, $payload)) { $delivered++; } } return $delivered; } public function deliver(IhWebhookEndpoint $endpoint, string $eventName, array $payload): bool { $body = [ 'event' => $eventName, 'timestamp' => now()->toIso8601String(), 'business_id' => $endpoint->business_id, 'data' => $payload, ]; $delivery = IhWebhookDelivery::create([ 'endpoint_id' => $endpoint->id, 'event_name' => $eventName, 'payload' => $body, 'status' => 'pending', ]); try { $request = Http::timeout((int) config('integrationhub.webhook.timeout_seconds', 15)) ->acceptJson() ->asJson(); if (! empty($endpoint->secret)) { $signature = hash_hmac('sha256', json_encode($body), $endpoint->secret); $request = $request->withHeaders([ 'X-IntegrationHub-Signature' => $signature, 'X-IntegrationHub-Event' => $eventName, ]); } $response = $request->post($endpoint->url, $body); $status = $response->successful() ? 'delivered' : 'failed'; $delivery->update([ 'response_code' => $response->status(), 'delivered_at' => now(), 'status' => $status, ]); $endpoint->update(['last_triggered_at' => now()]); return $response->successful(); } catch (\Throwable $e) { Log::warning('IntegrationHub webhook delivery failed', [ 'endpoint_id' => $endpoint->id, 'event' => $eventName, 'error' => $e->getMessage(), ]); $delivery->update([ 'response_code' => 0, 'delivered_at' => now(), 'status' => 'failed', ]); return false; } } public function availableEvents(): array { $events = config('integrationhub.webhook_events', []); $translated = []; foreach (array_keys($events) as $eventKey) { $translated[$eventKey] = \Modules\IntegrationHub\Utils\IntegrationHubUtil::eventLabel($eventKey); } return $translated; } }