Идемпотентность в платёжных системах — это когда один и тот же запрос можно выполнить несколько раз, и результат будет как от одного. Звучит просто. На практике — большинство реализаций сломаны.
Классическая ошибка: используют идемпотентный ключ как UUID запроса, а не UUID операции. Пользователь нажал «Оплатить» дважды? Генерируются два разных ключа — и проходят два списания.
Правильная схема:
1. Ключ идемпотентности формируется на клиенте ДО отправки запроса
2. Включает: user_id + order_id + amount + currency (но не timestamp)
3. Хранится в БД с TTL 24-72 часа
4. При повторном запросе с тем же ключом — возвращается cached ответ, деньги не списываются
Stripe поддерживает это через заголовок Idempotency-Key. Но если ваш бэкенд упал после отправки запроса в Stripe и до записи в БД — у вас дыра. Нужна транзакционная outbox-таблица.
Ещё один кейс: webhook от Stripe может прийти дважды (at-least-once delivery). Обработчик должен проверять статус в вашей БД, а не слепо обновлять по каждому событию.
Идемпотентность — это не фича, это требование к любой платёжной интеграции.
Интеграция платежных решений
@payment_integration_ops_arb
Идемпотентность в платёжных системах — это когда один и тот же запрос можно выполнить несколько раз, и результ
Этот пост опубликован в Telegram-канале Интеграция платежных решений. Подписаться можно по ссылке: @payment_integration_ops_arb.