API и интеграции

2 мин чтения·Опубликовано ·Обновлено

Idempotency: повторили запрос — не повторяйте платёж

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

После таймаута приложение не знает, произошла ли оплата. Ответ мог потеряться уже после списания. В этой ситуации отключённая кнопка «Оплатить» защищает только от лишнего нажатия: запрос всё равно могут повторить приложение, посредник или сотрудник поддержки.

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

Ключ относится к намерению, а не к нажатию

Для одной платёжной попытки нужен устойчивый идентификатор. Приложение сохраняет его до отправки и использует при восстановлении связи. Генерировать новый ключ после каждого таймаута — значит сообщать серверу о новой операции.

Одинаковая сумма сама по себе не признак дубля: человек вправе сделать две разные покупки. Напротив, прежний ключ с другой суммой должен вызвать проверку несовпадения. Область ключа связывают с клиентом и операцией; знание чужого ключа не должно давать доступ к результату. Эти различия разобраны в Amazon Builders’ Library.

Проверить наличие записи недостаточно

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

Внешнее списание не включается в такую транзакцию автоматически. После обрыва связи сохраняют состояние «результат неизвестен», проверяют исходную операцию у провайдера и повторяют её только по его правилам. Заводить новый платёж лишь потому, что предыдущий ответил таймаутом, опасно.

Срок хранения ключей и обработку ошибок также проверяют в документации конкретного API. Например, Stripe описывает различия своих версий API; переносить поведение одной реализации на любую другую нельзя.

Три проверки перед запуском

Для каждого случая нужно смотреть и журнал операций, и результат у провайдера. Одного сообщения «дубликат отклонён» недостаточно. Если исход нельзя установить автоматически, поддержке нужны идентификатор, ответственный за сверку и явный запрет создавать заменяющий платёж без выяснения результата.