Каждый день в магазинах мы видим разные кассы — всевозможные embedded-решения с загадочными кнопками. За такими кассами сидят кассиры, которые то и дело кричат «Галя, у нас отменааааа». Это неудобно и для кассиров, и для покупателей.  Интерфейс касс со временем становится более user friendly, а Гали уже нужны меньше, но касса всё еще остается громоздким и сложным артефактом.  Меня зовут Сарбеев Владимир, я Android-разработчик в МоемСкладе. И я уверен, что касса может быть компактной и удобной. Более того, в кассу можно превратить свой смартфон.  В МоемСкладе мы создали мобильное приложение Касса МойСклад. Это полноценная касса внутри смартфона.  Работает она так: после авторизации кассир может открывать и закрывать смены, продавать товар напрямую или по предварительным заказам, учитывать наличные. К Кассе можно подключить устройства, которые требуются в работе. Они на фото: 
1 — касса Атол Sigma 10; 2 — приложением не поддерживается, интеграция с сотрудниками 
3 — касса Атол 11Ф; 4 — терминал Verifone VX820; 5 — терминал PAX S90 
6 — касса Штрих-Нано-Ф; 7 — касса Атол 15Ф; 8 — касса Штрих-ON-LINE
9 — сканер штрихкодов; 10 — терминал PayMe; 11 — касса MSPOS-K Смартфон сам по себе не может распечатывать кассовые чеки и принимать оплату банковской картой, поэтому нужны кассы и терминалы оплаты. А аппаратный сканер требуется, если камера смартфона не подходит для полноценной замены сканера штрихкодов. Еще до релиза Кассы МойСклад мы решили, что камера камерой, но у пользователя может лежать аппаратный сканер штрихкодов, который он захочет использовать. Мы умеем работать со сканерами в виде обыкновенного HID (human interface device). После считывания штрихкода мы получаем от сканера последовательность символов. Это, пожалуй, самая простая интеграция. Самая простая, если бы не два «но». Во-первых, будучи «из коробки» сканер может передавать совсем не то, что должен. Во-вторых, не все модели сканеров сигнализируют нам, что считывание штрихкода завершено. Первое «но» решается просто: если сканер начинает передавать не то, что он должен отсканировать, нужно найти инструкцию к сканеру и настроить его с помощью сервисных штрихкодов. Обычно инструкция идет в комплекте на бумаге или в электронном виде у производителя. В ней после описания доступных настроек есть штрихкоды, которые сканируют в нужной последовательности. Так можно настроить сканер, как нужно вам.  Второе «но» — более серьезная проблема. Зоопарк сканеров обширен, и далеко не все устройства показывают окончание считанной строки. Для решения этой проблемы есть два варианта. Первый — с помощью тех же сервисных штрихкодов выставить настройку, которая будет передавать символ переноса строки после считывания. Если не повезло с моделью и первый вариант не подходит, можно задать сканеру суффикс. С помощью сервисных штрихкодов добавить в конец считанной последовательности символ, по которому можно поймать окончание ввода.  Итак, приложение есть, сканер штрихкодов подключили, но вот чек напечатать всё еще не можем. Для этого нам нужна сама касса. В МоемСкладе поддерживаем ККТ Атол и Штрих, еще MSPOS, о ней расскажу в другой статье.  Когда дело дошло до интеграции с кассой, объем железного кода стал неумолимо расти. Мы решили всю работу с подключаемым оборудованием вынести в отдельную библиотеку. Само же кассовое приложение стало клиентом, подтягивающим библиотеку через gradle. В зависимости от модели подключаться можно по USB, Bluetooth или Wi-Fi. А еще по протоколу UART, который представляет из себя жесткую сцепку кассы и Android-устройства в одном корпусе. Также у разных вендоров радикально разнятся реализации подключения клиента к кассе. Java-обертка поверх нативных библиотек .so, надстройка над опенсорсной библиотекой jPOS и даже фискальное ядро, доступ к которому осуществляется через службу с AIDL-интерфейсом (язык определения интерфейсов Android). При первых попытках интеграции одного устройства от одного производителя нас устраивала схема взаимодействия KKM Device:  Но с учетом количества реализаций драйвера, способов подключения и единообразия функционала мы решили переосмыслить работу с железом. В итоге предыдущая схема пришла к такому виду:  Т — это конкретная низкоуровневая обертка над драйвером Device Manager скрывает от клиента реализацию подключения. Достаточно создать мастера подключения, который потребует последовательно выбрать производителя кассы, тип подключения, задать настройки. В случае успешного подключения он возвращает нам объект, который реализует интерфейс KKMDevice. KKMDevice скрывает подробности работы с драйвером отдельного вендора. Wrapper’ы каждого конкретного производителя содержат в себе ссылку на драйвер T и делегаты, реализующие определенные наборы функций. Например, FiscalDelegate, NonFiscalDelegate, DeviceInfoDelegate. Отмечу несколько общих моментов интеграции: Фискальный накопитель — это устройство, которое собирает и обрабатывает информацию о торговых операциях. Может стоить дороже самой кассы. Если накопитель настроить неправильно, может потребоваться технологическое обнуление. Для этого вскрывают корпус кассы, сразу же слетает гарантия.  Итак, у нас есть интерфейс кассы, мы можем отсканировать товар по штрихкоду и распечатать чек. Осталось добавить возможность платить картой.  В нашем приложении интегрирована поддержка терминалов PayMe и Inpas. Первые подключаются по Bluetooth, а вторые можно подключить по USB или через Wi-Fi. Схема подключения терминалов оплаты очень похожа на подключение ККТ, разве что требуется дополнительная авторизация. Но есть и серьезные отличия — в обработке нештатного поведения устройства. Так в ККТ любая операция либо успешно прошла, либо нет. Если операция завершилась неудачей, ее можно попробовать провести еще раз или отменить. Всё остальное происходит без вмешательства. В случае с терминалами необходимо контролировать возможные прерывания процесса оплаты на любом шаге. Может не считаться банковская карта или на карте окажется недостаточно средств. Можно не дождаться ответа от банка или дождаться, но получить 5хх HTTP-код в ответ. А еще на любом из этапов может просто отвалиться связь.  Более того, вы не сможете выпустить адекватно работающее приложение с поддержкой терминалов Inpas без сертификации. В сертификацию входит проверка наличия и корректной работы всех пользовательских операций терминала и обработка таких событий, как отключение от сети после того как покупатель уже приложил к терминалу карточку. При тестировании терминала надо учитывать, с каким банком или платежной системой он сопряжен. В некоторых случаях даже в режиме разработки возврат денег осуществляется только через личный кабинет учетной записи, а не автоматически. Еще нужно помнить, что в процессе оплаты принимает участие и банк. К примеру, отсутствие slip-чека может возникнуть, если нет нужной настройки в личном кабинете банка.  Подключение различных устройств к Android-приложению — сложный, но интересный процесс. Мы рассказали о нем в целом, описать все препятствия, конечно, нереально.  Если у вас появились вопросы, буду рад ответить на них в комментах. Если вопросов наберется на отдельную статью, напишем :) Android разработчик