$this->event, 'payload' => $this->payload, 'timestamp' => now()->toISOString(), ], JSON_THROW_ON_ERROR); $signature = 'sha256=' . hash_hmac('sha256', $body, $this->webhook->secret); $host = parse_url($this->webhook->url, PHP_URL_HOST); if ($this->isPrivateHost($host)) { return; } $response = Http::timeout(10) ->withHeaders([ 'Content-Type' => 'application/json', 'X-Nimuli-Signature' => $signature, 'X-Nimuli-Event' => $this->event, ]) ->post($this->webhook->url, json_decode($body, true, 512, JSON_THROW_ON_ERROR)); WebhookDelivery::create([ 'webhook_id' => $this->webhook->id, 'event' => $this->event, 'payload' => json_decode($body, true, 512, JSON_THROW_ON_ERROR), 'status' => $response->successful() ? 'success' : 'failed', 'response_code' => $response->status(), 'attempts' => max(1, $this->attempts()), ]); } private function isPrivateHost(?string $host): bool { if (! $host) { return true; } $ip = gethostbyname($host); return filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) === false; } }