(Копия статьи "Под капотом ПО банкомата" (Автор Кирилл Орлов), расположенной в сети по адресу)
Что такое банкомат?
Любой банкомат по сути представляет собой компьютер с подключенной периферией, менеджером оборудования и собственно банковским приложением, управляющим всем этим хозяйством. Все решения по выдаче денег принимает сервер. Банкомат лишь собирает информацию от клиента и передаёт её на сервер.
Железо банкомата
Минимальный набор банкоматного железа включает в себя:
Кто же управляет всем этим зоопарком
Для того чтобы производители не мучились с написанием драйверов, которые потом никому не нужны, а разработчики софта не страдали от разнообразия решений по управлению той или иной железкой, было решено всё это дело унифицировать.
Так появился стандарт CEN/XFS либо просто XFS, что расшифровывается как eXtension For Financial Services.
Стандарт описывает клиент-серверную архитектуру состоящую из менеджера оборудования и сервисных провайдеров (читай драйвера устройств), которыми он управляет. В терминологии стандарта «сервисный провайдер» — это библиотека, предоставляющая определенный набор функций для получения информации об устройстве и управления им. Обычно это динамическая библиотека, содержащая определенный набор стандартных функций(Open, Close, GetInfo, Execute ) каждая из которых имеет ряд специфических для конкретного устройства аргументов.
Все взаимодействие с оборудованием происходит через API XFS менеджера. К примеру, параметр Command функции Execute может иметь значение для диспенсера купюр:
WFS_CMD_CDM_DISPENSE (набор денег из кассет)
WFS_CMD_CDM_PRESENT (выдачи пачки клиенту)
Для картридера:
WFS_CMD_IDC_RETAIN_CARD (захват карты),
WFS_CMD_IDC_READ_TRACK (чтение дорожек)
Существует несколько реализаций XFS-менеджеров (в том числе с открытым исходным кодом), написанных на c++ и теоретически библиотеки сервисных провайдеров, написанные под один менеджер, так же должны подходить ко всем остальным, но по факту иногда библиотека, написанная конкретным вендором под конкретный XFS менеджер, работает только с этим менеджером.
Также существует Java XFS со своими библиотеками, не совместимыми с классическими менеджерами.
Банковское приложение
Банковское приложение — это то, что вы видите на экране, когда подходите к устройству. Оно предназначено для сбора данных от пользователя, отправки этих данных на хост (сервер) и выполнения ответа от хоста. Как и в случае с железом (XFS) есть отраслевые протоколы (NDC/DDC), по которым приложение общается с хостом, загружает конфигурацию и интерпретируют её.
Любой крупный производитель банкоматов (Wincor, NCR, Diebold) имеет свою реализацию как XFS, так и банковского приложения.
Однако на рынке есть альтернативный софт, соответствующий всем стандартам и не привязанный к конкретному вендору.
Я буду описывать банкомат на примере NDC как наиболее распространенного в России протокола, но чуть менее популярный DDC имеет схожий принцип работы.
Как же оно работает
В каждый момент времени банкомат находится в одном из режимов работы:
В режиме In service банкомат находится в одном из состояний (стейт), с номером от 001 до 999, и 25 символьной строкой-описанием.
Первый символ этой строки — тип стейта (обозначаются буквами A..Z а так же a..z и некоторыми символами (,'.?)), он определяет совокупность. Остальные 24 символа — это 8 десятичных 3-значных чисел, каждое из которых является определенной настройкой стейта (номер экрана для показа, условия перехода на стейт, список действий). Стейтов одного типа может быть любое количество.
Режим In service
При старте режима обслуживания банкомат автоматически начинает выполнять стейт 000. Обычно это стейт A (Card read state). В этом стейте банкомат отображает экран с приглашением вставить карту и переводит картридер в режим приёма. Также стейт отвечает за чтение карты и ветвление в зависимости от результатов этой операции.
Ниже пример конфигурации типичного стейта A:
000 A001001011008004002001104
000 — номер стейта
A — тип стейта (Card read state)
001 — номер экрана (Screen number)
001 — номер стейта, на который переходить в случае успешного чтения карты
011 — номер стейта, на который переходить в случае ошибок чтения карты
008 — условие чтения 1
004 — условие чтения 2
002 — условие чтения 3
001 — условие возврата карты (сразу после чтения или по завершение операции)
104 — стейт перехода, если если карта неизвестна банку
Пройдемся по параметрам более подробно:
Тип стейта — тут всё понятно: определив тип стейта, приложение знает как интерпретировать дальнешие параметры.
Номер экрана — представляет собой ссылку на строку с текстовым описанием экрана, отображающимся во время работы данного стейта.
Не каждый стейт имеет экран.
Экран может иметь номер от 000 до 999. Экраны, отличающиеся на 100, обычно резервируют под разные языки. Таким образом экран 010 и экран 210 это скорее всего разноязычные версии одного экрана. Об экранах я расскажу чуть позже.
Номер стейта перехода в случае успешного чтения карты — то, какой стейт приложение начнет выполнять в случае, если карта распознана и данные прочитаны успешно.
Помимо стейтов и экранов в банкомате есть ещё один важный конфигурационный параметр — financial institution table. Таблица финансовых институтов содержит данные о том, какие карты принадлежат какому банку, как правильно парсить данные прочитанные с дорожек карты, и что делать в зависимости от этих данных дальше. Например если карта локальная то можно выполнить один сценарий, если карта стороннего банка то нужно запретить ветку сценария с мобильными платежами и проверкой баланса.
Номер стейта перехода в случае проблем с чтением карты — если карту не получилось прочесть ни по одному из предложенных условий — переходим на стейт, указанный в этом параметре. Как правило, это стейт J (Close state) на котором мы отдаём карту, показываем экран с предложением забрать её и активируем таймер по истечению срока которого будет запущен механизм удержания карты. Стейт J также является последним стейтом в случае успешной транзакции.
Условия чтения карты (3 параметра подряд) — это битовые маски, обозначающие номера треков, которые нужно прочесть, и взаимодействие с чипом в случае его наличия.
Например, Read Chip, Read Track 2 and Track 1, Read Track 1. Если хоть одно из условий срабатывает, то остальные условия не выполняются и карта считается прочитанной. Если ни одно из условий не выполняется, карта считается непрочитанной.
Условие возврата карты — банкомат может вернуть карты сразу после прочтения, а может сделать это в конце после завершения всех операций.
Остальные стейты устроены схожим образом:
Переходя по всем этим стейтам, приложение рано или поздно доходит до стейта взаимодействия с хостом — стейта I (Transaction Request State). На этом стейте формируется запрос из данных, собранных на прошлых стейтах и отправляется на сервер. Запрос представляет собой ID Банкомата (Logical Unit Number), данные с дорожек карты, данные о предыдущих транзакциях, данных с буферов суммы, пин-блока, нажатий функциональных клавиш (FDK буфер). Данные разделяются символом разделителем. Серверное приложение получает запрос и анализирует буфер FDK – именно по содержимому этого буфера хост понимает чего хочет банкомат. После чего, в зависимости от принятого решения, отсылает ответ в котором содержатся:
В специальном буфере передается количество купюр, которое нужно выдать из каждой кассеты (если это операция снятия наличных). Именно количество купюр, потому что банкомат не знает номиналы выдаваемых денег для него это просто бумажки в кассетах.
По завершению требуемых действий приложение шлёт подтверждение на хост и переходит на указанный стейт. Как правило это уже известный нам стейт J. В случае какого-либо сбоя приложение шлёт сообщение о сбое на хост и ждёт нового Transaction Reply с переходом на новый стейт.
Теперь об экранах
Экран банкомата представляет собой поле 32х16 клеток. Экран может содержать как графическую информацию, так и текстовую, которая позиционируется относительно клеток. Шрифты могут быть двойной высоты.
Описание экрана представляет собой строку с текстом, перемежающуюся управляющимися символами, такими как очистка экрана, позиционирование курсора, размер шрифта. В большинстве современных банков сегодня текст используется только при вводе сумм, а в остальных случаях экран — это просто цельная картинка. Однако встречаются и полностью текстовые экраны.
Пример экрана, отображающего картинку из таблицы картинок (\0c\1bP2018\1b\5c)
Именно на такие экраны ссылаются параметры стейта.
Совокупность стейтов, экранов, FIT, таймеров называется сценарием банкомата. Каждый сценарий имеет свой номер. После загрузки банкомата и подключением его к сети, он шлет на хост сообщение в котором сообщает свой ID и номер конфигурации. Если конфигурацию следует обновить — хост переводит банкомат в режим «Out Of Service» и начинает грузить необходимые параметры новой конфигурации. Последним параметром идёт номер конфигурации. Схожим образом происходит загрузка ключей для шифрования пин-блока, для макирования, и мастер-ключей.