Post #11797
347
☀Объяснение:
1. Почему возникают дубликаты?
Платёжные системы часто работают по семантике at-least-once (как минимум один раз). Это означает, что при сомнении (таймаут, неполучение подтверждения, перезапуск) шлюз может отправить callback повторно. Сетевые сбои, перезагрузки серверов — обычная причина дублей. Если ваша система списывает деньги при каждом вызове, клиент заплатит дважды.
2. Идемпотентность — единственное решение
Идемпотентная операция при повторном выполнении с теми же входными данными не меняет состояние системы. В данном случае: обработав первый callback, вы списываете деньги и запоминаете уникальный ID транзакции (например, payment_id). При повторном callback вы проверяете: если payment_id уже обработан — просто возвращаете успех, не списывая повторно. Технически это делается через хранение ID в Redis (с TTL) или в БД с уникальным индексом.
3. Почему не подходят другие варианты?
A (увеличить таймаут) — не влияет на дубликаты, таймаут отвечает за время ожидания ответа от вашего сервера шлюзом, но шлюз может дублировать и без таймаута.
C (отключить повторные callback на стороне шлюза) — невозможно, это внутренняя логика шлюза. Даже если бы можно было, вы снизите надёжность: при временном сбое уведомление потеряется навсегда.
D (ручной разбор) — не масштабируется, при тысячах платежей в день ручная проверка невозможна, бизнес не успеет.
4. Реальный кейс
Интернет-магазин подключил платёжный шлюз. В первые часы у нескольких клиентов списались деньги дважды. Анализ показал, что шлюз отправлял дубликат при задержке ответа магазина более 2 секунд. Внедрение идемпотентности на основе transaction_id позволило автоматически отсекать дубликаты без потери надёжности.
5. Что должен зафиксировать аналитик в требованиях
«Обработка callback-ов должна быть идемпотентной. Для этого использовать уникальный идентификатор платежа, предоставляемый шлюзом (поле payment_id), и хранить обработанные ID в Redis или БД с временем жизни не менее 24 часов».
«При повторном получении callback-а с уже обработанным ID система должна возвращать HTTP 200 OK без повторного выполнения бизнес-логики».
«Для защиты от гонок использовать блокировки или атомарные операции (например, SET NX в Redis)».
Вывод: Идемпотентность — обязательное требование для любой интеграции, где внешняя система может повторять запросы (а это почти все платёжные, SMS, email-сервисы). Без неё дублирование неизбежно приведёт к финансовым потерям и недовольству клиентов.
1. Почему возникают дубликаты?
Платёжные системы часто работают по семантике at-least-once (как минимум один раз). Это означает, что при сомнении (таймаут, неполучение подтверждения, перезапуск) шлюз может отправить callback повторно. Сетевые сбои, перезагрузки серверов — обычная причина дублей. Если ваша система списывает деньги при каждом вызове, клиент заплатит дважды.
2. Идемпотентность — единственное решение
Идемпотентная операция при повторном выполнении с теми же входными данными не меняет состояние системы. В данном случае: обработав первый callback, вы списываете деньги и запоминаете уникальный ID транзакции (например, payment_id). При повторном callback вы проверяете: если payment_id уже обработан — просто возвращаете успех, не списывая повторно. Технически это делается через хранение ID в Redis (с TTL) или в БД с уникальным индексом.
3. Почему не подходят другие варианты?
A (увеличить таймаут) — не влияет на дубликаты, таймаут отвечает за время ожидания ответа от вашего сервера шлюзом, но шлюз может дублировать и без таймаута.
C (отключить повторные callback на стороне шлюза) — невозможно, это внутренняя логика шлюза. Даже если бы можно было, вы снизите надёжность: при временном сбое уведомление потеряется навсегда.
D (ручной разбор) — не масштабируется, при тысячах платежей в день ручная проверка невозможна, бизнес не успеет.
4. Реальный кейс
Интернет-магазин подключил платёжный шлюз. В первые часы у нескольких клиентов списались деньги дважды. Анализ показал, что шлюз отправлял дубликат при задержке ответа магазина более 2 секунд. Внедрение идемпотентности на основе transaction_id позволило автоматически отсекать дубликаты без потери надёжности.
5. Что должен зафиксировать аналитик в требованиях
«Обработка callback-ов должна быть идемпотентной. Для этого использовать уникальный идентификатор платежа, предоставляемый шлюзом (поле payment_id), и хранить обработанные ID в Redis или БД с временем жизни не менее 24 часов».
«При повторном получении callback-а с уже обработанным ID система должна возвращать HTTP 200 OK без повторного выполнения бизнес-логики».
«Для защиты от гонок использовать блокировки или атомарные операции (например, SET NX в Redis)».
Вывод: Идемпотентность — обязательное требование для любой интеграции, где внешняя система может повторять запросы (а это почти все платёжные, SMS, email-сервисы). Без неё дублирование неизбежно приведёт к финансовым потерям и недовольству клиентов.

