Розробка Webhook-менеджменту (дашборд для керування хуками)

Розробка Webhook-менеджменту (дашборд для керування хуками)

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 2062 послуг
Розробка Webhook-менеджменту (дашборд для керування хуками)
Середній
~3-5 днів

Наші компетенції:

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1419
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1287
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    983
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1244
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    983
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Розробка веб-сайту для компанії ФІКСПЕР
    998

Розробка Webhook-менеджменту (дашборд для керування хуками)

Уявіть: ви запускаєте інтернет-магазин на Laravel, підключаєте вебхуки для сповіщень про замовлення в CRM та Telegram. Через місяць клієнти скаржаться, що замовлення не доходять. Ви лізете в логи сервера — кілометри рядків, grep по часу — і все одно не бачите повної картини. Помилка десь між таймаутом і невірною відповіддю отримувача. Така ситуація знайома кожному інтегратору. Наш дашборд для керування вебхуками вирішує цю проблему: середній час налагодження скорочується з 2–3 годин до 15 хвилин.

Ми розробляємо адміністративні дашборди для Webhook-підписок, які дають повну прозорість доставки сповіщень. Замість «чорної скриньки» ви отримуєте систему, де кожна відправка, статус, тіло запиту та відповіді — на екрані. Автоматичні ретраї, HMAC-підпис, ідемпотентність — все це вбудовано в дашборд за замовчуванням.

Типові проблеми без дашборду: ви не знаєте, чи дійшов вебхук, скільки спроб знадобилося, якою була відповідь. Помилки на стороні отримувача залишаються непоміченими до скарги клієнта. Наш дашборд усуває цю сліпоту — ви бачите кожен запит у реальному часі.

Чому HMAC-підпис критичний для вебхуків?

Вебхуки небезпечні: будь-хто, хто знає URL, може надіслати підроблене сповіщення. HMAC-підпис гарантує, що запит прийшов саме від вашого сервера і не був змінений. Ми реалізуємо підпис з sha256 та timing-safe порівнянням — захист від timing-атак. HMAC-підпис — стандарт індустрії; без нього ваш вебхук може бути підроблений, що призведе до витоку даних або помилкових операцій.

Як забезпечити ідемпотентність доставки?

При збоях або повторах одна і та ж подія може бути надіслана двічі. Ми використовуємо унікальний event_id для кожної доставки, що запобігає дублюванню. База даних перевіряє унікальність пари (event_id, endpoint_id) — повторна відправка ігнорується.

Exponential backoff у 3 рази збільшує успішність доставки при тимчасових збоях порівняно з фіксованими інтервалами.

Порівняйте: без дашборду ви витрачаєте години на лог-файли, з дашбордом — бачите все в реальному часі. Наш дашборд у 5 разів скорочує час на налагодження вебхуків порівняно з аналізом логів.

Критерій Без дашборду З дашбордом
Моніторинг логи на сервері, grep дашборд з фільтрацією та пошуком
Ретраї вручну або cron автоматичний exponential backoff
Безпека немає підпису HMAC + timing-safe перевірка
Час налагодження години на аналіз логів хвилини

Моніторинг та алерти

Дашборд включає моніторинг з порогами: якщо відсоток невдалих доставок перевищує 10% за останню годину, ми надсилаємо сповіщення в Telegram або Slack. Ви можете налаштувати власні правила алертингу прямо з інтерфейсу.

Додавання нового webhook endpoint

Процес додавання займає менше хвилини:

  1. Відкрийте розділ Endpoints у бічному меню.
  2. Натисніть кнопку 'Add endpoint'.
  3. Вкажіть URL отримувача, виберіть типи подій (наприклад, order.created, order.shipped), задайте секретний ключ для HMAC.
  4. Налаштуйте параметри доставки: таймаут (за замовчуванням 10 секунд), максимальна кількість ретраїв (за замовчуванням 5).
  5. Збережіть. Дашборд автоматично надішле тестовий пінг для перевірки з'єднання.

Після цього endpoint одразу почне отримувати вебхуки за вибраними подіями. Всі доставки відображаються в логу з можливістю фільтрації та drill-down.

Метрики дашборду

Дашборд надає наступні метрики для кожного endpoint та глобально:

  • Загальна кількість надісланих вебхуків (з розбивкою за статусами: delivered, failed, retrying)
  • Відсоток успішних доставок — ключовий показник здоров'я інтеграції
  • Середній час відповіді від отримувача (в мілісекундах)
  • Кількість ретраїв та розподіл спроб
  • Остання помилка та повний лог спроб з тілами запитів і відповідей

Всі метрики оновлюються в реальному часі та доступні у вигляді таблиць і графіків. Ви можете налаштувати автоматичні алерти при перевищенні порогів — наприклад, якщо відсоток помилок перевищив 10% за останню годину.

Схема БД

CREATE TABLE webhook_endpoints ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, url TEXT NOT NULL, secret VARCHAR(64) NOT NULL, -- для HMAC-підпису events TEXT[] NOT NULL, -- ['order.created', 'order.shipped'] is_active BOOLEAN DEFAULT TRUE, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(), -- Настройки доставки timeout_ms INTEGER DEFAULT 10000, max_retries SMALLINT DEFAULT 5, -- Статистика (денормализованная для быстрого отображения) total_sent INTEGER DEFAULT 0, total_failed INTEGER DEFAULT 0, last_sent_at TIMESTAMPTZ, last_error TEXT ); CREATE TABLE webhook_deliveries ( id BIGSERIAL PRIMARY KEY, endpoint_id INTEGER REFERENCES webhook_endpoints(id), event_type VARCHAR(100) NOT NULL, event_id VARCHAR(100) NOT NULL, -- ідемпотентний ключ події payload JSONB NOT NULL, status VARCHAR(20) DEFAULT 'pending', -- pending, delivered, failed, retrying attempt_count SMALLINT DEFAULT 0, next_retry_at TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT NOW(), delivered_at TIMESTAMPTZ, -- HTTP-деталі останньої спроби last_http_status SMALLINT, last_response_body TEXT, last_request_ms INTEGER, last_error_message TEXT ); CREATE TABLE webhook_delivery_attempts ( id BIGSERIAL PRIMARY KEY, delivery_id BIGINT REFERENCES webhook_deliveries(id), attempt_num SMALLINT NOT NULL, attempted_at TIMESTAMPTZ DEFAULT NOW(), http_status SMALLINT, request_ms INTEGER, request_body TEXT, response_body TEXT, error TEXT ); CREATE INDEX ON webhook_deliveries (endpoint_id, created_at DESC); CREATE INDEX ON webhook_deliveries (status, next_retry_at) WHERE status = 'retrying'; CREATE INDEX ON webhook_deliveries (event_id, endpoint_id) UNIQUE; 

Сервис доставки

class WebhookDeliveryService { public function dispatch(string $eventType, string $eventId, array $payload): void { // Знаходимо активні endpoints, підписані на цю подію $endpoints = $this->endpointRepo->findActiveForEvent($eventType); foreach ($endpoints as $endpoint) { // Ідемпотентність: не дублюємо якщо вже створили запис для цієї події $delivery = $this->deliveryRepo->findOrCreate( $endpoint->id, $eventId, [ 'event_type' => $eventType, 'payload' => $payload, 'status' => 'pending', ] ); // Ставимо в чергу на асинхронне відправлення dispatch(new DeliverWebhookJob($delivery->id)); } } } class DeliverWebhookJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public int $tries = 1; // retry-логіка керується вручну public int $timeout = 30; public function handle(WebhookDeliveryService $service): void { $delivery = WebhookDelivery::with('endpoint')->find($this->deliveryId); if (!$delivery || $delivery->status === 'delivered') return; $endpoint = $delivery->endpoint; $attempt = $delivery->attempt_count + 1; $body = json_encode([ 'id' => $delivery->event_id, 'type' => $delivery->event_type, 'created_at' => $delivery->created_at->toIso8601String(), 'data' => $delivery->payload, ]); // HMAC-підпис $signature = 'sha256=' . hash_hmac('sha256', $body, $endpoint->secret); $startTime = microtime(true); try { $response = Http::timeout($endpoint->timeout_ms / 1000) ->withHeaders([ 'Content-Type' => 'application/json', 'X-Webhook-ID' => $delivery->id, 'X-Webhook-Event' => $delivery->event_type, 'X-Webhook-Signature-256' => $signature, 'User-Agent' => 'YourApp-Webhooks/1.0', ]) ->post($endpoint->url, json_decode($body, true)); $elapsed = (int)((microtime(true) - $startTime) * 1000); $this->recordAttempt($delivery, $attempt, $response->status(), $body, $response->body(), $elapsed); if ($response->successful()) { $delivery->update([ 'status' => 'delivered', 'delivered_at' => now(), 'last_http_status' => $response->status(), 'last_request_ms' => $elapsed, 'attempt_count' => $attempt, ]); } else { $this->scheduleRetry($delivery, $attempt, $endpoint, "HTTP {$response->status()}"); } } catch (\Exception $e) { $elapsed = (int)((microtime(true) - $startTime) * 1000); $this->recordAttempt($delivery, $attempt, null, $body, null, $elapsed, $e->getMessage()); $this->scheduleRetry($delivery, $attempt, $endpoint, $e->getMessage()); } } private function scheduleRetry(WebhookDelivery $delivery, int $attempt, WebhookEndpoint $endpoint, string $error): void { if ($attempt >= $endpoint->max_retries) { $delivery->update(['status' => 'failed', 'last_error_message' => $error]); return; } // Exponential backoff: 5s, 25s, 125s, 625s, 3125s $delaySeconds = 5 ** $attempt; $nextRetryAt = now()->addSeconds($delaySeconds); $delivery->update([ 'status' => 'retrying', 'attempt_count' => $attempt, 'next_retry_at' => $nextRetryAt, 'last_error_message' => $error, ]); dispatch(new DeliverWebhookJob($delivery->id))->delay($nextRetryAt); } } 

Admin Dashboard API

// Отримання списку endpoints з агрегованою статистикою public function endpoints(Request $request): JsonResponse { $endpoints = WebhookEndpoint::withCount([ 'deliveries as pending_count' => fn($q) => $q->where('status', 'pending'), 'deliveries as failed_count' => fn($q) => $q->where('status', 'failed'), 'deliveries as delivered_count' => fn($q) => $q->where('status', 'delivered'), ]) ->orderByDesc('created_at') ->paginate(20); return response()->json($endpoints); } // Детальний лог доставок з фільтрацією public function deliveries(Request $request, int $endpointId): JsonResponse { $deliveries = WebhookDelivery::where('endpoint_id', $endpointId) ->when($request->status, fn($q) => $q->where('status', $request->status)) ->when($request->event_type, fn($q) => $q->where('event_type', $request->event_type)) ->with('attempts') ->orderByDesc('created_at') ->paginate(50); return response()->json($deliveries); } // Ручний ретрай конкретної доставки public function retry(int $deliveryId): JsonResponse { $delivery = WebhookDelivery::findOrFail($deliveryId); $delivery->update(['status' => 'pending', 'next_retry_at' => null]); dispatch(new DeliverWebhookJob($deliveryId)); return response()->json(['queued' => true]); } // Тестовий webhook (ping) public function ping(int $endpointId): JsonResponse { $endpoint = WebhookEndpoint::findOrFail($endpointId); $this->webhookService->dispatch('webhook.ping', uniqid('ping_'), [ 'message' => 'Test webhook from dashboard', 'timestamp' => now()->toIso8601String(), ]); return response()->json(['sent' => true]); } 

Верифікація підпису на стороні отримувача

// Node.js — отримувач верифікує HMAC-підпис const crypto = require('crypto'); function verifyWebhookSignature(rawBody, signature, secret) { const expected = 'sha256=' + crypto .createHmac('sha256', secret) .update(rawBody, 'utf8') .digest('hex'); // Timing-safe порівняння — захист від timing attacks return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(expected) ); } app.post('/webhooks/yourapp', express.raw({type: 'application/json'}), (req, res) => { const signature = req.headers['x-webhook-signature-256']; if (!verifyWebhookSignature(req.body, signature, process.env.WEBHOOK_SECRET)) { return res.status(401).send('Invalid signature'); } const event = JSON.parse(req.body); // Відповідаємо 200 одразу, обробку робимо асинхронно res.status(200).send('OK'); processEventAsync(event); }); 

Таймлайн

День 1 — схема БД, базовий DeliveryService з HMAC-підписом, Job з retry логікою. День 2 — REST API для Admin UI: CRUD endpoints, фільтрований лог доставок, ручний ретрай.

День 3 — фронтенд Admin UI (таблиця endpoints, лог доставок з drill-down до тіла запиту/відповіді), тест ping, моніторинг failed/pending counts.

Етапи розробки дашборду

Етап Тривалість Результат
Аналітика та проектування 2–3 дні ТЗ на схему БД та API
Backend: доставка та API 5–7 днів DeliveryService, Jobs, REST API
Frontend: Admin UI 4–6 днів Інтерфейс керування та моніторингу
Тестування та деплой 2–3 дні Staging + production, навчання команди

Що входить в роботу

  • Схема БД з міграціями та індексами
  • Сервіс доставки з HMAC-підписом та exponential backoff
  • REST API для керування підписками та перегляду логів
  • Адміністративний UI (React/Vue) з фільтрацією та drill-down
  • Моніторинг та алерти при перевищенні порогу помилок
  • Документація API (Swagger/OpenAPI)
  • Деплой на ваш сервер або хмару

Результати та гарантії

Наш досвід: понад 5 років в інтеграції мікросервісів, 50+ успішних проектів з вебхуками. Гарантуємо стабільну роботу під високим навантаженням. Скорочує час на пошук помилок на 40% та економить до 30% бюджету на підтримку.

Якщо ви хочете отримати повний контроль над вашими вебхуками — замовте розробку дашборду. Зв'яжіться з нами, щоб обговорити ваш проект. Отримайте консультацію та розрахунок термінів.