Тема
Слой драйверов
Каждый банк говорит на своём языке: свои поля, свои статусы, свои представления о том, что значит «платёж прошёл». Интеграций больше сотни, и если бы ядро знало про каждую, оно состояло бы из одних частных случаев. Поэтому между ядром и банками стоит отдельный сервис с единым контрактом: ядро формулирует намерение — провести платёж, сделать выплату, узнать статус, — а драйвер переводит его в запрос к провайдеру и приводит ответ к нашим понятиям. Ядро не знает, с кем разговаривает: оно берёт из гейта имя драйвера и ссылку на секреты и вызывает сервис по HTTP. Устройство сервиса — в карточке drivers.
Что драйвер обязан уметь
Интерфейс один на всех, но реализовывать его целиком не требуется: драйвер переопределяет только те операции, которые поддерживает провайдер, остальные остаются нереализованными.
| Операция | Зачем нужна |
|---|---|
| Признак «карту не собираем» | Отвечает, идёт ли платёж картой или через форму банка; от ответа зависит, какую операцию вызовет ядро |
| Платёж картой | Отправить в банк карточный платёж и вернуть результат либо данные для 3DS |
| Платёж через форму банка | Увести плательщика туда, где он подтвердит операцию сам: страница банка, QR, приложение |
| Выплата | Провести перевод в обратную сторону, по реквизитам получателя |
| Запрос статуса | Спросить у провайдера текущее состояние операции; общий метод для всех типов транзакций |
| Обработка вебхука | Принять уведомление провайдера, обычно — просто переспросить статус |
| Завершение после 3DS | Дожать платёж, когда плательщик вернулся со страницы банка |
| Возврат | Оформить возврат или отмену по исходной транзакции |
Сверх этого набора есть возможности, которые включаются отдельно: рекуррентные списания без участия плательщика, двухстадийные операции с подтверждением и отменой, эмиссия и погашение электронных денег, запрос баланса гейта, расчёт комиссии провайдера, повторная отправка одноразового кода, региональные переводы. Их ядро вызовет, только если гейт их поддерживает.
Поля обработки: как драйвер возвращает данные в ядро
Ответ драйвера — это не только статус. Вместе с ним приходит набор полей обработки: плоский словарь строк, в котором драйвер сообщает всё, что ядру нужно знать о ходе операции. Формат выбран сознательно: он позволяет добавить провайдеру своё поле, не меняя контракт для остальной сотни интеграций. Так возвращаются сумма и валюта, которые реально списываются (они могут отличаться от запрошенных мерчантом, если гейт работает в другой валюте); идентификатор операции у провайдера, по которому потом ищут транзакцию при возврате и запросе статуса; стадия, в которую ядро переведёт транзакцию; счётчик переспросов.
Отдельная роль — редирект. Когда банк требует 3DS, драйвер кладёт в поля обработки либо адрес страницы аутентификации, либо готовую HTML-форму для браузера плательщика. Ядро не разбирает, что внутри: оно передаёт это мерчанту или плательщику на промежуточной странице.
Неопределённость — это «в обработке», а не отказ
Статусов у драйвера три: успех, отказ и «в обработке». Главное правило слоя: отказ ставится только тогда, когда провайдер явно отказал или мы до него не дошли.
Явный отказ — это документированный отрицательный статус, известный код ошибки или понятный по смыслу ответ вроде «карта не поддерживается». Сюда же относится наша собственная проверка, не пустившая запрос в банк: такой платёж банк не увидит, и закрывать его сразу безопасно.
Всё остальное — «в обработке». Таймаут, разрыв соединения, ошибка на стороне провайдера, незнакомый статус, недостающее поле в ответе: во всех этих случаях банк мог операцию провести, просто мы об этом не узнали. Закрыв такой платёж отказом, мы разойдёмся с банком по деньгам и отрежем мерчанта от настоящего результата. Обратная сторона правила: незакрытая операция обязана иметь способ дойти до определённости — вебхук или запланированный переспрос, — иначе она зависнет навсегда, см. Очереди, таймеры и отложенные задачи.
Секреты гейта
У драйвера нет своей конфигурации под конкретного мерчанта: логины, ключи, сертификаты и адреса API живут в секрете гейта в AWS Secrets Manager. Ядро передаёт в запросе не сам секрет, а ссылку на него, и драйвер забирает содержимое сам, разбирая его в описанную в коде структуру. Отсюда два правила. Первое: набор полей секрета — такой же контракт, как и интерфейс драйвера, поэтому обязательное поле не должно иметь значения по умолчанию, лучше падение на старте, чем тихая работа на подставленном значении. Второе: новая интеграция почти всегда означает новый секрет, а значит, и задачу для инфраструктурной команды. Запросы между ядром и сервисом подписаны, неподписанный не принимается — подробности в Аутентификация и подписи.
Как адресуются колбеки провайдера
Большинство провайдеров принимают адрес уведомления прямо в запросе на операцию. Драйвер строит его из базового адреса уведомлений, своего имени и идентификатора транзакции, так что по пришедшему колбеку сразу понятно, о каком платеже речь; само уведомление приходит в ядро и уже оттуда попадает к драйверу. Есть и провайдеры, у которых адрес настраивается один раз на их стороне и одинаков для всех платежей: там транзакцию ищут по содержимому уведомления, и такая интеграция требует правки не только в драйвере — см. Колбек от банка.
Как добавляется новая интеграция
Пошагово — на странице Как написать драйвер: что делает агентский скилл /new-driver и что при этом ожидается от разработчика. Что стоит знать заранее, до перехода туда: один драйвер — это один файл, а не пакет со слоями; работа начинается не с кода, а с документации провайдера и матрицы «эндпоинт — способ авторизации», потому что у одного API разные операции нередко авторизуются по-разному; почти каждая интеграция тянет за собой инфраструктурные задачи — домены провайдера в межсетевом экране и адреса, с которых он шлёт уведомления.
Почему здесь нет списка провайдеров
Список интеграций меняется быстрее любой документации, а знание о конкретном провайдере — это не строка в таблице, а несколько страниц: авторизация по каждому эндпоинту, маппинг статусов, поведение песочницы, известные грабли. Оно хранится рядом с кодом, в репозитории драйверов, и в пространстве PSP в Confluence. Здесь мы объясняем устройство слоя, а не ведём его реестр.
Куда дальше
- Платёж картой server-to-server — вызов драйвера во флоу.
- Как выбирается банк — откуда берётся гейт, чей драйвер вызывают.
- Колбек от банка — путь уведомления провайдера.
- drivers — карточка сервиса: входы, выходы, хранилища.