104 lines
3.1 KiB
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;
|
|
}
|
|
}
|