Skip to content

Слой драйверов

Каждый банк говорит на своём языке: свои поля, свои статусы, свои представления о том, что значит «платёж прошёл». Интеграций больше сотни, и если бы ядро знало про каждую, оно состояло бы из одних частных случаев. Поэтому между ядром и банками стоит отдельный сервис с единым контрактом: ядро формулирует намерение — провести платёж, сделать выплату, узнать статус, — а драйвер переводит его в запрос к провайдеру и приводит ответ к нашим понятиям. Ядро не знает, с кем разговаривает: оно берёт из гейта имя драйвера и ссылку на секреты и вызывает сервис по HTTP. Устройство сервиса — в карточке drivers.

Что драйвер обязан уметь

Интерфейс один на всех, но реализовывать его целиком не требуется: драйвер переопределяет только те операции, которые поддерживает провайдер, остальные остаются нереализованными.

ОперацияЗачем нужна
Признак «карту не собираем»Отвечает, идёт ли платёж картой или через форму банка; от ответа зависит, какую операцию вызовет ядро
Платёж картойОтправить в банк карточный платёж и вернуть результат либо данные для 3DS
Платёж через форму банкаУвести плательщика туда, где он подтвердит операцию сам: страница банка, QR, приложение
ВыплатаПровести перевод в обратную сторону, по реквизитам получателя
Запрос статусаСпросить у провайдера текущее состояние операции; общий метод для всех типов транзакций
Обработка вебхукаПринять уведомление провайдера, обычно — просто переспросить статус
Завершение после 3DSДожать платёж, когда плательщик вернулся со страницы банка
ВозвратОформить возврат или отмену по исходной транзакции

Сверх этого набора есть возможности, которые включаются отдельно: рекуррентные списания без участия плательщика, двухстадийные операции с подтверждением и отменой, эмиссия и погашение электронных денег, запрос баланса гейта, расчёт комиссии провайдера, повторная отправка одноразового кода, региональные переводы. Их ядро вызовет, только если гейт их поддерживает.

Поля обработки: как драйвер возвращает данные в ядро

Ответ драйвера — это не только статус. Вместе с ним приходит набор полей обработки: плоский словарь строк, в котором драйвер сообщает всё, что ядру нужно знать о ходе операции. Формат выбран сознательно: он позволяет добавить провайдеру своё поле, не меняя контракт для остальной сотни интеграций. Так возвращаются сумма и валюта, которые реально списываются (они могут отличаться от запрошенных мерчантом, если гейт работает в другой валюте); идентификатор операции у провайдера, по которому потом ищут транзакцию при возврате и запросе статуса; стадия, в которую ядро переведёт транзакцию; счётчик переспросов.

Отдельная роль — редирект. Когда банк требует 3DS, драйвер кладёт в поля обработки либо адрес страницы аутентификации, либо готовую HTML-форму для браузера плательщика. Ядро не разбирает, что внутри: оно передаёт это мерчанту или плательщику на промежуточной странице.

Неопределённость — это «в обработке», а не отказ

Статусов у драйвера три: успех, отказ и «в обработке». Главное правило слоя: отказ ставится только тогда, когда провайдер явно отказал или мы до него не дошли.

Явный отказ — это документированный отрицательный статус, известный код ошибки или понятный по смыслу ответ вроде «карта не поддерживается». Сюда же относится наша собственная проверка, не пустившая запрос в банк: такой платёж банк не увидит, и закрывать его сразу безопасно.

Всё остальное — «в обработке». Таймаут, разрыв соединения, ошибка на стороне провайдера, незнакомый статус, недостающее поле в ответе: во всех этих случаях банк мог операцию провести, просто мы об этом не узнали. Закрыв такой платёж отказом, мы разойдёмся с банком по деньгам и отрежем мерчанта от настоящего результата. Обратная сторона правила: незакрытая операция обязана иметь способ дойти до определённости — вебхук или запланированный переспрос, — иначе она зависнет навсегда, см. Очереди, таймеры и отложенные задачи.

Секреты гейта

У драйвера нет своей конфигурации под конкретного мерчанта: логины, ключи, сертификаты и адреса API живут в секрете гейта в AWS Secrets Manager. Ядро передаёт в запросе не сам секрет, а ссылку на него, и драйвер забирает содержимое сам, разбирая его в описанную в коде структуру. Отсюда два правила. Первое: набор полей секрета — такой же контракт, как и интерфейс драйвера, поэтому обязательное поле не должно иметь значения по умолчанию, лучше падение на старте, чем тихая работа на подставленном значении. Второе: новая интеграция почти всегда означает новый секрет, а значит, и задачу для инфраструктурной команды. Запросы между ядром и сервисом подписаны, неподписанный не принимается — подробности в Аутентификация и подписи.

Как адресуются колбеки провайдера

Большинство провайдеров принимают адрес уведомления прямо в запросе на операцию. Драйвер строит его из базового адреса уведомлений, своего имени и идентификатора транзакции, так что по пришедшему колбеку сразу понятно, о каком платеже речь; само уведомление приходит в ядро и уже оттуда попадает к драйверу. Есть и провайдеры, у которых адрес настраивается один раз на их стороне и одинаков для всех платежей: там транзакцию ищут по содержимому уведомления, и такая интеграция требует правки не только в драйвере — см. Колбек от банка.

Как добавляется новая интеграция

Пошагово — на странице Как написать драйвер: что делает агентский скилл /new-driver и что при этом ожидается от разработчика. Что стоит знать заранее, до перехода туда: один драйвер — это один файл, а не пакет со слоями; работа начинается не с кода, а с документации провайдера и матрицы «эндпоинт — способ авторизации», потому что у одного API разные операции нередко авторизуются по-разному; почти каждая интеграция тянет за собой инфраструктурные задачи — домены провайдера в межсетевом экране и адреса, с которых он шлёт уведомления.

Почему здесь нет списка провайдеров

Список интеграций меняется быстрее любой документации, а знание о конкретном провайдере — это не строка в таблице, а несколько страниц: авторизация по каждому эндпоинту, маппинг статусов, поведение песочницы, известные грабли. Оно хранится рядом с кодом, в репозитории драйверов, и в пространстве PSP в Confluence. Здесь мы объясняем устройство слоя, а не ведём его реестр.

Куда дальше

Внутренняя база знаний. Нашли неточность — поправьте страницу или заведите вопрос в разделе «Открытые вопросы».