API, webhooks и backend Опубликовано 22 мая 2026 г. 10 мин чтения

Webhooks и статусы платежей: как проектировать безопасно

Практический backend-подход к платежным callback/webhook событиям и надежной смене статусов заказа.

Webhooks и статусы платежей: как проектировать безопасно

Webhook нельзя обрабатывать как обычную форму

Callback от платежной системы должен проходить проверку подлинности, суммы и состояния заказа.

Webhook gate
Validate signature, amount, currency, order, transition and duplicate delivery.

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

Минимальная проверка включает подлинность события, соответствие суммы и валюты, наличие заказа, допустимость перехода статуса и защиту от дублей. Только после этого можно менять бизнес-статус.

  • Проверить подпись или доверенный механизм провайдера.
  • Сверить сумму, валюту и order id.
  • Проверить, не финальный ли уже статус.
  • Записать raw event в журнал.
  • Вернуть провайдеру быстрый технический ответ.

Статусы должны быть конечным автоматом

Без явных правил переходов заказ может стать оплаченным, потом ожидающим, а затем ошибочным из-за позднего события.

Payment state machine
Created -> Pending -> Paid / Failed / Cancelled / Refunded.

Платежные статусы нужно описывать как конечный автомат. Есть начальные, промежуточные и финальные состояния. Финальные статусы нельзя случайно перезаписывать более старыми событиями.

Например, если заказ уже имеет статус paid, поздний pending callback не должен откатывать заказ назад. Если пришел refund, это отдельное бизнес-событие, а не просто failed.

  • Created и Pending - не финальные состояния.
  • Paid, Failed, Cancelled - финальные для оплаты.
  • Refunded/Partially refunded - отдельная ветка после успешной оплаты.
  • Любой запрещенный переход должен логироваться.

Retries и очереди защищают от временных сбоев

CRM, ERP или фискальный сервис могут быть недоступны, но платежное событие не должно потеряться.

Reliable delivery queue
Persist event, acknowledge provider, retry internal delivery with backoff.

Если после оплаты нужно отправить данные в CRM, ERP или сервис фискализации, лучше делать это через очередь. Платежный webhook сохраняется быстро, а внутренние интеграции получают событие с повторными попытками.

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

  • Сохранять событие до обработки.
  • Использовать exponential backoff для повторов.
  • Иметь dead-letter статус для ручного разбора.
  • Не повторять списание при повторе внутренней доставки.

FAQ

Webhook должен сразу менять заказ?

Он может менять заказ только после проверки подлинности, суммы, валюты, order id и допустимости перехода статуса.

Что делать, если CRM недоступна после успешной оплаты?

Сохранить платежное событие и доставлять его в CRM через очередь с повторными попытками. Оплата не должна теряться из-за временного сбоя CRM.

Можно ли принимать один webhook несколько раз?

Да, обработчик должен быть идемпотентным. Повтор события не должен создавать повторные заказы, чеки или статусы.