Достаточного много читал на ГТ и Хабре статей про банковские карты, банкоматы, и вот решил внести свой вклад. Ниже я попробую рассказать о том, как устроен банкомат с точки зрения программного обеспечения.

Что такое банкомат?


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

Железо банкомата


Минимальный набор банкоматного железа включает в себя:
  • картридер, для чтения карты клиента
  • пин-пад, для ввода пин-кода и прочей информации как, например, суммы платежа/снятия
  • функциональные клавиши по бокам (4+4) являются дополнением подключаемым к пин-паду. В некоторых современных банкоматах их заменили на тач-скрин.
  • диспенсер для выдачи денег
  • различные датчики, подсветка

Кто же управляет всем этим зоопарком


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

Так появился стандарт 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 имеет схожий принцип работы.

Как же оно работает


В каждый момент времени банкомат находится в одном из режимов работы:
  • Power Up — Загрузка
  • Offline — Нет связи с сервером, коннектимся
  • Supervisor — работает инкассатор или сервис-инженер
  • Out of service — банкомат не работает, потому что неисправен, кончились деньги, или просто кто-то в банке перевел его в этот режим.
  • In service — основной режим работы, знакомый всем тем, у кого есть банковские карты.

В режиме 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. Если хоть одно из условий срабатывает, то остальные условия не выполняются и карта считается прочитанной. Если ни одно из условий не выполняется, карта считается непрочитанной.

Условие возврата карты — банкомат может вернуть карты сразу после прочтения, а может сделать это в конце после завершения всех операций.

Остальные стейты устроены схожим образом:

  • Есть стейты для чтения суммы с клавиатуры и помещения в специальный внутренний буфер;
  • Есть стейты для чтения пин-кода пин-падом и получение затем пин-блока в специальный буфер;
  • Есть стейты для проверки введенных данных (например, если введенная сумма меньше минимальной суммы, то идет перенаправление на стейт с сообщением об ошибке);
  • Есть стейты для выбора с помощью боковых клавиш (так называемых FDK) и помещения символов этих клавиш (ABCD FGHI) в специальный 8-байтный буфур;
  • Есть стейты для обнуления и предустановки буферов.

Переходя по всем этим стейтам, приложение рано или поздно доходит до стейта взаимодействия с хостом — стейта I (Transaction Request State). На этом стейте формируется запрос из данных, собранных на прошлых стейтах и отправляется на сервер. Запрос представляет собой ID Банкомата (Logical Unit Number), данные с дорожек карты, данные о предыдущих транзакциях, данных с буферов суммы, пин-блока, нажатий функциональных клавиш (FDK буфер). Данные разделяются символом разделителем. Серверное приложение получает запрос и анализирует буфер FDK – именно по содержимому этого буфера хост понимает чего хочет банкомат. После чего, в зависимости от принятого решения, отсылает ответ в котором содержатся:
  • идентификатор действия которое нужно совершить;
  • номер экрана который нужно при этом действии показывать;
  • содержимое чека, если чек нужно напечатать;
  • стейт на который нужно перейти по завершению действия.

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

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

Теперь об экранах

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

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

Пример экрана, отображающего картинку из таблицы картинок (\0c\1bP2018\1b\5c)

Именно на такие экраны ссылаются параметры стейта.

Совокупность стейтов, экранов, FIT, таймеров называется сценарием банкомата. Каждый сценарий имеет свой номер. После загрузки банкомата и подключением его к сети, он шлет на хост сообщение в котором сообщает свой ID и номер конфигурации. Если конфигурацию следует обновить — хост переводит банкомат в режим «Out Of Service» и начинает грузить необходимые параметры новой конфигурации. Последним параметром идёт номер конфигурации. Схожим образом происходит загрузка ключей для шифрования пин-блока, для макирования, и мастер-ключей.

Вот, если вкратце, так устроен банкомат. Надеюсь кому-нибудь эта информация пригодится.

Комментарии (27)


  1. EngineerSpock
    20.07.2015 13:53

    Существует несколько реализаций XFS-менеджеров (в том числе с открытым исходным кодом), написанных на c++ и теоретически библиотеки сервисных провайдеров, написанные под один менеджер, так же должны подходить ко всем остальным, но по факту иногда библиотека, написанная конкретным вендором под конкретный XFS менеджер, работает только с этим менеджером.

    Также существует Java XFS со своими библиотеками, не совместимыми с классическими менеджерами.

    Любой крупный производитель банкоматов (Wincor, NCR, Diebold) имеет свою реализацию как XFS, так и банковского приложения.

    И как тогда добиваться совместимости?

    Однако на рынке есть альтернативный софт, соответствующий всем стандартам и не привязанный к конкретному вендору.

    Что за софт — платный или бесплатный? Ссылки, плиз, в студию.

    Так что получается, правильно ли я понимаю, что разработчик платёжного приложения для POS-терминала может просто (по идее) взять библиотеку к устройству от вендора, которая отвечает требованиям XFS-менеджера и просто юзать XFS-менеджер? И в дальнейшем при появлении нового оборудования просто подключать новые библиотеки соответствующие требованиям XFS?


    1. Jesting Автор
      21.07.2015 20:49

      Совместимости — увы никак.


  1. Razaz
    20.07.2015 14:57

    Однако на рынке есть альтернативный софт, соответствующий всем стандартам и не привязанный к конкретному вендору.


    И вы слетаете с гарантии и суппорта?


    1. Aspos
      20.07.2015 15:21
      +2

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


      1. Razaz
        20.07.2015 15:44

        А суппорт? А обновления? Драйвера? Если честно не вижe смысла париться с аналогами XFS — проще в веб стэйт отдать управление… и вендорам ок и владельцам меньше проблем.


        1. Aspos
          20.07.2015 15:47

          Водораздел идёт по XFS: вендор банкомата отвечает за работу устройства и работу драйверов до слоя XFS. Выше XFS — ответственность поставщика банкоматного софта.
          Это позволяет забыть о NDC/DDC, стэйтах-шмейтах и прочих ограничений эпохи королевы Виктории.


          1. Razaz
            20.07.2015 15:50

            Имхо как раз левый софт на банкомате — источник проблем. Это надо мониторить, обновлять и тд и тп. Почему просто не открыть веб вью стэйт и тоже забыть про стэйты?
            Вы еще забываете, что сборки ОС у вендоров свои.


            1. Aspos
              20.07.2015 15:58
              +1

              Смотря что называть «левым» софтом.
              Практика показывает, что софт компаний специализирующися на банкоматном софте внезапно оказывается лучше дефолтного софта поставляемого вместе с железом.
              Особенно это становится явно, когда в банке большая сеть, особенно, когда используются устройства нескольких вендоров.
              А если в банке несколько хостов, то дефолтный софт банкоматных вендоров уже совсем не подходит.


              1. Razaz
                20.07.2015 16:01

                Дак мой вопрос и строится вокруг идеи — зачем менять софт — когда есть браузер на банкомате. Открыли браузер, передали управление и вперед. Зачем ставить кастомный XFS? Не подскажите имена вендоров и софта?


                1. Aspos
                  20.07.2015 16:14
                  +1

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

                  Отдали браузером управление — значит еще один хост должен дублировать функционал АТМ-контроллера: транзакции, реконсиляция, аутентификация, журналирование, все эти прелести.

                  Специализированный софт (CR2, к примеру) имеет свой АТМ-контроллер, свой АТМ-клиент и общаются они по своему протоколу. Никаких NDC и прочего архаизма. В легаси-схеме устарел сам подход, когда банкомат был тупым терминалом.
                  Основные банкоматные вендоры идут дорогой замены и хоста и клиента, эмуляцией (и заменой) ISO, NDC. Есть даже инсталляции кое-где, но лет пять готовых продуктов еще не будет.

                  Радует, что все вендоры идут в одну сторону, но беда в том, что, как обычно, каждый вендор идёт чуть-чуть своей дорогой.


                  1. Razaz
                    20.07.2015 16:44

                    Проблема в том, что опять свой протокол. Как с ними интегрироваться другим вендорам?


                    1. Aspos
                      20.07.2015 17:04

                      Да, в этом беда. Нет ещё единого протокола и, мне кажется, ещё лет десять не будет.
                      Ну тот же CR2 свой проприетарный протокол открыл, но это ещё не стандарт.


                      1. Razaz
                        20.07.2015 19:58

                        Просто имхо — будущее банкоматов — это веб морда, которая требует минимального железа и обвязка к нативному апи доступному из js. Снимает кучу проблем вроде контроля целостности ПО, обновления софта как примеры.


                        1. Propheta13
                          21.07.2015 11:27

                          Это не будущее, это уже почти настоящее) (не сочтите за рекламу).


                          1. Razaz
                            21.07.2015 11:46

                            Я бы вам сказал откуда ноги там растут, но промолчу)


                            1. Propheta13
                              21.07.2015 11:49
                              +1

                              Я знаю откуда там ноги растут, я в этом проекте работаю)


                              1. Razaz
                                21.07.2015 13:21

                                ;)


  1. tushev
    20.07.2015 14:59

    Мне программирование этих стейтов чем то напомнило создание микропрограммы для ядра микропроцессора, битовые поля, адреса переходов… Я понимаю что такой подход был бы актуален лет 30 назад, когда в банкомате был совсем примитивный процессор. А почему не пришли на какие нибудь более человекопонятные скрипты?
    А есть ли какие нибудь среды разработок, которые позволяют создавать конфигурации визуальным способом? Или какие нибудь скриптовые языки которые компилируются в конфигурацию?


    1. Cobolorum
      20.07.2015 15:11
      +1

      Для все более или менее развитых хостовых систем, есть и эмуляторы которые позволяют на 80-90% оттестировать логику переходов или что вводит видит пользователь, проверить правильность таймаутов. Есть визуальные средства помогающие увидеть граф переходов по стейтам. Есть относительно примитивные редакторы для графики.
      А все остальное от лукавого. Хорошим примером является банкоматы и терминалы сбербанка. На банкоматах все ясно и понятно. А вот на терминалах смены дизайна и расположения элементов достали.
      минимализм и жесткость хорошо дисциплинирует и позволяет сосредоточится на сути, а не на дизайнерских глюках.


  1. Gorodnya
    20.07.2015 21:12

    Я тут интересный баг/фичу обнаружил: вместо PIN-кода можно ввести любые 8 цифр, даже не придётся нажимать «подтвердить» на клавиатуре — при нажатии последней цифры открывается банкоматное меню.
    Деньги снять, конечно, не удалось, но знакомые банковские сотрудники удивляются)


    1. PowerMetall
      20.07.2015 23:23

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


      1. Gorodnya
        20.07.2015 23:30

        Проверка не происходит, скорее всего, из-за настроек конкретного банка/процессинга. Потому как успел попробовать в банкомате другого банка — сработало не на 8-й, а уже на 7-й цифре.
        К тому же, читал в одной из статей тут или на Гиктаймс, что есть банкоматы, которые проверяют PIN сразу, а есть — когда только после запроса суммы.


        1. Gorodnya
          20.07.2015 23:34

          Да, вот та интересная ситуация: http://geektimes.ru/post/258978/#comment_8707976


  1. efremovaleksey
    20.07.2015 23:31

    Скажите, встроенная в банкоматы система видеонаблюдения работает независимо?


    1. Jesting Автор
      21.07.2015 02:57

      Да


      1. Propheta13
        21.07.2015 11:28

        Не согласен. Зависит таки от реализации.


        1. Aspos
          21.07.2015 12:22

          Да, на что кто горазд.

          Видел банк с 2000+ банкоматами, который внутрь каждого банкомата поставил по еще одному компу с USB-камерой, своей сетью и защищенным питанием. И это не потому что они дураки, а потому что так вышло дешевле, чем покупать софт у винкора.
          Бывает ставят софт, который берёт событие с XFS-слоя и таким образом синхронизирует видео с транзакцией.
          А бывает так, что видеонаблюдение является частью клиентского приложения и для управления, журналирования, хранения видео используется та же инфраструктура что и для транзакций.