Обработка вебхуков: проверка подписи, быстрый ответ и вынесение долгой работы
Партнёр обычно ждёт короткий HTTP-ответ. Проверяете подпись: неверная — сразу отказ, верная — быстрый успех. Долгую работу не оставляете в этом запросе — переносите в пайплайн или фоновую задачу. Если партнёр отправит то же событие снова, повторный запрос с тем же id события не должен второй раз менять ваши данные.
Обновлено: 2026-04-20
Кратко
Суть ответа
Обработка вебхуков: проверка подписи, быстрый ответ и вынесение долгой работы. Отдельные функции на провайдера снижают случайное связывание.
Когда подходит и когда нет
- Интеграции SaaS
- Платежи
- События с Git-хостинга
На что обратить внимание
- Пропуск проверки подписи «временно».
- Синхронные записи в БД до 200 OK.
Ситуация: нагрузка и где обычно ломается
Что идёт не так при обработке вебхуков без идемпотентности и без разделения быстрого HTTP-ответа и долгой работы в фоне
Дубликаты и медленный приёмник дают таймауты без идемпотентности и без передачи тяжёлого в фон.
Перегруженная общая точка входа тянет вниз пользовательский трафик.
One overloaded endpoint drags down unrelated user traffic.
Когда упрощённых рецептов мало
Типичные ошибки при реализации HTTP-коллбэков от SaaS-провайдеров (платежи, Git, мессенджеры)
Пропуск проверки подписи «временно».
Синхронные записи в БД до 200 OK.
Как Inquir помогает в этом сценарии
Как в Inquir устроены отдельные маршруты под каждого провайдера и продолжение работы в пайплайне после 200 OK
Отдельные функции на провайдера снижают случайное связывание.
Пайплайны продолжают работу после быстрого HTTP-ответа.
Что вы получаете на платформе
Что дают API-шлюз и пайплайны для надёжной обработки вебхуков
Доступ на уровне маршрута
Ключи API или свои схемы на API-Gateway.
Трассы
Видно, на каком шаге сбой — проверка, постановка в очередь или запись.
Маршрутизация тенантов
Хосты или префиксы под отдельные URL вебхуков.
Что сделать дальше, по шагам
Как обрабатывать вебхуки на Inquir Compute
Проверка подписи, быстрый ответ провайдеру, идемпотентные записи.
Проверить событие
Ранний отказ при неверной подписи.
Ответить
Ответьте быстро в лимитах провайдера.
Обработать
Идемпотентные записи по идентификатору события у провайдера.
Пример кода
Паттерны реализации под конкретного провайдера
У разных провайдеров разные заголовки подписи и таймауты. Отдельная функция на провайдера: логика проверки остаётся маленькой и легко проверяемой.
export async function handler(event) { const rawBody = event.body ?? ''; if (!stripe.webhooks.verifySignature(rawBody, event.headers['stripe-signature'], process.env.STRIPE_WEBHOOK_SECRET)) { return { statusCode: 400, body: 'invalid signature' }; } const evt = JSON.parse(rawBody); // Persist evt.id BEFORE side effects — idempotency key const isNew = await db.upsertWebhookEvent(evt.id, evt.type); if (!isNew) return { statusCode: 200, body: 'duplicate' }; // Ack Stripe fast, continue fulfillment asynchronously await global.durable.startNew('process-payment', undefined, { eventId: evt.id, type: evt.type, obj: evt.data.object }); return { statusCode: 200, body: 'ok' }; }
import { createHmac } from 'node:crypto'; export async function handler(event) { const rawBody = event.body ?? ''; const hmac = event.headers['x-shopify-hmac-sha256']; const digest = createHmac('sha256', process.env.SHOPIFY_WEBHOOK_SECRET).update(rawBody).digest('base64'); if (hmac !== digest) return { statusCode: 401, body: 'invalid signature' }; const topic = event.headers['x-shopify-topic']; // e.g. 'orders/create' const order = JSON.parse(rawBody); await global.durable.startNew('process-order', undefined, { topic, orderId: order.id }); return { statusCode: 200, body: '' }; }
Когда подходит и когда нет
Когда имеет смысл обрабатывать вебхуки через API-шлюз Inquir и продолжать логику в пайплайнах
Когда это уместно
- Интеграции SaaS
- Платежи
- События с Git-хостинга
Когда лучше не трогать
- Двунаправленные сокеты — другой класс транспорта
Вопросы и ответы
Вопросы и ответы
Зачем не трогать сырое тело для HMAC?
Провайдеры подписывают точные байты; пересборка JSON ломает подпись.
Тяжёлая работа до 200?
Нет — подтверждение в лимите провайдера, продолжение в пайплайне или фоновой задаче, чтобы повторы не дублировали дорогие эффекты.
Дубликаты доставки?
ID события провайдера как ключ идемпотентности: «видели» до мутации данных.