OrderPaid пришёл, а заказ уже отменён. Кто принимает решение?
Разработчик пишет в чат: «Технически всё работает». Очередь жива, сообщение валидное, обработчик отработал без ошибок.
Но есть нюанс: пока событие OrderPaid шло по брокеру, заказ уже успели отменить.
Деньги куда-то надо девать. Возврат? Игнор? Ручная разборка? Если это заранее не согласовали в требованиях, финансовое решение принимает код. Не бизнес. Не аналитик. А случайный if в обработчике, написанный в пятницу вечером.
Как это выглядит на практике На одном из проектов отмена уходила синхронно (холд снят, статус CANCELLED), а успех от внешнего шлюза прилетал асинхронно, с задержкой в минуту.
Утром поддержка видела картину: в админке заказ «Отменён», а в финансовой витрине по нему висит «Успешная оплата». Клиент звонит со скриншотом списания.
Фраза «пусть утренняя сверка разберётся» здесь не работает. Сверка приходит Т+1, а клиент звонит сразу. Поддержка видит «Отменён» и говорит, что платежа не было. Клиент присылает выписку. Доверие потеряно, тикет эскалирован.
Что я теперь фиксирую в спецификации до кода Опыт подсказывает, что happy path работает только в презентациях. В проде деньги и статусы всегда пытаются разойтись. Поэтому в разделе интеграции я больше не пишу абстрактное «Обработать событие OrderPaid».
Там появляются конкретные правила:
-
Источник истины. Если на момент получения
OrderPaidстатус заказа =CANCELLED, система НЕ меняет его наPAID. -
Фиксация расхождения. Вместо этого создаётся запись в таблице или топике
payment_discrepancies(payment_id, order_id, время отмены, время события). -
Владелец и SLA. Чётко указано, кто и в какой срок разбирает эту очередь (автовозврат, если дорога открыта, или ручной чек оператора).
-
Идемпотентность. Отдельной строкой: повторное получение того же
OrderPaidс тем же ключом не плодит новые тикеты и не инициирует повторные движения денег.
Хорошая постановка задачи — это описание не только того, как система работает по плану, но и того, как она ведёт себя, когда всё идёт не по плану.
А как у вас решается эта гонка состояний: доверяете автоматике, отдаёте на откуп сверке или строите отдельный контур ручного разбора?