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

Идемпотентность означает, что повтор одной логической операции не создаёт дополнительного бизнес-эффекта. В платежах она нужна и при запросах, и при обработке уведомлений.

API и разработка
API и разработка
Идемпотентность платежей
Редакция KartaPay5 мин чтенияОпубликовано: Обновлено:
Идемпотентность платежей: как избежать повторной выдачи — иллюстрация KartaPay

Разделите два вида повторов

Первый повтор возникает при создании операции: двойной клик или потерянный ответ. Второй — при обработке события: повторная доставка или параллельные обработчики.

Решение одного не устраняет другое. Блокировка кнопки полезна для интерфейса, но не защищает сервер от сетевых повторов.

  • Создание: не породить лишнюю оплату.
  • Подтверждение: не повторить изменение заказа.
  • Исполнение: не выдать результат повторно.

Определите ключ логической операции

Ключ должен соответствовать одной бизнес-задаче, а не каждому сетевому запросу. Храните его связь с заказом, параметрами и результатом.

Поддержку идемпотентных ключей на стороне KartaPay нужно проверить по документации. Не добавляйте выдуманный заголовок, рассчитывая, что сервис автоматически начнёт его учитывать.

Проверьте перед следующим шагом

  • Ключ стабилен для повтора одной задачи.
  • Изменение параметров обнаруживается.
  • Результат запроса сохраняется.
  • Внешний механизм подтверждён документацией.

Обрабатывайте неопределённый результат

Таймаут не доказывает, что операция не создана. Сохраните состояние неопределённости и выясните результат доступным способом, прежде чем начинать новую попытку.

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

  1. 1Зафиксировать попытку.
  2. 2Сохранить известный результат.
  3. 3При таймауте отметить неопределённость.
  4. 4Сверить состояние перед новой попыткой.

Защититесь от параллельных событий

Проверка «если ещё не оплачено» без атомарности допускает гонку: два обработчика увидят одно состояние и оба начнут выдачу.

Используйте ограничения уникальности и транзакционный переход состояния в своём хранилище. Конкретный механизм выбирайте под архитектуру, сохраняя единственность бизнес-эффекта.

  • Уникальная привязка внешней операции.
  • Атомарный переход заказа.
  • Защита от повторной задачи исполнения.
  • Безопасный ответ на уже обработанное событие.

Не теряйте выдачу между шагами

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

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

Проверьте перед следующим шагом

  • Задача не теряется при перезапуске.
  • Исполнитель проверяет уже выполненное.
  • Сбой выдачи виден.
  • Повтор не требует новой оплаты.

Проверьте поведение под сбоями

Отправьте одинаковое событие последовательно и параллельно. Остановите обработчик между фиксацией оплаты и выдачей, затем восстановите его.

Подпись вебхука остаётся обязательной: идемпотентность не делает поддельное событие достоверным. Проверяйте безопасность и устойчивость как отдельные свойства.

Проверьте перед следующим шагом

  • Повтор не меняет итог повторно.
  • Параллельность не создаёт дубль.
  • После сбоя выдача восстанавливается.
  • Поддельное событие отклоняется до бизнес-действий.