mirror of
https://github.com/valitydev/disputes-api.git
synced 2024-11-06 09:05:18 +00:00
df25417b6b
* rename AdminManagementServlet * add disputes-tg-bot usage * add dummy for tg bot usages * add mapping * remove texeption catcher * bumps deps, remove debug endpoint * rename * rename * disable isScheduleReadyForCreateAdjustmentsEnabled * fix tests * up pg versino * refactor ProviderRouting * add handleUnexpectedResultMapping tests cases * checkstyle * maven-site issue * bump workflow * bump workflow * bump workflow * review fixes
136 lines
13 KiB
Markdown
136 lines
13 KiB
Markdown
# disputes-api
|
||
|
||
# Технические особенности
|
||
|
||
Сервисы разделены по модулям, к которым относится данный функционал, будь то `../api/`, `../security/`
|
||
или `../schedule/`
|
||
|
||
Поэтому возможны смежные названия сервисов (как `**AttachmentsService`) , но при этом сервисы работают для разных задач,
|
||
ограниченные рамками модулей
|
||
|
||
Реализовывать отдельное оповещение нет необходимости, потому что закладываемся, что мерчант настроит получение вебхуков
|
||
по ивенту корректировки и `webhook-dispatcher` сам узнает об этом ивенте о пошлет уведомление
|
||
|
||
## Модуль `API`
|
||
|
||
Модуль внешнего доступа для создания диспутов и опроса статуса. Все действия проходят через БД, проактивного запроса к
|
||
провайдерскому `API` не происходит. Создание диспута означает лишь создание записи в БД, решение далее принимается на
|
||
уровне модуля `../schedule/`
|
||
|
||
Перед созданием нового диспута проверяем, существует ли уже какой либо открытый по данному платежу, потому что открытым
|
||
может быть только один за раз, если существует, отдаем действующий
|
||
|
||
(реализации на данный момент нет) Передача uniqID на создании\статусе диспута дает возможность проверять наличие
|
||
диспута (через опрос статуса) до этапа создания с внешнего вызова
|
||
|
||
При ошибках сервис кидает:
|
||
|
||
- `5хх`, если это отказ внешних шлюзов
|
||
- `404`, если это отсутствие данных
|
||
- `400`, если это ошибка в данных запросов
|
||
- `401`, если это отсутствие прав для доступа к `API`
|
||
|
||
При опросе диспута существует несколько значений параметра `ErrorReason`, при которых информация об диспуте не отдается
|
||
и наружу выкидывается `404`. Такое поведение возникнет, если в другом потоке `шедулатора` при обработке диспута возникли
|
||
ошибки\отказ внешних шлюзов с ключевыми данными и в рамках данного диспута проблема является непреодолимой. Единственным
|
||
способом решить данную проблему будет создание нового диспута.
|
||
|
||
## Модуль Schedule
|
||
|
||
Модуль с `шедулаторами`, которые по расписанию обрабатывают диспуты.
|
||
Все процессы в `шедулаторах` проходят в изоляциях транзакций, при исключениях возникает откат.
|
||
|
||
При обработке диспутов `шедулатор` блочит используемые айдишники на уровне запроса к базе.
|
||
Диспут у провайдера не будет создан, пока платеж находится в не финальном статусе, это ограничение на уровне `hellgate`.
|
||
Когда статус платежа
|
||
становится `captured|cancelled|failed` разрешена дальнейшая обработка диспута.
|
||
|
||
Если при финальном статусе платежа `captured` создавать на провайдере диспут является не желательной ситуацией, можно
|
||
установить опцию в терминале `DISPUTE_FLOW_CAPTURED_BLOCKED` и пулять
|
||
состояние
|
||
в топик\тг-провайдер-бот\filebeat на ручной разбор (`AdminManagement` module)
|
||
|
||
Не все провайдеры на данный момент поддерживают работу с диспутами по `API`.
|
||
Предполагается такой способ действия при этой ситуации:
|
||
|
||
1) При наличии диспутов по `API` у провайдеров в терминале добавляется опция — `DISPUTE_FLOW_PROVIDERS_API_EXIST`
|
||
2) если эта опция терминала есть, то сервис ищет роут до адаптера и отправляет запрос по трифт протоколу, иначе будет
|
||
пулять в топик\тг-провайдер-бот\filebeat
|
||
3) если возникнет ошибка роута, то будет пулять в топик\тг-провайдер-бот\filebeat
|
||
|
||
Используется экспоненциальный пуллинг, после которого мы считаем, что диспут протух и поллить его не надо.
|
||
Опция `DISPUTE_FLOW_MAX_TIME_POLLING_MIN` контролирует максимальное время пуллинга
|
||
Диспуты на проверку статуса упорядочиваются по последнему времени проверки поля `next_check_after`, берутся самые
|
||
древние
|
||
|
||
Ответственность за актуальный статус диспута несет конкретный адаптер. Решение остается за адаптером, тк детали
|
||
реализации могут отличаться в зависимости от интеграции, `disputes-api` работает уже с результатом этого процесса и
|
||
занимается обновлением статуса диспута в своей БД. При этом, при создании диспута необходимо в адаптере по возможности
|
||
проверять наличие существующего диспута, в случае отказа внешних шлюзов после вызова ручки создания диспута на адаптере.
|
||
|
||
Если по какой то причине на этапе опроса статуса `шедулатор` не найдет в БД актуальную запись об
|
||
конкретном `provider_dispute_id` (т.е. диспут в адаптере не был создан), то обработка диспута будет возвращена на этап
|
||
назад, для попытки создать диспут в адаптере заново.
|
||
|
||
Перед созданием корректировки сервис пытается найти уже созданные корректировки и найти среди них существующую
|
||
корректировку и при успехе переводит диспут в успех. Этот процесс ликвидирует ситуацию дублей корректировок.
|
||
В идеале, после создания корректировки диспут переводится в успех.
|
||
|
||
# Консистентность
|
||
|
||
Данная реализация предусматривает, что сервис при обработке не зависнет в неопределенном состоянии, а если это
|
||
произойдет, то это не повлияет на состояние данных
|
||
|
||
Критичные внешние шлююзы:
|
||
|
||
- `postgres` [RW] (хранение данных по диспутам)
|
||
- `hellgate` [RW] (запись корректировок)
|
||
- `file-storage-v2` [RW] (хранение файлов чеков диспутов)
|
||
- `dominant` [R] `bouncer` [R] `token-keeper-v2` [R] (авторизация по токену)
|
||
|
||
В модуле `API` при падении внешних узлов в общей цепочке вызовов будет откат транзакции, данные в БД не запишутся,
|
||
диспут не будет создан и наружу вернется выбранный http-код
|
||
|
||
В модуле `Schedule` при падении внешних узлов в общей цепочке вызовов будет откат транзакции, данные в БД не запишутся,
|
||
а также продусмотрена проверка `hellgate` , существует ли уже такая корректировка
|
||
|
||
Запись `file-storage-v2` не регулируется на уровня транзакции сервиса, но конкретно в случае `file-storage-v2`
|
||
возможность повторной записи не является критичным фактором
|
||
|
||
Вызов адаптеров — пулинг на падения не влияет, но при создании предполагается, что это ответственность адаптера
|
||
удостовериться, что такого диспута еще не существует.
|
||
|
||
# Модуль ручного разбора
|
||
|
||
схема такая:
|
||
после создания диспута через нашу внешнюю апишку, будет происходить несколько кейсов:
|
||
|
||
- если `CreatedDisputesService` при попытке создать диспут в провайдере понимает, что такой ручки в провайдере не
|
||
существут, отправляет на ручной разбор
|
||
- если не выставлен флаг в опциях `DISPUTE_FLOW_PROVIDERS_API_EXIST` , то тоже отправляет на ручной разбор
|
||
- если это captured платеж и выставлена опция `DISPUTE_FLOW_CAPTURED_BLOCKED` , то тоже отправляет на ручной разбор
|
||
|
||
Далее, через внутрений трифт-интерфейс саппорт получает способ манипулировать диспутом для его
|
||
обработки (`AdminManagementDisputesService`)
|
||
|
||
- Перед переводом диспута в финальный статус саппорт должен будет забиндить айди созданного диспута в провайдере через
|
||
ручку `BindCreated()`. Здесь особенность, что этот метод фильтрует возможность биндить диспуты только созданные
|
||
вручную (из `manual_created`)
|
||
|
||
Далее, в режиме ручного разбора есть опция финализации диспута в фейл (`CancelPending()`) либо в
|
||
успех (`ApprovePending()`). Здесь особенность, что в фейл можно перевести любой диспут имеющий не финальный статус, а в
|
||
успех можно перевести, только если гарантировано создан внешний диспут у провайдера (
|
||
из `pending`,`manual_pending`)
|
||
|
||
- Из за того, что для ручных диспутов добавлены отдельные
|
||
статусы `manual_pending` ,`manual_created` не происходит ситуации, что такие диспуты попадут в
|
||
таску `PendingDisputesService` которая автоматически вызывает апи провайдера для проверки статуса
|
||
|
||
# Схема аппрува корректировок
|
||
|
||
Добавить в БД для диспута колонку "IS_AUTO", по дефолту проставляем туда FALSE.
|
||
Получаем успешный статус от провайдера, пишем в БД статус READY_FOR_ADJUSTMENT.
|
||
Корректировки проводим в отдельном потоке по расписанию, как сейчас создаем и проводим диспуты (просто последний вариант
|
||
разбиваем на два отдельных). По расписанию стартует поток и автоматически проводит только те проводки, где IS_AUTO =
|
||
TRUE. В идеале саппорт/фины будут скриптом/в админке сначала проставлять TRUE.
|