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

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

Разработка и обслуживание любых видов сайтов:

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

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

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

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

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1418
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1286
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    983
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1243
  • 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% бюджета на поддержку.

Если вы хотите получить полный контроль над вашими вебхуками — закажите разработку дашборда. Свяжитесь с нами, чтобы обсудить ваш проект. Получите консультацию и расчет сроков.