Go to file
2024-08-29 00:27:07 +07:00
.github/workflows init structure 2024-08-13 17:38:40 +07:00
src add AdminDisputesHandler 2024-08-29 00:27:07 +07:00
.gitignore init structure 2024-08-13 17:38:40 +07:00
pom.xml add AdminDisputesHandler 2024-08-29 00:27:07 +07:00
README.md add readme 2024-08-27 13:44:58 +07:00

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_BAN_ON_CAPTURED и пулять состояние в в топик\тг-провайдер-бот на ручной разбор

(реализации на данный момент нет) Не все провайдеры на данный момент поддерживают работу с диспутами по API.
Предполагается такой способ действия при этой ситуации:

  1. При наличии диспутов по API у провайдеров в терминале добавляется опция — DISPUTE_FLOW_PROVIDER_API_EXIST
  2. если эта опция терминала есть, то сервис ищет роут до адаптера и отправляет запрос по трифт протоколу, иначе будет пулять в топик\тг-провайдер-бот
  3. если возникнет ошибка роута, то будет пулять в топик\тг-провайдер-бот

Используется экспоненциальный пуллинг, после которого мы считаем, что диспут протух и поллить его не надо. Опция 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 возможность повторной записи не является критичным фактором

Вызов адаптеров — пулинг на падения не влияет, но при создании предполагается, что это ответственность адаптера удостовериться, что такого диспута еще не существует.