Вебхуки криптоплатежей: события, безопасность и надёжная обработка заказов

Вебхук — это момент, когда магазин узнаёт, что криптоплатёж окончателен. Рассказываем, как построить безопасный, идемпотентный и скучно надёжный обработчик, с картой событий и чек-листом для продакшена.

Обновлено: 4 мин чтения
Вебхуки криптоплатежей — подписанные события счёта, идущие от платёжного шлюза на сервер продавца

Вебхуки криптоплатежей — это HTTP-запросы, которые платёжный шлюз отправляет на ваш сервер при каждом изменении статуса счёта: перевод обнаружен, подтверждён в сети, недоплачен, переплачен или истёк. Обработчик проверяет подпись, обновляет заказ и запускает выдачу. Поскольку криптоплатежи приходят асинхронно — через минуты после того, как клиент ушёл со страницы, — источником истины является вебхук, а не браузер.

Это руководство посвящено вебхукам: какие события приходят, как их проверять, как безопасно обрабатывать одно событие, пришедшее дважды, и как всё это тестировать и мониторить. О создании счетов читайте в руководстве по интеграции API криптоплатежей.

Почему вебхуки, а не опрос или редирект?

  • Редирект — не доказательство — возврат клиента на страницу «спасибо» ничего не говорит о поступлении денег.
  • Опрос расточителен — запрашивать API каждые несколько секунд по каждому открытому счёту не масштабируется и всё равно запаздывает.
  • Вебхук — это push — шлюз сообщает сразу, как только что-то изменилось, и прикладывает проверяемую подпись.
Главное: никогда не отмечайте заказ оплаченным из-за редиректа, сообщения в чате или скриншота. Считается только проверенный вебхук (или аутентифицированный запрос статуса через API).

Какие события вы будете получать

СобытиеЗначениеЧто должен сделать обработчик
invoice.paidПеревод обнаружен, ждём подтвержденийПоказать «платёж получен, подтверждается»; пока не выдавать
invoice.confirmedНабрано нужное число подтвержденийОтметить оплату и выполнить заказ
invoice.underpaidМеньше ожидаемого, ниже допускаСообщить клиенту, сколько не хватает; ждать доплаты
invoice.overpaidПришло больше ожидаемогоВыполнить заказ; решить, что делать с разницей
invoice.expiredНет корректной оплаты в срокВернуть зарезервированный товар; заказ остаётся неоплаченным

Это названия событий в mistKET. В других шлюзах похожие статусы называются иначе — сопоставьте их со своими статусами заказа в одном месте.

Проверка подписи

Отправить POST на публичный URL может кто угодно, поэтому каждый вебхук должен проходить аутентификацию. mistKET подписывает каждую доставку HMAC-SHA256 и передаёт заголовки:

  • X-Mistket-Event — название события.
  • X-Mistket-Timestamp — Unix-время, входящее в подпись.
  • X-Mistket-Signature — sha256= и HMAC от {timestamp}.{raw body} с вашим секретом вебхука.
  • X-Mistket-Delivery — ID доставки для логов.
  1. Прочитайте сырое тело — до разбора JSON, потому что перекодирование меняет байты.
  2. Пересчитайте HMAC — по метке времени, точке и сырому телу с вашим секретом.
  3. Сравните за постоянное время — через hash_equals, hmac.compare_digest или crypto.timingSafeEqual.
  4. Отклоняйте старые метки времени — например, старше пяти минут, чтобы блокировать повторы.
  5. Только потом разбирайте и действуйте — и быстро возвращайте 2xx.

Конструкция следует стандартной схеме HMAC; храните секрет на сервере и меняйте его при утечке.

Выбор и защита callback-URL

Используйте отдельный HTTPS-путь, например /webhooks/mistket, независимый от обычных страниц, и передавайте его как callback при создании каждого счёта. Исключите его из CSRF-защиты, кеширования и редиректов: 301-редирект или закешированный ответ — частая причина «тихих» сбоев вебхуков. Не требуйте сессионную cookie: шлюз не авторизованный пользователь, аутентификация — это подпись HMAC. И наконец, логируйте каждую доставку с событием, номером заказа и кодом ответа, чтобы за секунды отвечать на вопрос «а вебхук пришёл?».

Идемпотентность: одно событие может прийти дважды

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

  • Ключ — номер заказа — найдите заказ, на который ссылается счёт.
  • Проверяйте текущий статус — если заказ уже выполнен, подтвердите получение и ничего не делайте.
  • Используйте транзакцию или блокировку — чтобы две параллельные доставки не выдали товар дважды.
  • Сохраняйте ID доставки — пригодится при разборе дублей.
Совет: отвечайте 200, как только событие проверено и сохранено, а медленную работу — отправку писем или создание серверов — выносите в фоновые задачи. Медленные обработчики вызывают тайм-ауты, а тайм-ауты — повторы.

Статусы заказа вокруг событий

Простая машина состояний предотвращает большинство ошибок: ожидает → подтверждается (по paid) → оплачен (по confirmed) → выполнен, с ветками недоплата и истёк. Разрешайте только переходы вперёд: invoice.paid, пришедший после invoice.confirmed, никогда не должен откатывать заказ назад. Поздние платежи по истёкшим счетам должны создавать запись для проверки, а не тихо переоткрывать заказ.

Неудобные случаи

  • Недоплата — сообщите клиенту точную недостающую сумму и что её можно отправить на ту же платёжную страницу; частичные платежи суммируются.
  • Переплата — выполните заказ, затем по своей политике решите: зачесть на баланс или вернуть разницу переводом.
  • Истечение — верните товар в продажу и предложите новый счёт, если клиент ещё хочет купить.
  • Не та сеть — решается поддержкой, а не кодом; чтобы этого избежать, чётко показывайте сеть на странице оплаты.
Напоминание о безопасности: никогда не размещайте секреты API или вебхуков в клиентском коде, мобильных приложениях или логике сообщений бота. Держите их на сервере, ограничьте доступ к API белым списком IP и включите двухфакторный вход в кабинет продавца.

Тестирование и мониторинг

  1. Поднимите тестовый эндпоинт — по HTTPS, с логированием заголовков и сырых тел.
  2. Вызовите каждое событие — paid, confirmed, underpaid, overpaid и expired небольшими реальными платежами.
  3. Повторите доставку — убедитесь, что обработчик игнорирует дубль.
  4. Сломайте подпись — измените один байт и проверьте, что запрос отклонён.
  5. Смотрите логи доставки — кабинет показывает каждую попытку, код ответа и хеш транзакции.
  6. Настройте оповещения — всплеск ответов не 2xx означает, что заказы не выполняются.

Боты и платные сообщества устроены так же; как это ложится на чат, показано в статье приём криптоплатежей в Telegram-боте.

Вебхуки в mistKET

mistKET отправляет подписанные HMAC вебхуки для каждого статуса счёта, повторяет неудачные доставки с нарастающими интервалами и показывает в кабинете логи доставки, ожидаемые и полученные суммы и хеши транзакций. Запросы к API подписываются так же, поэтому одна вспомогательная функция покрывает оба направления.

5событий счёта
HMACподписи SHA-256
Часыавтоповторов

Примеры запросов и вебхуков — в разделе для разработчиков; посмотрите тарифы и управляйте ключами через вход для продавцов. Чтобы получить доступ, подайте заявку в Telegram — @mistnetwork.

Частые вопросы

Что такое вебхук криптоплатежа?
HTTP-запрос, который шлюз отправляет на ваш сервер при каждом изменении статуса счёта: платёж обнаружен, подтверждён, недоплачен или истёк.
Какое событие должно запускать выполнение заказа?
Событие confirmed — после нужного числа подтверждений в сети. Событие paid лишь означает, что перевод обнаружен.
Как проверить вебхук mistKET?
Пересчитайте HMAC-SHA256 по метке времени, точке и сырому телу с вашим секретом, сравните за постоянное время с X-Mistket-Signature и отклоняйте устаревшие метки времени.
Почему один и тот же вебхук пришёл дважды?
Доставки повторяются, если эндпоинт не успел ответить или вернул ошибку. Сделайте обработчик идемпотентным: проверяйте статус заказа перед выполнением.
Что будет, если мой сервер недоступен?
Вебхуки повторяются с нарастающими интервалами несколько часов, а статус счёта всегда можно проверить через API или в кабинете продавца.

Похожие статьи