FreemiumProBusinessEnterprise

Жизненный цикл платежа

Обзор

Каждый платёж в evntflo проходит через определённую последовательность статусов. Переходы между статусами происходят автоматически на основе webhook-уведомлений от платёжного шлюза. Организатор видит текущий статус в разделе Участники и в детали регистрации.

Статусы платежа

СтатусОписание
pendingПлатёж создан, участник перенаправлен на страницу оплаты шлюза
paidДеньги получены, шлюз подтвердил оплату через webhook
failedОплата не прошла (недостаточно средств, карта заблокирована, ошибка 3D Secure)
expiredУчастник не завершил оплату в течение отведённого времени (30 минут)
refundedВозврат выполнен полностью
partially_refundedВыполнен частичный возврат

Диаграмма переходов

         создание платежа
               │
               ▼
           ┌────────┐
           │pending │
           └───┬────┘
               │
       ┌───────┼───────┐
       ▼       ▼       ▼
   ┌──────┐ ┌────┐ ┌───────┐
   │failed│ │paid│ │expired│
   └──────┘ └─┬──┘ └───────┘
              │
       ┌──────┴──────┐
       ▼             ▼
┌──────────┐  ┌──────────────────┐
│refunded  │  │partially_refunded│
└──────────┘  └──────────────────┘

Переходы необратимы: paid не может вернуться в pending, а refunded — в paid.

Бронирование (Reservation)

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

Как работает бронь

  1. Участник нажимает «Оплатить» — evntflo создаёт reservation с TTL 15 минут.
  2. Из доступного количества билетов вычитается забронированное место.
  3. Участник перенаправляется на страницу оплаты шлюза.
  4. Если оплата прошла — бронь превращается в подтверждённую регистрацию.
  5. Если TTL истёк — бронь автоматически освобождается, билет снова доступен.

Бронирование предотвращает ситуацию, когда двое участников оплачивают последний билет одновременно.

Webhook-обработка

evntflo узнаёт о результате платежа через webhook — HTTP-запрос от платёжного шлюза на серверы evntflo.

Последовательность

  1. Шлюз (ЮKassa, Точка, Telegram) отправляет POST-запрос на webhook URL evntflo.
  2. evntflo проверяет подпись запроса (каждый шлюз использует свой механизм подписи).
  3. Платёж обновляет статус в базе данных.
  4. Если статус paid — регистрация участника подтверждается, отправляется email с билетом.
  5. Если статус failed или expired — бронь освобождается.

Повторные доставки

Если evntflo не смог обработать webhook (например, вернул 5xx), шлюз повторяет запрос:

  • ЮKassa: до 10 попыток с экспоненциальной задержкой
  • Точка: до 5 попыток с интервалом 5 минут

Благодаря idempotency-ключам повторная обработка одного и того же webhook безопасна и не создаёт дубликатов.

Idempotency-защита

Каждая платёжная операция в evntflo защищена idempotency-ключом — уникальным идентификатором, который гарантирует, что операция выполняется ровно один раз.

Зачем это нужно

  • Участник случайно нажал «Оплатить» дважды — создаётся только один платёж
  • Webhook пришёл повторно из-за таймаута — статус обновляется один раз
  • Сетевой сбой прервал запрос, клиент отправил повтор — деньги не списываются дважды

Как это работает

  1. При создании платежа evntflo генерирует Idempotency-Key (UUIDv7).
  2. Ключ отправляется в заголовке запроса к шлюзу.
  3. Если шлюз получает повторный запрос с тем же ключом, он возвращает результат первой операции.
  4. evntflo кэширует ключ в Redis с TTL 24 часа.

Связь статусов платежа и регистрации

Статус платежа напрямую влияет на статус регистрации участника:

Статус платежаСтатус регистрацииЧто видит участник
pendingpayment_pending«Ожидает оплаты»
paidregistered«Зарегистрирован», получает билет на email
failedpayment_failed«Оплата не прошла», предлагается повторить
expiredexpired«Время оплаты истекло», предлагается начать заново
refundedrefunded«Возврат оформлен»

При включённой модерации между оплатой и финальным статусом registered может быть промежуточный этап проверки организатором.

Просмотр истории платежей

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

  • Текущий статус платежа
  • Метод оплаты (карта, СБП, Stars)
  • Сумма и валюта
  • Дата и время создания / оплаты / возврата
  • Idempotency-ключ (для диагностики)
  • История переходов между статусами

Для экспорта данных о платежах — Экспорт платежей и отчёты.

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

Почему платёж завис в статусе pending?
Чаще всего — участник не завершил оплату (закрыл страницу банка, не подтвердил 3D Secure). Платёж автоматически перейдёт в expired через 30 минут. Если webhook от шлюза не пришёл — проверьте настройки webhook.
Что произойдёт при повторном нажатии кнопки «Оплатить»?
Ничего плохого. Каждый платёж защищён idempotency-ключом: повторный запрос с тем же ключом не создаст дубль, а вернёт результат исходной операции.
Можно ли вручную перевести платёж в статус paid?
Да, но только для ручных платежей (наличные, безналичный перевод). Для платежей через шлюз статус обновляется автоматически через webhook.
Как долго хранится бронь (reservation)?
По умолчанию 15 минут. За это время участник должен завершить оплату, иначе бронь освобождается и билет снова становится доступен.