ultimatepos/Modules/IntegrationHub/Services/WebhookDispatcherService.php

104 lines
3.1 KiB
PHP

<?php
namespace Modules\IntegrationHub\Services;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Modules\IntegrationHub\Models\IhWebhookDelivery;
use Modules\IntegrationHub\Models\IhWebhookEndpoint;
class WebhookDispatcherService
{
public function dispatch(int $businessId, string $eventName, array $payload): int
{
if (! \Module::has('IntegrationHub') || ! \Module::isEnabled('IntegrationHub')) {
return 0;
}
$endpoints = IhWebhookEndpoint::forBusiness($businessId)
->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;
}
}