Любая система, работающая с платежами, должна быть надежной и отказоустойчивой.
Сбои при оплате возможны — это может быть проблема с сетью, временный сбой банка или просроченная карта. Грамотная стратегия повторных попыток помогает корректно обрабатывать такие ошибки, избегая дублирования списаний.
Сейчас покажу, как это сделать.
Важная часть надежной системы повторных платежей — отслеживание их статуса. У каждой транзакции должен быть четкий статус, который определяет дальнейшие действия: повтор, возврат или эскалацию.
Типовые статусы платежа:
Статусы платежей следует сохранять в append-only таблице БД для гарантии целостности данных и упрощения диагностики.
База данных только для добавления (append-only), также называемая неизменяемой (immutable) базой данных, позволяет только добавлять новые данные в конец, без возможности изменения или удаления существующих записей.
Вот как может выглядеть простой пример таблицы отслеживания статусов платежей:
При каждом изменении статуса платежа в таблицу добавляется новая строка. В колонке метаданных можно хранить дополнительную информацию, относящуюся к изменению статуса — например, сообщения об ошибках для неудачных попыток или идентификаторы транзакций для успешных платежей.
Такой подход дает несколько преимуществ:
Два компонента, которые могут помочь, — это очередь повторных попыток (Retry Queue) и очередь недоставленных сообщений (Dead Letter Queue).
1. Очередь повторных попыток
2. Очередь мертвых писем (DLQ)
Крайне важно правильно определить, стоит ли повторять неудачный платеж. Эффективная стратегия повтора должна отличать временные ошибки (которые могут исчезнуть при повторной попытке) от постоянных сбоев, требующих других способов обработки.
Когда следует повторять платеж
Когда не стоит повторять платеж
Если ошибка вызвана фундаментальной проблемой в данных или системе, то лучший выбор — «Не повторять».
Хорошо продуманная система должна анализировать тип ошибки перед автоматическим повторением транзакции, чтобы обеспечить эффективность и избежать лишней обработки.
Следующие шаги иллюстрируют, как работает надежный процесс повторного платежа:
1. Произошел сбой – Платеж не проходит из-за временного или постоянного сбоя
2. Проверка возможности повтора — Система определяет, является ли ошибка временной (например, таймаут сети) или постоянной (например, недостаток средств).
3. Процесс повторной обработки — Платежи, находящиеся в очереди повторов, забираются платежной службой для повторной попытки.
4. Проверка при повторной ошибке — Если платеж по-прежнему не прошел, система повторно оценивает возможность его повторного проведения.
5. Обработка очереди мертвых писем — транзакции в DLQ требуют изучения для определения необходимости ручного вмешательства, уведомления клиента или исправления системы.
Одна из основных задач в сфере платежей — обеспечить, чтобы повторные попытки не приводили к дублированию платежей. Именно здесь на помощь приходит стратегия Exactly-Once — она гарантирует, что платеж будет обработан только один раз, даже при многократных повторных попытках.
Способы достижения этого включают:
Но это тема для отдельного поста, который я готовлю ;-)
Создание надежной системы повторных платежей необходимо для того, чтобы эффективно справляться с ошибками, избегая при этом потери прибыли и разочарования клиентов. Использование отслеживания статуса платежей, очередей повторов и очередей «мертвых писем» может помочь создать более надежную систему.
P.S. Обращаем ваше внимание на то, что у нас на сайте проходит распродажа.
Сбои при оплате возможны — это может быть проблема с сетью, временный сбой банка или просроченная карта. Грамотная стратегия повторных попыток помогает корректно обрабатывать такие ошибки, избегая дублирования списаний.
Сейчас покажу, как это сделать.
Отслеживание статуса платежа
Важная часть надежной системы повторных платежей — отслеживание их статуса. У каждой транзакции должен быть четкий статус, который определяет дальнейшие действия: повтор, возврат или эскалацию.
Типовые статусы платежа:
- Инициирован: Платежный запрос получен, но обработка еще не начата.
- Обрабатывается: Платеж находится в процессе обработки платежным шлюзом.
- Успешно завершен: Платеж был успешно проведен.
- Не выполнен: Попытка платежа завершилась неудачей.
- Ожидает повторной попытки: Платеж не прошел, но запланирована повторная попытка.
- Возвращен: Платеж был успешным, но средства были возвращены.
- Отменен: Платеж был отменен до начала обработки.

Статусы платежей следует сохранять в append-only таблице БД для гарантии целостности данных и упрощения диагностики.
База данных только для добавления (append-only), также называемая неизменяемой (immutable) базой данных, позволяет только добавлять новые данные в конец, без возможности изменения или удаления существующих записей.
Вот как может выглядеть простой пример таблицы отслеживания статусов платежей:
CREATE TABLE payment_status (
id SERIAL PRIMARY KEY,
payment_id UUID NOT NULL,
status VARCHAR(50) NOT NULL,
timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
metadata JSONB
);
При каждом изменении статуса платежа в таблицу добавляется новая строка. В колонке метаданных можно хранить дополнительную информацию, относящуюся к изменению статуса — например, сообщения об ошибках для неудачных попыток или идентификаторы транзакций для успешных платежей.
Такой подход дает несколько преимуществ:
- Журнал аудита: Обеспечивает полную историю изменений статусов, что важно для соответствия требованиям и отладки.
- Целостность данных: Поскольку существующие записи нельзя изменить, исключается риск случайного повреждения данных.
- Параллельная обработка: Упрощает работу с параллельными операциями, так как добавляются только новые данные без изменения существующих.
Ключевые компоненты системы повторных платежей
Два компонента, которые могут помочь, — это очередь повторных попыток (Retry Queue) и очередь недоставленных сообщений (Dead Letter Queue).
1. Очередь повторных попыток
- Обрабатывает временные проблемы: таймауты сети, задержки обработки
- Неудачные платежи вновь помещаются в очередь для повторной попытки после небольшой задержки.
2. Очередь мертвых писем (DLQ)
- Сохраняет постоянные ошибки или транзакции, превысившие лимит повторных попыток.
- Помогает выявлять и изолировать проблемные транзакции, вместо бесконечных повторных попыток.
Повторить или не повторить: вот в чем вопрос
Крайне важно правильно определить, стоит ли повторять неудачный платеж. Эффективная стратегия повтора должна отличать временные ошибки (которые могут исчезнуть при повторной попытке) от постоянных сбоев, требующих других способов обработки.

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

1. Произошел сбой – Платеж не проходит из-за временного или постоянного сбоя
2. Проверка возможности повтора — Система определяет, является ли ошибка временной (например, таймаут сети) или постоянной (например, недостаток средств).
- Если повтор возможен — Транзакция перемещается в Очередь повторов для повторной обработки.
- Если повтор невозможен — Ошибка фиксируется в базе для дальнейшего анализа.
3. Процесс повторной обработки — Платежи, находящиеся в очереди повторов, забираются платежной службой для повторной попытки.
4. Проверка при повторной ошибке — Если платеж по-прежнему не прошел, система повторно оценивает возможность его повторного проведения.
- Если платеж можно повторить, система повторяет попытку до определенного предела (например, 3 попытки).
- Если повторная попытка невозможна, неудачная транзакция перемещается в очередь мертвых писем (DLQ) для ручной проверки и отладки.
5. Обработка очереди мертвых писем — транзакции в DLQ требуют изучения для определения необходимости ручного вмешательства, уведомления клиента или исправления системы.
Предотвращение двойных списаний с гарантией однократной поставки (Exactly-Once Delivery)
Одна из основных задач в сфере платежей — обеспечить, чтобы повторные попытки не приводили к дублированию платежей. Именно здесь на помощь приходит стратегия Exactly-Once — она гарантирует, что платеж будет обработан только один раз, даже при многократных повторных попытках.
Способы достижения этого включают:
- Идемпотентные ключи – Гарантируют, что повторные попытки ссылаются на одну и ту же транзакцию.
- Обработка распределённых транзакций – Использование событийного подхода (event sourcing) или блокировок для предотвращения дублирующей обработки.
Но это тема для отдельного поста, который я готовлю ;-)
Заключение
Создание надежной системы повторных платежей необходимо для того, чтобы эффективно справляться с ошибками, избегая при этом потери прибыли и разочарования клиентов. Использование отслеживания статуса платежей, очередей повторов и очередей «мертвых писем» может помочь создать более надежную систему.
Иногда надежность — это просто серия хорошо управляемых повторных попыток.
P.S. Обращаем ваше внимание на то, что у нас на сайте проходит распродажа.