Тема
drivers
Переводчик между нами и банками. Ядро формулирует намерение на своём языке — провести платёж, сделать выплату, узнать статус, вернуть деньги, — а драйвер превращает это в запрос к конкретному провайдеру и приводит его ответ обратно к нашим понятиям. Интеграций больше сотни, но интерфейс у всех один, поэтому ядро не знает, с кем именно разговаривает: оно передаёт имя драйвера и ссылку на секреты гейта, остальное — забота этого сервиса.
Стек: Kotlin, Spring Boot. Весь код живёт в одном репозитории и одном модуле: один драйвер — один файл.
Чего не делает
Не принимает решений: не выбирает гейт, не строит каскад, не считает комиссию, не меняет баланс и не хранит транзакцию. Всё, что он знает о платеже, приходит в теле запроса от ядра и умирает вместе с ответом. Не смотрит наружу: публичного доступа к драйверам нет, даже вебхук провайдера сначала попадает в ядро и только потом приходит сюда. Не общается с мерчантом. И не верит телу вебхука: содержимое, как правило, не разбирается, а служит поводом переспросить у провайдера настоящий статус.
Входы
- Запросы ядра на операции с транзакцией: провести платёж картой или через форму банка, сделать выплату, переспросить статус, дожать платёж после возврата плательщика с 3DS, оформить возврат, провести рекуррентное списание. Каждый запрос подписан, неподписанный не принимается.
- Переданный ядром вебхук провайдера: ядро приняло его на свой адрес и пересылает драйверу, чтобы тот решил, что с ним делать.
- Операции вокруг платежей, которые тоже требуют разговора с провайдером: выпуск виртуальных карт и операции по ним, отправка и проверка кодов подтверждения, выпуск и поиск CVU для аргентинских переводов.
Выходы
- API провайдера — собственно то, ради чего сервис существует. Способ авторизации у каждого свой: от простого ключа до OAuth с подписью и взаимного TLS по сертификату.
- Сервис токенизации — забрать настоящие карточные данные, когда их нужно отправить в банк. Без этого шага у драйвера есть только токен.
- Логи взаимодействия с провайдером и сообщения для дежурных каналов уходят в Kafka, откуда их разбирают соседние сервисы.
Ответ драйвера — это не только статус. Вместе с ним возвращаются поля обработки: сколько и в какой валюте реально списано, идентификатор операции у провайдера, стадия платежа и то, что нужно показать плательщику, — адрес страницы банка или готовая форма редиректа.
Статусов всего три: успех, отказ и «в обработке». Правило, которое стоит запомнить раньше всего остального: отказ ставится только тогда, когда провайдер явно отказал или мы не дошли до него вовсе. Любая неопределённость — таймаут, пятисотка, незнакомый статус — это «в обработке», иначе система закроет платёж, который на самом деле прошёл.
Хранилища
Своей базы нет. Redis служит короткой памятью: тела полученных вебхуков, токены доступа к провайдерам и мелкие данные, нужные между двумя запросами. Секреты гейтов — логины, ключи, сертификаты — лежат в AWS Secrets Manager, драйвер достаёт их по ссылке из запроса и у себя не держит.
Участвует во флоу
- Платёж картой server-to-server — поход в банк и последующие переспросы статуса.
- Выплаты, возвраты и чарджбэки, двухстадийные платежи, рекуррентные платежи — везде, где есть внешний провайдер.
Где искать
- Репозиторий: smartcore-pci-software/drivers. Он в PCI-контуре, поэтому живёт в отдельной организации GitHub со своим remote — как с ним работать, написано в его
AGENTS.md. - Инфраструктура и сетевые связи: карточка сервиса в описании прод-контура — там он называется
drivers-service. - Публичная документация: наружу сервис не смотрит вовсе, мерчант о драйверах не знает. Публичный след их работы — только коды ошибок транзакций, в которые приводятся ответы банков.
AGENTS.md— карта репозитория: точки входа драйвера, хелперы, поля обработки, типичные грабли. Читается первым. Рядомdocs/providers/со знанием о конкретных провайдерах и.cursor/rules/с конвенциями, без которых PR не пройдёт ревью.- Как добавляется новая интеграция — скилл
/new-driver. - Общий разбор слоя — в Слой драйверов.