loadMissing('organization'); $payload = [ 'event' => $event, 'visit' => [ 'id' => $visit->id, 'public_id' => $visit->public_id, 'external_ref' => $visit->external_ref, 'source' => $visit->source, 'status' => $visit->status, 'visitor_type' => $visit->visitor_type, 'badge_code' => $visit->badge_code, 'checked_in_at' => $visit->checked_in_at?->toIso8601String(), 'checked_out_at' => $visit->checked_out_at?->toIso8601String(), 'visitor_name' => $visit->visitor?->full_name, 'host_name' => $visit->host?->name, ], 'timestamp' => now()->toIso8601String(), ]; $this->dispatchPayload($visit->organization_id, $event, $payload); } public function dispatchEmployee(string $event, Employee $employee, ?EmployeePresence $presence = null): void { $presence ??= $employee->presence; $payload = [ 'event' => $event, 'employee' => [ 'id' => $employee->id, 'employee_code' => $employee->employee_code, 'full_name' => $employee->full_name, 'department' => $employee->department, 'branch_id' => $employee->branch_id, 'status' => $presence?->status, 'destination' => $presence?->destination, 'signed_in_at' => $presence?->signed_in_at?->toIso8601String(), 'expected_return_at' => $presence?->expected_return_at?->toIso8601String(), ], 'timestamp' => now()->toIso8601String(), ]; $this->dispatchPayload($employee->organization_id, $event, $payload); } /** @param array $payload */ protected function dispatchPayload(int $organizationId, string $event, array $payload): void { $endpoints = WebhookEndpoint::query() ->where('organization_id', $organizationId) ->where('is_active', true) ->get() ->filter(fn (WebhookEndpoint $endpoint) => $endpoint->subscribesTo($event)); foreach ($endpoints as $endpoint) { $this->send($endpoint, $payload); } } /** @param array $payload */ protected function send(WebhookEndpoint $endpoint, array $payload): void { $body = json_encode($payload); $headers = ['Content-Type' => 'application/json']; if ($endpoint->secret) { $headers['X-Frontdesk-Signature'] = hash_hmac('sha256', $body, $endpoint->secret); } try { Http::timeout(10)->withHeaders($headers)->withBody($body, 'application/json')->post($endpoint->url); } catch (\Throwable $e) { Log::warning('Frontdesk webhook delivery failed', [ 'endpoint_id' => $endpoint->id, 'url' => $endpoint->url, 'error' => $e->getMessage(), ]); } } }