Карты, деньги, 20 интеграций: как подружить POS-терминалы и фронтенд приложения

Карты, деньги, 20 интеграций: как подружить POS-терминалы и фронтенд приложения - 1

Когда ваш бизнес становится глобальным, его приложение приходится адаптировать под новые реалии — обновлять вёрстку, добавлять переводы и изображения. Ну а если ваше приложение тесно связано со сторонним железом, то тут уже приходится включать фантазию на всю катушку.

Два года назад @rexepted написал статью о том, как мы работаем с чеками в разных странах. В ней он описал принцип работы нашей плагинной системы для соединения с разными моделями контрольно-кассовых машин (ККМ). А ещё рассказал о том, как она работает с нашим frontend-приложением через IPC-шину (inter-process communication). С того времени мы запустились ещё в 7 странах, а число наших точек увеличилось на треть — с 890 до 1200+. Благодаря нашей плагинной системе мы ни дня не потратили на интеграцию нашего софта с налоговым ПО новых стран. Этим теперь занимались команды на аутсорсе.

Однако мы добиваемся 100-процентной диджитализации опыта в наших кофейнях и ресторанах и постоянно создаём новые гаджеты для них. Так у нас появились киоски самообслуживания — им и нужна интеграция с POS-терминалами. Как и в случае с ККМ, мы сами занимались интеграцией с POS-терминалами и, выходя на новые рынки, поняли, что больше этого делать не можем.

Киоск самообслуживания

Киоск самообслуживания

К тому же мы должны были законнектить кассу ресторана с POS-терминалами. Поскольку до этого интеграция с ними была только в России, в других странах кассиры вручную вводили сумму заказа на терминале, а это тормозило приём заказа.

Кассир взаимодействует с кассой ресторана

Кассир взаимодействует с кассой ресторана

Получив новые данные и почесав головы, мы поняли, что пора! В этой статье я поделюсь нашим опытом интеграции POS-терминалов во фронтенд приложения, который, возможно, будет полезен вам. Это не руководство и ни в коем случае не призыв к действию.

Карты, деньги, 20 интеграций: как подружить POS-терминалы и фронтенд приложения - 4

Задача

Нам необходимо:

  • научить кассы и киоски принимать оплаты через единые контракты;

  • прикрутить оплату заказа не только через терминал, но и с помощью QR-кода;

  • дать возможность любой аутсорс-команде работать над нашей плагинной системой;

  • дать киоскам и кассам возможность выбирать, с каким платёжным плагином они будут работать;

  • собрать плагины двух типов Web- и Electron-.

Контракты

Контракты — это соглашения приложений или разных их частей о взаимодействии друг с другом. Они определяют набор правил и форматов данных для обеспечения корректного взаимодействия и обмена информацией между компонентами.

Для того, чтобы плагин мог взаимодействовать с кассой или киоском, нам нужны универсальные контракты — они подходят к 90% терминалов. Если коротко, то образ результата такой: одна вилка для розеток самых разных регионов.

Карты, деньги, 20 интеграций: как подружить POS-терминалы и фронтенд приложения - 5

Есть два вида контрактов: публичные и приватные. Первые — для сторонних разработчиков, а вторые — для наших приложений. Начнём с публичных.

Выделим основные методы. Пока что их два:

pay — лежит в основе всего, ведь POS-терминал должен, прежде всего, принимать оплату. Этому методу мы сообщаем сумму и тип оплаты: карта или QR.

refund — терминал должен вернуть деньги, если клиент откажется от покупки. Одним терминалам достаточно сообщить сумму покупки и приложить карту, а некоторым для возврата нужен ID транзакции или RRN.

Затем определим, что ещё умеют POS-терминалы и как мы можем их использовать в будущем. Мы собрали следующие необязательные функции:

  • отмена транзакции прямо в интерфейсе приложения для более удобного UX;

  • HealthCheck — проверка связи с терминалом;

  • получение данных о последнем платеже для возврата средств. Поможет, если оплата прошла, а информацию о ней сервис не получил или вообще не создал заказ;

  • получение статуса платежа по его идентификаторам. Очень актуально для QR-платежей;

  • закрытие банковской смены, Z-отчёт;

  • получение банковского слипа. Например, для печати через принтер ККМ, а не POS-терминала;

  • отображение настроек плагина для сохранения полезной информации в локальном хранилище. Например, IP терминала в локальной сети.

Опираясь на прошлый опыт разработки плагинных систем, мы понимали, что на старте фронтенд-приложения, всё это дело нужно инициализировать. Для этого мы добавили обязательный метод Initialize. Он возвращает функционал плагина из перечня выше и доступные способы оплаты — карта, QR-код или всё вместе. На выходе получаем такой интерфейс:

Карты, деньги, 20 интеграций: как подружить POS-терминалы и фронтенд приложения - 6

Приватные контракты IPaymentsIntegration отличаются от публичных IPaymentPlugin лишь парой новых методов. Для реализации этих контрактов мы изолируем логику общения с бэкендом и получения каких-либо данных. Например, в приватном методе Initialize мы сначала узнаём актуальную версию и тип плагина, скачиваем его и устанавливаем в зависимости от типа.

Архитектура приложения

Чтобы быстрее объяснить устройство нашей архитектуры, напомню, что у нас есть приложение кассы, написанное с помощью Electron. Оно общается с различными ККМ через IPC-коммуникацию. У киосков самообслуживания есть аналогичная Electron программа, а также iOS-приложение.

Если терминал поддерживает беспроводное соединение — например, HTTP — его можно реализовать как web-плагин. Если нужно что-то посерьезнее — проводная связь через USB или COM-порты —, то нам пригодится именно Electron плагин. Он может достучаться до «железок», а обычный браузер нет.

Ниже представлена схема взаимодействия наших frontend-приложений с платёжными плагинами:

Архитектура плагинной системы

Архитектура плагинной системы

Как это выглядит на практике? При загрузке кассы ресторана или киоска самообслуживания импортируется микрофронтенд — объект, реализующий приватные контракты IPaymentsIntegration. После этого вызывается метод Initialize. Он скачивает и устанавливает актуальную версию плагинов, доступных для текущего устройства.

Вызывая другие методы, мы уже знаем, какой плагин инициализирован. На основе его типа получаем wrapper, а он вызывает код самого плагина. Многие вещи уже реализованы в нашем микрофронтенде:

  • гарантии доставки данных до нашего бэкенда;

  • фоновые джобы, отслеживающие статус QR-платежей;

  • установка и кеширование версий плагина;

  • логирование всех операций для понимания того, что происходит с оплатой на конкретной кассе или киоске.

Как происходит разработка плагина

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

Карты, деньги, 20 интеграций: как подружить POS-терминалы и фронтенд приложения - 8

Для примера создадим тестовый web-плагин:

Карты, деньги, 20 интеграций: как подружить POS-терминалы и фронтенд приложения - 9

Видим, что файлы для нового плагина добавились. В них входят:

  • базовые файлы настройки TypeScript;

  • конфигурация eslint, чтобы код был красивый и единообразный;

  • базовая vite-конфигурация для простейшей сборки плагина.

Карты, деньги, 20 интеграций: как подружить POS-терминалы и фронтенд приложения - 10

При выполнении команды добавляется и GitHub Action. Он позволяет опубликовать версию плагина при мёрже кода в основную ветку.

Разработчики плагина могут подсматривать в соседние папки, чтобы найти лучшие решения или похихикать с чужого кода. Однако ничего изменить в них не получится — настройки доступа установлены на уровне папки. Если плагину нужны будут какие-то особые настройки, деплой или билд, то разработчики смогут модифицировать сгенерированные файлы так, как им нужно.

Код написан и протестирован на локальном стенде. Разработчики приносят Pull Request. Если в нём нет ничего криминального, то мы мёржим его в основную ветку. После успешных тестов и билда плагин публикуется в блоб-хранилище, где ему указывается актуальная версия в файле version.

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

Администрирование и настройка

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

Один POS-терминал — одна страна? Так просто? На самом деле нет. Иногда в одной стране могут быть несколько интеграций с разными терминалами. А ещё же есть оплата по QR-коду, которая идёт параллельно POS-терминалам.

В итоге мы решили собрать админку для платежей в нашей системе Dodo IS, в которой для конкретных касс и киосков указывались доступные платёжные провайдеры. Оставался всего один вопрос: где хранить логины, пароли, идентификаторы и т.д. каждого из провайдеров?

Мы вспомнили об админке для платежей в киоске — её мы собрали для старых интеграций и решили доработать. Теперь при настройке киоска — а в будущем и кассы — мы можем указать его настройки и доступных для него провайдеров.

Как это работает? Сначала нам нужно добавить к устройству тип оплаты. Подразумевается, что платёжные провайдеры есть двух видов. У первого нет никаких параметров — всё настраивается на самом устройстве, например, после указания IP терминала.

Пример простого платёжного провайдера, где не требуются дополнительные настройки

Пример простого платёжного провайдера, где не требуются дополнительные настройки

Второй вид посложнее. Ему нужны настройки и секретная информация, такая как в примере с KaspiQR.

Пример QR-провайдера, которому нужны дополнительные настройки для работы с плагином

Пример QR-провайдера, которому нужны дополнительные настройки для работы с плагином

Как это выглядит в интерфейсе настроек:

Карты, деньги, 20 интеграций: как подружить POS-терминалы и фронтенд приложения - 13

Всё идеально?

Не совсем. Периодически нам придётся работать над соединением плагинов и наших девайсов. Например, если аутсорс-команда разработала плагин, а его версия подтянулась в блоб, нам нужно:

  • добавить в наш бэкенд данные нового платёжного провайдера и его мета-информацию о транзакциях — обычно transactionID и RRN, но иногда и другие данные. Так мы сможем хранить всю информацию в нашей базе данных в нормальном виде;

  • указать настройки, которые поддерживает платёжный провайдер. В большинстве случаев достаточно указать локальный IP терминала на самом устройстве. Однако оплаты по QR-коду требуют логины и пароли для общения с сервисами банка и определением счёта, на который нужно зачислить средства;

  • добавить платёжный провайдер в админку, чтобы привязать его к конкретному устройству и настроить;

  • указать в плагинной системе местонахождение плагина для конкретного платёжного провайдера.

Однако это просто рутина. Любой разработчик из нашей команды справится с этими задачками за 2-3 часа.

Что в итоге?

У нас есть рабочая плагинная система и несколько плагинов. Первый мы написали сами для Кыргызстана, пока собирали систему. В прод запустили их синхронно, чтобы обнаружить все проблемы на старте и пофиксить их.

Позже появился другой подрядчик для того же Кыргызстана и очень быстро написал для нас второй плагин. По итогу для этой страны уже есть выбор из двух плагинов. В зависимости от того, что предлагает тот или иной провайдер, управляющие ресторана выбирают и настраивают всё под свои нужды.

Принимать платежи с помощью QR-кодов мы учились в Казахстане. Для этого мы добавили в качестве способа оплаты KaspiQR — с этим мы тоже справились быстро.

В это же время наши аутсорс-команды, собиравшие плагины для ККМ, разработали платёжные плагины для Беларуси и Кипра. Для Беларуси, кстати, уже тестируют и планируют активно внедрять во всех ресторанах страны. А вот Кипр уже успешно работает с новой интеграцией.

Планы на будущее

Осталось всего 20 интеграций в разных странах, но на каждую мы не потратим больше 2-3 часов. Теперь новые страны смогут открываться без нашего участия, а мы сможем сфокусироваться на других задачах и проектах.

В будущем хотим попробовать устройства 2 в 1. Они часто встречаются, когда мы ищем платёжных провайдеров в других странах. Эти устройства умеют принимать оплату, фискализировать и печатать чеки. Конечно, их пока нельзя привязать к нашим плагинным системам, но, возможно, мы подумаем о том, как их применять в наших реалиях. Но об этом уже как-нибудь в другой раз…

Автор: VasilkovN

Источник

Оставить комментарий