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

Разделите два вида повторов
Первый повтор возникает при создании операции: двойной клик или потерянный ответ. Второй — при обработке события: повторная доставка или параллельные обработчики.
Решение одного не устраняет другое. Блокировка кнопки полезна для интерфейса, но не защищает сервер от сетевых повторов.
- Создание: не породить лишнюю оплату.
- Подтверждение: не повторить изменение заказа.
- Исполнение: не выдать результат повторно.
Определите ключ логической операции
Ключ должен соответствовать одной бизнес-задаче, а не каждому сетевому запросу. Храните его связь с заказом, параметрами и результатом.
Поддержку идемпотентных ключей на стороне KartaPay нужно проверить по документации. Не добавляйте выдуманный заголовок, рассчитывая, что сервис автоматически начнёт его учитывать.
Проверьте перед следующим шагом
- Ключ стабилен для повтора одной задачи.
- Изменение параметров обнаруживается.
- Результат запроса сохраняется.
- Внешний механизм подтверждён документацией.
Обрабатывайте неопределённый результат
Таймаут не доказывает, что операция не создана. Сохраните состояние неопределённости и выясните результат доступным способом, прежде чем начинать новую попытку.
Если контракт позволяет безопасно повторить тот же запрос, соблюдайте его правила. Если нет — используйте документированную сверку и процедуру разбора, а не бесконечные повторы.
- 1Зафиксировать попытку.
- 2Сохранить известный результат.
- 3При таймауте отметить неопределённость.
- 4Сверить состояние перед новой попыткой.
Защититесь от параллельных событий
Проверка «если ещё не оплачено» без атомарности допускает гонку: два обработчика увидят одно состояние и оба начнут выдачу.
Используйте ограничения уникальности и транзакционный переход состояния в своём хранилище. Конкретный механизм выбирайте под архитектуру, сохраняя единственность бизнес-эффекта.
- Уникальная привязка внешней операции.
- Атомарный переход заказа.
- Защита от повторной задачи исполнения.
- Безопасный ответ на уже обработанное событие.
Не теряйте выдачу между шагами
Если пометить заказ оплаченным, а затем упасть до отправки задания, покупка останется без результата. Если сначала отправить результат, а потом упасть до записи, повтор может выдать его снова.
Надёжная постановка задачи рядом с фиксацией оплаты и идемпотентный исполнитель уменьшают эти риски. Отдельно учитывайте успешность внешнего действия и возможность его повторной проверки.
Проверьте перед следующим шагом
- Задача не теряется при перезапуске.
- Исполнитель проверяет уже выполненное.
- Сбой выдачи виден.
- Повтор не требует новой оплаты.
Проверьте поведение под сбоями
Отправьте одинаковое событие последовательно и параллельно. Остановите обработчик между фиксацией оплаты и выдачей, затем восстановите его.
Подпись вебхука остаётся обязательной: идемпотентность не делает поддельное событие достоверным. Проверяйте безопасность и устойчивость как отдельные свойства.
Проверьте перед следующим шагом
- Повтор не меняет итог повторно.
- Параллельность не создаёт дубль.
- После сбоя выдача восстанавливается.
- Поддельное событие отклоняется до бизнес-действий.