Введение
Приветствую вас, уважаемые читатели! Прошу прощения за столь длительное ожидание, но его величество Прокрастинация мне запрещала дописывать статью.
В предыдущей части мы рассмотрели терминал самообслуживания с точки зрения железа. Сейчас пришло время ликбеза по UI. Всё повествование будет вестись на основе стороннего ПО, вендора которого я не называю в силу определённых обязательств, но подход является общим для всех.
И так, все мы помним по картинке из предыдущей главы, что UI (далее я буду называть его дизайном) у нас основано на одной из двух технологий (в данном конкретном ПО): Adobe Flash и HTML, которое взаимодействет с ядром, которое, в свою очередь взаимодействует с физическими устройствами, такими как купюроприёмник, чековый принтер, пинпад и.д.
Как происходит взаимодействие UI и ядра ПО?
Для того, чтобы интерфейс, написанный на Flash или с использованием W3C технологий взаимодействовал с ядром терминала, ПО вызывает внутри себя через объект WebView (или аналогичные) html-страничку или ShockwaveFlash (или аналогичный) swf-файл. Вызванный таким образом объект (прим.: под объектом понимается html-страница или swf-файл) получает доступ к ряду функций ядра, необходимых для взаимодействия объекта интерфейса с ядром терминала. Функции ядра становятся доступны через ExternalInterface – интерфейс прикладного программирования (API), который обеспечивает прямую связь между объектом интерфейса и контейнером, который вызвал данный объект. Иными словами, в UI (с помощью window.external для JavaScript или ExternalInterface для ActionScript) мы можем вызывать предопределённые внешние функции ядра.
Степы, контекст, сценарии и услуги
Основными понятиями, которыми мы будем манипулировать на протяжении всей статьи являются степ, контекст, сценарии и услуга. Давайте рассмотрим что же это такое.
Услуга
Объект, содеращий информацию об оплачиваемой услуге, такую как наименование услуги, алиас, минимальная и максимальная сумма оплаты, атрибуты услуги (обязательные и необзятельные), логотип, категория и т.д.
<service id="superservice" meaning="Супер услуга" action_timeout="2" can_next="true" need_check="true" />
Сценарий
Поведение каждой услуги описывается сценарием. Сценарий представляет собой набор шагов, с помощью которых можно выполнить определённые действия. Сценарий может быть линейным и нелинейным. Линейный сценарий выполняет строго определённую последовательность шагов, по которой можно перемещаться только на шаг вперёд или назад. Нелинейный сценарий позволяет в зависимости от заданных условий перемещаться на любой шаг.
<scenario alias="superservice">
<step name="InputNumber">
...
</step>
<step name="PutMoney">
...
</step>
<step name="Print">
...
</step>
</scenario>
Степ
Степ представляет собой шаг (фактически, отдельная html-страница или swf-файл), который мы можем использовать под определённую задачу: ввод номера, вывод текстовой информации, ввод наличности и т.д. Все шаги являются предопределёнными – т.е. в сценариях вы можете использовать только определённый набор шагов, без возможности создания своих собственных. Фактически степ – это самостоятельная страница, на которой происходят заданные действия и выдаётся результат.
<step name="Print">
<option name="...">...</option>
</step>
В рассматриваемом ПО предопределёнными являются следующие шаги:
Наименование | Описание |
---|---|
MainMenu | Отображение главного меню с категориями и услугами (начальный экран). Это стартовый степ при загрузке ПО. |
Menu | Отображение меню выбора |
PutMoney | Внесение наличности. На этом степе активируется купюроприёмник и монетоприёмник. |
InputInfo | Ввод буквенно-цифровой информации с клавиатуры. На этом степе активируется клавиатура, если она есть (либо отображается на экране). |
InputNumberInfo | Ввод цифровой информации. На этом степе активируется цифровая клавиатура или отображается на экране. |
BarCode | Чтение штрихкода. На этом степе активируется сканер штрих-кодов |
ShowInfo | Отображение текстовой информации |
Печать чека. На этой степе активируется принтер. | |
Dispense | Выдача сдачи. На этой степе активируется диспенсер. |
SmartCard | Чтение и запись смарт-карт. На этом степе активируется считыватель карт (бесокнтактный или любой другой установленный и настроенный) |
EnterCardAndPin | Чтение банковской карты и пинкода. Активируется устройство чтение карт и пинпад. |
CardOperation | Операция по банковской карте. Непосредственно транзакция по списыванию средств. |
RunApp | Запуск стороннего приложения. |
Custom | Запуск своего шага. |
Параметры степа
Каждый степ имеет свои параметры для настройки под конкретный сценарий использования.
<option name="logo">logo/superservice.png</option>
Иерархия объектов
Ниже представлена иерархия взаимосвязей с рассмотренными выше объектами:
config.xml
Все настройки платёжного приложения хранятся в БД. Изменения этих настроек производятся с помощью одного единственного файла config.xml в котором описываются все возможные сценарии, чеки и параметры шагов. Этот файл парсится и записывается в БД при загрузке ПО. Файл config.xml поделён на следующие логические блоки:
Список услуг. В этом блоке описываются все услуги, которые доступны платёжному терминалу с указанием минимальной и максимальной суммы оплаты.
Справочник языков. Перечень доступных языков интерфейса с указанием идентификатора, наименования и активного по умолчанию языка.
Описание степов сценариев. Перечень доступных степов с указанием на источник (источником может являться как файл, так и некоторый идентификатор, который будет вами обрабатываться для отображения конкретного шага).
Параметры печати чеков. В блоке описывается общий для всех сценариев header и footer чека, а так же услугозависимая центральная часть чека.
Описание линейных сценариев услуг. Описание всех линейных сценариев, используемых в услугах.
Описание нелинейных сценариев услуг. Описание всех нелинейных сценариев.
Параметры степов по умолчанию. Описание настроек по умлочанию для каждого шага.
Информационные сообщения. Описание информационных сообщений с привязкой к событиям и языковым настройкам.
Взаимосвязь объектов между собой
Ранее мы рассмотрели ключевые объекты платёжной. Теперь рассмотрим как они взаимодействуют между собой на примере оплаты мобильного телефона:
При включении терминального ПО происходит запрос (1) и получение (1.1) справочников доступных услуг. В этих справочниках содержатся такая информация как минимальная сумма платежа, максимальная сумма платежа, название услуги, идентификатор и прочие. После чего на экран выводится главное меню со списком категорий и услуг. Далее плательщик, подойдя к терминалу выбирает нужную ему услугу «Оплата мобильного телефона» (2). Дизайн отправляет информацию о выбранной услуге ядру (2.1), который в свою очередь ищет наличие данной услуги и сценария. После того, как услуга найдена, происходит инициализация сценария и отправка информации для отображения первого шага (в нашем случае InputInfo) (2.1.1). Информация, которую ядро отправляет для отображения степа содержит в себе источник шага и настройки, с которыми необходимо его запустить. После получения этих данных дизайн формирует шаг и выводит его на экран (2.1.1.1). Плательщик вводит номер (3), и дизайн информирует ядро о завершении степа, и передаёт ядру данные (3.1). После получения данных ядро проверяет корректность переданной информации и передаёт новые данные для инициализации степа ввода купюр (PutMoney)(3.1.1). Данный степ активирует устройство ввода денег (будь то купюроприёмник или монетоприёмник). Дизайн из полученных данных формирует вид и отображает его. Во время приёма купюр и/или монет ядро информирует дизайн об изменениях (4.1) для отображения актуальной информации (4.1.1) о внесённых средствах. После завершения ввода купюр, плательщик нажимает «Оплатить» на экране (5) для завершения оплаты. Дизайн информирует ядро о завершении степа (5.1). Ядро посылает команду чековому принтеру на печать чека (5.1.1) и вызывает отображение шага «Print» (5.1.2). Дизайн по полученным данным отрисовывает вид и отображает его на экране плательщику (5.1.2.1). Ядро отправляет информацию о платеже на платёжный сервер по https-каналу.
Заключение
Мы рассмотрели в общих чертах модель взаимодействия ядра системы и дизайна. В следующей, заключительной главе я расскажу вам о том, что у нас был флеш, почему мы от него отказались, что сейчас у нас html и в ближайшем будущем зарелизим версию на backbone с grunt-сборкой всего и вся. Надеюсь я вас не сильно утомил. В качестве бонуса прикладываю скриншоты описанного выше процесса оплаты мобильного телефона, а так же пример сценария, используемого в примере. Скриншоты обезличены по просьбе руководства. Компанию, в которой я работаю по прежнему не называю.
Буду рад ответить на интересующие вопросы!
<scenarioIntricate name="superservice">
<step name="InputNumber" id="InputNumber">
<option name="maskstringformate">[000]-[000]-[0000]</option>
<option name="namemc">logo/superservice.png</option>
<option name="label2" lng="3">Номер телефона</option>
<option name="label1" lng="3">Введите номер мобильного телефона</option>
<option name="text_back" lng="3">Назад</option>
<option name="text_mainmenu" lng="3">Главное меню</option>
<option name="text_next" lng="3">Далее</option>
</step>
<step name="PutMoney" id="PutMoney">
<option name="namemc">logo/superservice.png</option>
<option name="label1" lng="3">
<li>Внимание! При оплате сервисов в других валютах, конверсия валют производится по внутреннему курсу MyPay</li>
<li>Принимаются купюры достоинством 20 THB, 50 THB, 100 THB, 500 THB, 1000 THB</li>
<li>Максимальная сумма платежа {Payment.Service.MaxValue} THB</li>
<li>{Payment.Service.DescriptionCommission} </li>
</option>
<option name="comissionfield" lng="3">1. Внимание! Аппарат сдачи не дает </option>
<option name="introductionlabel" lng="3">Сумма зачисленная</option>
<option name="remainlabel" lng="3">Комиссия</option>
<option name="requireslabel" lng="3">Внесенная сумма</option>
<option name="text_header" lng="3">Вставьте купюры в купюроприемник</option>
<option name="text_mainmessage" lng="3">Внимательно проверьте введенные вами данные</option>
<option name="text_b_surrender" lng="3">ЗАЧИСЛИТЬ СДАЧУ С ЧЕКА (СЧИТАТЬ ШТРИХ-КОД)</option>
<option name="text_minvalue" lng="3">Минимальная сумма платежа</option>
</step>
<step name="Print" id="Print">
<option name="labelcenter"></option>
<option name="label1" lng="3">Спасибо!</option>
<option name="label2" lng="3">Сохраните чек до момента поступления денег на Ваш счет</option>
<option name="timeout">15000</option>
<option name="introductionlabel" lng="3">Сумма зачисленная</option>
<option name="remainlabel" lng="3">Комиссия</option>
<option name="requireslabel" lng="3">Внесенная сумма</option>
<option name="text_balance" lng="3">Сдача</option>
<option name="namemc">assets/superservice.png</option>
</step>
<rules>
<startstep>InputNumber</startstep>
<startstep>PutMoney</startstep>
<startstep>Print</startstep>
</rules>
</scenarioIntricate>
Автор: Devoll