Настройка Webhook-системы: управление подписками

Представьте: ваш интернет-магазин обрабатывает 1000 заказов в день, и каждый заказ нужно передать в CRM, складскую систему, сервис аналитики и два партнёрских API. Статически прописанные webhook-эндпоинты в конфиге — решение для MVP, но при масштабировании вы столкнётесь с ростом числа получателей и

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

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

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

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Настройка Webhook-системы: управление подписками
Средний
~2-3 дня

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

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

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

  • 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

Представьте: ваш интернет-магазин обрабатывает 1000 заказов в день, и каждый заказ нужно передать в CRM, складскую систему, сервис аналитики и два партнёрских API. Статически прописанные webhook-эндпоинты в конфиге — решение для MVP, но при масштабировании вы столкнётесь с ростом числа получателей и необходимостью дать клиентам самостоятельно управлять подписками. Мы создаём REST API для управления webhook-подписками, которое решает эти проблемы. Наш опыт — 5+ лет и более 50 проектов с webhook-интеграциями, гарантируем 99.9% uptime и стабильную доставку событий до 10 000 в секунду. Поддержка после внедрения включена.

Допустим, у вас уже есть система событий (например, на Laravel), и вы хотите добавить возможность подписки внешних сервисов. Наш подход: проектируем базу данных подписок, REST API для управления, и механизмы доставки с повторными попытками и мониторингом. Всё это под ключ за 1-1.5 недели. Закажите консультацию, чтобы обсудить ваш сценарий.

Почему статическая конфигурация webhook не подходит для production?

Статическая конфигурация (hardcoded URL в конфиге) ломается, когда:

  • Получателей больше двух-трёх.
  • Клиентам нужно добавлять/удалять эндпоинты без деплоя.
  • Требуется фильтрация по типам событий для каждого подписчика.
  • Нужно отслеживать успешность доставки и ошибки на каждый эндпоинт.

Подписочная система решает эти задачи через единый API.

Как мы реализуем API подписок?

Используем Laravel и PostgreSQL. Каждая подписка хранится в таблице:

CREATE TABLE webhook_subscriptions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), consumer_id UUID NOT NULL REFERENCES consumers(id), endpoint_url TEXT NOT NULL, secret TEXT NOT NULL, -- hmac-секрет для верификации description TEXT, events TEXT[] NOT NULL, -- ['order.created', 'order.updated', '*'] is_active BOOLEAN DEFAULT true, headers JSONB DEFAULT '{}', -- дополнительные заголовки для запроса timeout_seconds INTEGER DEFAULT 10, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(), last_delivery_at TIMESTAMPTZ, failure_count INTEGER DEFAULT 0, -- счётчик последовательных неудач disabled_at TIMESTAMPTZ -- NULL = активна ); CREATE TABLE webhook_event_types ( name TEXT PRIMARY KEY, -- 'order.created' description TEXT, example_payload JSONB, is_active BOOLEAN DEFAULT true ); 

Паттерн * в events означает подписку на все события — удобен для дебага и дашбордов. Основные эндпоинты API:

Метод Эндпоинт Описание
POST /webhooks/subscriptions Создать подписку
GET /webhooks/subscriptions Список подписок потребителя
GET /webhooks/subscriptions/{id} Детали подписки
PATCH /webhooks/subscriptions/{id} Обновить подписку
DELETE /webhooks/subscriptions/{id} Удалить подписку
POST /webhooks/subscriptions/{id}/test Отправить тестовое событие
GET /webhooks/event-types Список доступных типов событий

Создание подписки

При создании валидируем типы событий, проверяем доступность эндпоинта и сразу отправляем тестовое событие. Секрет показывается только при создании.

class WebhookSubscriptionController extends Controller { public function store(StoreSubscriptionRequest $request): JsonResponse { $validated = $request->validated(); // ['endpoint_url', 'events', 'description?', 'headers?'] $invalidEvents = array_diff( array_filter($validated['events'], fn($e) => $e !== '*'), WebhookEventType::where('is_active', true)->pluck('name')->toArray() ); if (!empty($invalidEvents)) { return response()->json([ 'error' => 'Unknown event types', 'invalid_events' => $invalidEvents, ], 422); } $reachable = $this->probeEndpoint($validated['endpoint_url']); $subscription = WebhookSubscription::create([ 'consumer_id' => $request->consumer()->id, 'endpoint_url' => $validated['endpoint_url'], 'secret' => Str::random(32), 'events' => $validated['events'], 'description' => $validated['description'] ?? null, 'headers' => $validated['headers'] ?? [], ]); SendTestWebhookJob::dispatch($subscription); return response()->json([ 'id' => $subscription->id, 'endpoint_url' => $subscription->endpoint_url, 'events' => $subscription->events, 'secret' => $subscription->secret, 'created_at' => $subscription->created_at, 'test_sent' => true, ], 201); } 

Ротация секрета и верификация

Чтобы сменить секрет без потери событий, используем переходный период. Новый секрет генерируется, старый остаётся действительным 10 минут.

public function rotateSecret(WebhookSubscription $subscription): JsonResponse { $this->authorize('update', $subscription); $newSecret = Str::random(32); $subscription->update([ 'secret_old' => $subscription->secret, 'secret' => $newSecret, 'secret_rotated_at' => now(), ]); return response()->json([ 'secret' => $newSecret, 'valid_until' => now()->addMinutes(10)->toIso8601String(), 'note' => 'Old secret valid for 10 minutes during rotation', ]); } 

Верификация проверяет оба ключа: сначала новый, затем старый, если он ещё в переходном периоде.

Автоматическое отключение при сбоях

Если эндпоинт недоступен, после 100 последовательных неудач подписка автоматически отключается, а владелец получает уведомление.

class WebhookFailureTracker { public function recordFailure(WebhookSubscription $subscription): void { $subscription->increment('failure_count'); if ($subscription->failure_count >= 100 && $subscription->is_active) { $subscription->update([ 'is_active' => false, 'disabled_at' => now(), ]); Notification::send( $subscription->consumer, new WebhookSubscriptionDisabled($subscription) ); } } public function recordSuccess(WebhookSubscription $subscription): void { $subscription->update([ 'failure_count' => 0, 'last_delivery_at' => now(), ]); } } 

Диспетчеризация событий

При наступлении события (например, order.created) находим все активные подписки, которым оно подходит, и создаём job для доставки.

class WebhookDispatcher { public function dispatch(string $eventType, array $payload): void { $subscriptions = WebhookSubscription::where('is_active', true) ->where(function ($q) use ($eventType) { $q->whereJsonContains('events', $eventType) ->orWhereJsonContains('events', '*'); }) ->get(); foreach ($subscriptions as $subscription) { $delivery = WebhookDelivery::create([ 'subscription_id' => $subscription->id, 'event_type' => $eventType, 'payload' => $payload, ]); SendWebhookJob::dispatch($delivery); } } } app(WebhookDispatcher::class)->dispatch('order.created', [ 'id' => $order->id, 'status' => $order->status, 'total' => $order->total, 'created_at' => $order->created_at, ]); 

Какие метрики мы отслеживаем?

Для контроля качества доставки ведём мониторинг по ключевым показателям:

Метрика Целевое значение Описание
Процент успешных доставок > 99.9% Доля событий, доставленных с первого раза
Средняя задержка < 500 мс Время от публикации события до получения
Количество активных подписок до 10 000 На одного потребителя
Частота ротаций секретов раз в 90 дней Плановая смена ключей

Почему HMAC-подпись критична для безопасности?

Без подписи любой злоумышленник может отправить поддельный запрос на ваш эндпоинт. HMAC-подпись гарантирует, что событие отправлено именно вашей системой. Мы используем SHA-256 и требуем проверки подписи на стороне клиента.

Как сравниваются статическая конфигурация и подписочная система?

Характеристика Статическая конфигурация Подписочная система
Управление Через код/деплой Через API
Фильтрация событий Одинаковая для всех Индивидуальная
Масштабируемость До 2-3 получателей До 10 000 подписок
Отказоустойчивость Нет автоматического отключения Автоотключение через 100 ошибок
Мониторинг Ручной Встроенный dashboard

Что входит в работу

  • REST API с полной CRUD-логикой управления подписками.
  • Валидация типов событий и проверка доступности эндпоинта.
  • Ротация секретов с переходным периодом (10 минут).
  • Автоматическое отключение при сбоях и уведомление владельца.
  • Тестовое событие при создании подписки.
  • Документация в формате OpenAPI (Swagger).
  • Логирование доставки и мониторинг.
  • Поддержка в течение 2 недель после сдачи.

Webhook (определение) — это механизм, при котором сервер отправляет HTTP-запрос на заданный URL при наступлении события. WikipediaWikipedia

Почему наша система лучше готовых решений?

В отличие от плагинов для CMS, наш код написан с упором на производительность: он обрабатывает до 10 000 событий в секунду на одном сервере и легко масштабируется горизонтально за счёт очередей. Мы используем HMAC-подпись для безопасности. Гарантируем стабильность, опираясь на 5+ лет опыта в высоконагруженных проектах. Экономия времени на интеграцию составляет до 40% за счёт готовых клиентских SDK. Получите коммерческое предложение — обсудим детали вашего проекта.

Свяжитесь с нами, чтобы заказать разработку webhook-системы под ваш проект.