Вебхуки для заказов цифровых товаров
Краткий ответ
Вебхуки — это HTTP push-уведомления, отправляемые системой поставщика на ваш сервер при наступлении события заказа. Для цифровых товаров критические события: заказ создан, заказ выполнен, заказ провалился. Вместо многократного опроса эндпоинта статуса заказа для проверки готовности кода, вебхуки уведомляют ваш сервер в момент завершения фулфилмента. Это ускоряет доставку, сокращает API-вызовы и устраняет задержки, связанные с опросом.
Определение: Вебхук для заказов цифровых товаров — это HTTP POST-запрос, отправляемый поставщиком на ваш серверный эндпоинт при изменении статуса заказа — например, когда код готов к доставке. Ваш сервер получает событие и обрабатывает доставку без необходимости опроса.
Главный вывод: Опрос эндпоинта статуса заказа работает при малых масштабах. При высоких объёмах опрос достигает ограничений по частоте и вносит задержку. Вебхуки — production-grade решение: одно событие на каждое изменение заказа, доставляемое по факту.
Для кого это руководство
- Разработчики, интегрирующие API цифровых товаров и нуждающиеся в асинхронной обработке заказов
- Операторы магазинов, у которых фулфилмент заказов иногда задерживается (ожидающие заказы)
- Все, кто строит высокообъёмный pipeline цифровых товаров
Опрос vs. Вебхуки
| Фактор | Опрос | Вебхуки |
|---|---|---|
| Как работает | Ваш сервер спрашивает «заказ выполнен?» каждые N секунд | Поставщик уведомляет ваш сервер при изменении статуса |
| Задержка | Зависит от интервала опроса | Почти мгновенная |
| Объём API-вызовов | Высокий (N вызовов на каждый ожидающий заказ) | Один вызов на событие |
| Риск ограничений по частоте | Высокий при масштабировании | Нет |
| Реализация | Проще | Немного сложнее (эндпоинт + валидация) |
| Лучше для | Разработки/тестирования | Production |
Типы вебхук-событий
Для API поставщика цифровых товаров ожидайте следующие типы событий:
| Событие | Когда срабатывает | Действие на вашем сервере |
|---|---|---|
order.created |
Заказ получен поставщиком | Логировать; запустить таймер SLA |
order.fulfilled |
Код готов; заказ выполнен | Доставить код клиенту |
order.failed |
Фулфилмент провалился | Уведомить операторов; запустить флоу возврата, если платёж был принят |
order.refunded |
Заказ отменён поставщиком | Обновить статус; уведомить клиента |
balance.low |
Баланс реселлера ниже порога | Запустить процесс пополнения баланса |
Наиболее критическое событие — order.fulfilled — это триггер для доставки кода.
Формат вебхук-payload (типичный)
{
"event": "order.fulfilled",
"timestamp": "2026-05-01T14:23:11Z",
"data": {
"order_id": "SUP-99887",
"reference": "ORD-12345",
"status": "fulfilled",
"items": [
{
"sku": "steam-20-usd",
"code": "XXXXX-YYYYY-ZZZZZ",
"pin": null
}
]
},
"signature": "sha256=abc123..."
}
Всегда проверяйте поле reference — это ваш внутренний ID заказа, позволяющий сопоставить событие поставщика с вашей базой данных без хранения ID заказов поставщика как первичных ключей.
Валидация подписи
Поставщики подписывают вебхук-payload, чтобы вы могли убедиться, что они пришли из легитимного источника. Без валидации любой может отправить POST на ваш эндпоинт.
Валидация HMAC-SHA256 (наиболее распространённая):
import hmac
import hashlib
def validate_webhook(payload_body: bytes, signature_header: str, secret: str) -> bool:
expected = hmac.new(
secret.encode('utf-8'),
payload_body,
hashlib.sha256
).hexdigest()
received = signature_header.replace('sha256=', '')
return hmac.compare_digest(expected, received)
Правила:
- Валидируйте до обработки любого payload
- Используйте сравнение за постоянное время (
hmac.compare_digest) для предотвращения тайминг-атак - Возвращайте HTTP 400 при провале валидации подписи (не возвращайте 200)
- Возвращайте HTTP 200 немедленно при успешной валидации — до обработки события
Асинхронная обработка
Обрабатывайте вебхук-события асинхронно. Ваш вебхук-эндпоинт должен вернуть HTTP 200 в пределах таймаута поставщика (обычно 3–10 секунд). Если ваша обработка события занимает дольше — запись в базу данных, отправка email, API-вызовы — поставщик может пометить доставку как неудачную и повторить.
Правильная архитектура:
Вебхук-эндпоинт получает POST
→ Валидирует подпись
→ Немедленно возвращает HTTP 200
→ Помещает событие в очередь (Redis, SQS, таблица DB-очереди)
Фоновый воркер
→ Извлекает событие из очереди
→ Обрабатывает: доставляет код клиенту, обновляет статус заказа
Неправильно: Обработка доставки внутри вебхук-обработчика до возврата 200.
Поведение при повторных попытках
Поставщики повторяют доставку вебхука, если не получают HTTP 200 в пределах таймаута. Типичные расписания повторов:
- 1-я попытка: 30 секунд после ошибки
- 2-я попытка: 5 минут
- 3-я попытка: 30 минут
- Далее: варьируется (некоторые поставщики повторяют в течение 24 часов)
Ваша обработка идемпотентности должна предотвращать двойную обработку одного заказа при повторе. Используйте ссылку на заказ как ключ идемпотентности:
if order_already_delivered(reference):
return HTTP 200 # Подтвердить, ничего не делать
Резервный вариант: опрос для пропущенных событий
Вебхуки могут не сработать. Ваш эндпоинт может лечь, или сетевая проблема может помешать доставке. Реализуйте резервный опрос для заказов, остающихся в статусе pending более N минут:
Планировщик (каждые 5 минут):
→ Найти все заказы со статусом = 'pending' и возрастом > 5 минут
→ Для каждого: вызвать GET /orders/:id
→ Если статус = fulfilled: обработать доставку
→ Если статус = failed: уведомить операторов
Это гарантирует, что ни один заказ не застрянет навсегда из-за пропущенного вебхука.
Чек-лист реализации
- URL вебхук-эндпоинта зарегистрирован у поставщика (обычно в настройках API)
- POST-эндпоинт, принимающий вебхук-payload, реализован
- Чтение raw body до JSON-парсинга (для валидации подписи по raw-байтам)
- Валидация подписи реализована с использованием алгоритма поставщика и общего секрета
- HTTP 200 возвращается немедленно после успешной валидации
- Событие помещается в асинхронную очередь
- Фоновый воркер, обрабатывающий события из очереди, построен
- Проверка идемпотентности по ссылке на заказ реализована
- Резервный опрос для ожидающих заказов реализован
- Протестировано с тестовым payload поставщика
- Мониторинг ошибок доставки вебхуков в дашборде поставщика
