Внешняя компонента, для работы с драйвером «Атол v.10», посредством JSON-заданий.
Описание JSON заданий, можно посмотреть на официальном сайте атол: http://integration.atol.ru/api/#json-tasks
Так как атоловский "WEB сервер", работал не стабильно и зависал через 2 часа работы, решил написать свою компоненту.
Компонента позволяет - проверить состояние смены, и оправить JSON-задание.
Для работы необходима библиотека "fptr10.dll" из поставки Атол "Драйвер контрольно-кассовой техники v.10" и VCREDIST 2015.
Рекомендую хранить библиотеку в общем макете для "32bit" и "64bit" систем.
Компонента ведет логи в "папка пользователя"\Documents\NativeAtolKKT.log
При вылетах и системных ошибках нужно смотреть логи.
Список JSON-заданий драйвера Атол v.10:
- Допечатать документ
- Открытие смены
- Закрытие смены
- Фискальные чеки
- Чеки коррекции
- Нефискальные документы
- X-отчет
- Внесения и выплаты
- Отчет о состоянии расчетов
- Печать документа из ФН
- Печать копии последнего чека
- Запрос параметров регистрации ККТ
- Регистрация / перерегистрация ККТ
- Закрытие ФН
- Открыть денежный ящик
- Установка даты и времени
- Чтение настроек ККТ
- Запись настроек ККТ
- Запрос информации о ККТ
- Запрос состояния ККТ
- Запрос состояния денежного ящика
- Запрос состояния смены
- Запрос информации о ФН
- Запрос состояния ФН
- Запрос состояния обмена с ОФД
- Запрос сменных итогов
- Запрос необнуляемых итогов
- Чтение документа из ФН
- Запрос состояния лицензий
На данный момент компонента используется для пакетной печати чеков - на один электронный (без печати) чек, уходит 3 секунды.
Внимание перед установкой параметров соединения с ККТ необходимо выполнить "Атол.Инициализировать"
Свойства:
Атол.ПарольДоступа (Атол.AccessPassword)
Синтаксис:
Атол.ПарольДоступа = "30";
Описание:
Использование: чтение, запись.
Тип: Строка.
Устанавливает параметр - пароль доступа.
Атол.ПарольПользователя (Атол.UserPassword)
Синтаксис:
Атол.ПарольПользователя = "30";
Описание:
Использование: чтение, запись.
Тип: Строка.
Устанавливает параметр - пароль пользователя.
Атол.КаналОФД (Атол.OfdChannel)
Синтаксис:
Атол.КаналОФД = "0";
Описание:
Использование: чтение, запись.
Тип: Строка.
Устанавливает параметр - канал обмена с ОФД.
Значения:
NONE = 0
USB = 1
PROTO = 2
Атол.КаналСвязи (Атол.Channel)
Синтаксис:
Атол.КаналСвязи = "2";
Описание:
Использование: чтение, запись.
Тип: Строка.
Устанавливает параметр - способ связи с ККТ.
Значения:
COM = 0
USB = 1
TCPIP = 2
BLUETOOTH = 3
Атол.КомСкорость (Атол.BaudRate)
Синтаксис:
Атол.КаналСвязи = "9600";
Описание:
Использование: чтение, запись.
Тип: Строка.
Устанавливает параметр - скорость работы ККТ по RS232.
Значения:
BR_1200 = 1200
BR_2400 = 2400
BR_4800 = 4800
BR_9600 = 9600
BR_19200 = 19200
BR_38400 = 38400
BR_57600 = 57600
BR_115200 = 115200
BR_230400 = 230400
BR_460800 = 460800
BR_921600 = 921600
Атол.КомБит (Атол.Bits)
Синтаксис:
Атол.КомБит = "8";
Описание:
Использование: чтение, запись.
Тип: Строка.
Устанавливает параметр - количество бит в байте канала RS232.
Значения:
BITS_7 = 7
BITS_8 = 8
Атол.КомСтопБит (Атол.StopBits)
Синтаксис:
Атол.КомСтопБит = "1";
Описание:
Использование: чтение, запись.
Тип: Строка.
Устанавливает параметр - количество стоп-битов канала RS232.
Значения:
SB_1 = 0
SB_1_5 = 1
SB_2 = 2
Атол.КомЧетность (Атол.Parity)
Синтаксис:
Атол.КомЧетность = "0";
Описание:
Использование: чтение, запись.
Тип: Строка.
Устанавливает параметр - четность канала RS232.
Значения:
PARITY_NO - нет = 0
PARITY_ODD - четность = 1
PARITY_EVEN - нечетность = 2
PARITY_MARK - установлена = 3
PARITY_SPACE - сброшена = 4
Атол.КомПорт (Атол.ComFile)
Синтаксис:
Атол.КомПорт = "1";
Описание:
Использование: чтение, запись.
Тип: Строка.
Устанавливает параметр - номер порта.
Значения: идентификатор порта. Для Windows - номер COM-порта (например, "15" или "COM15").
Для Linux - путь к TTY-файлу (например, "/dev/ttyS5" или "/dev/ttyACM0").
Атол.ЛинуксПутьКУСБ (Атол.UsbDevicePath)
Синтаксис:
Атол.ЛинуксПутьКУСБ = "auto";
Описание:
Использование: чтение, запись.
Тип: Строка.
Устанавливает параметр - расположение USB-устройства в системе (только Linux).
Значения: расположение USB-устройства в системе (только Linux).
Если настройка не указана, имеет значение "auto" или пустое значение, то поиск и подключение к устройству будет проводиться по известным драйверу VendorID и ProductID.
На Windows подключение всегда ведется по VendorID и ProductID.
Атол.ИПАдрес (Атол.IPAddress)
Синтаксис:
Атол.ИПАдрес = "192.168.1.25";
Описание:
Использование: чтение, запись.
Тип: Строка.
Устанавливает параметр - IP-адрес ККТ.
Значения: Может быть как ip-адресом, так и hostname-ом.
Атол.ИППорт (Атол.IPPort)
Синтаксис:
Атол.ИППорт = "5555";
Описание:
Использование: чтение, запись.
Тип: Строка.
Устанавливает параметр - IP-порт ККТ.
Значения: 1-65535
Атол.МАКАдрес (Атол.MACAddress)
Синтаксис:
Атол.МАКАдрес = "FF:FF:FF:FF:FF:FF";
Описание:
Использование: чтение, запись.
Тип: Строка.
Устанавливает параметр - Bluetooth MAC-адрес ККТ.
Значения: Bluetooth MAC-адрес ККТ.
Устройство должно быть предварительно сопряжено с хостом средствами ОС.
Атол.Ошибка (Атол.GetError)
Синтаксис:
Сообщить(Атол.Ошибка);
Описание:
Использование: чтение.
Тип: Строка.
Возвращает последнюю ошибку компоненты.
Атол.КодОшибки (Атол.GetErrorCode)
Синтаксис:
Сообщить(Атол.КодОшибки);
Описание:
Использование: чтение.
Тип: Целое число.
Возвращает код ошибки, драйвера Атол. (используется как проверка на "ошибок нет" = 0)
Описание кодов, можно посмотреть в документации: http://integration.atol.ru/api/#f9886ca2bc
Атол.СостояниеСоединения (Атол.Opened)
Синтаксис:
Сообщить(Атол.СостояниеСоединения);
Описание:
Использование: чтение.
Тип: Булево.
Возвращает "истина" если соединение с ККТ установлено, иначе "ложь".
Атол.СостояниеСмены (Атол.Shift_State)
Синтаксис:
Сообщить(Атол.СостояниеСмены);
Описание:
Использование: чтение.
Тип: Целое число.
Возвращаемое значение:
Смена открыта = 0
Смена закрыта = 1
Смена истекла = 2
Функции:
Атол.Инициализировать (Атол.Initialize)
Синтаксис:
Атол.Инициализировать(<ПутьКбиблиотеке_fptr10.dll>);
Параметры:
<ПутьКбиблиотеке_fptr10.dll> - путь к библиотеке драйвера Атол 10, на диске.
Возвращаемое значение: булево, (истина - успех)
Описание:
Подключает библиотеку (fptr10.dll) драйвера атол.
Библиотеку нужно указвать той-же разрядности что и 1С.
Атол.Открыть (Атол.Open)
Синтаксис:
Атол.Открыть();
Возвращаемое значение: булево, (истина - успех)
Описание:
Открывает соединение с ККТ.
Атол.Закрыть (Атол.Close)
Синтаксис:
Атол.Закрыть();
Возвращаемое значение: булево, (истина - успех)
Описание:
Закрывает соединение с ККТ.
Атол.ОтправитьJSON (Атол.RequestJSON)
Синтаксис:
ОтветJSON = Атол.ОтправитьJSON(<JSONтекст>);
Параметры:
<JSONтекст> - текст с JSON структурой.
Возвращаемое значение: Строка (Текст с JSON структурой.) Описание смотри в документации: http://integration.atol.ru/api/#json-tasks
Описание:
Отправляет JSON-задание на ККТ.
************************************************
Пример реализации:
ОбщийМакет.АтолККТ - двоичные данные, "zip" архив внешней компоненты.
ОбщийМакет.fptr10x64 - библиотека драйвера Атол 64 битная.
ОбщийМакет.fptr10 - библиотека драйвера Атол 32 битная.
Общий модуль: МодульККТ
Функция ПодключитьАтолКомпоненту() Экспорт
Попытка
Если НЕ ПустаяСтрока(ПараметрыСеанса.АдресХранилищаАтолСоединение) Тогда
Подключение = ПолучитьИзВременногоХранилища(ПараметрыСеанса.АдресХранилищаАтолСоединение).АтолККТ;
Возврат Подключение;
КонецЕсли;
Исключение
ПараметрыСеанса.АдресХранилищаАтолСоединение = "";
КонецПопытки;
КомпУст=Ложь;
Попытка
КомпУст=ПодключитьВнешнююКомпоненту("ОбщийМакет.АтолККТ","NativeAtol",ТипВнешнейКомпоненты.Native);
Исключение
ПоказатьОповещениеПользователя("Произошла исключительная ошибка при подключении компоненты!",,ОписаниеОшибки(),БиблиотекаКартинок.Остановить);
КонецПопытки;
Если Не КомпУст Тогда
ПоказатьОповещениеПользователя("Произошла ошибка при подключении компоненты!",,"",БиблиотекаКартинок.Остановить);
КонецЕсли;
Попытка
СисИнфо = Новый СистемнаяИнформация;
Если СисИнфо.ТипПлатформы = ТипПлатформы.Windows_x86 Тогда
ПолучитьОбщийМакет("fptr10").Записать(КаталогВременныхФайлов()+"fptr10.dll");
ИначеЕсли СисИнфо.ТипПлатформы = ТипПлатформы.Windows_x86_64 Тогда
ПолучитьОбщийМакет("fptr10x64").Записать(КаталогВременныхФайлов()+"fptr10.dll");
КонецЕсли;
Исключение
ЗаписьЖурналаРегистрации("АтолККТ",УровеньЖурналаРегистрации.Ошибка,,ОписаниеОшибки());
//Возврат Неопределено;
КонецПопытки;
АтолККТ = Новый("AddIn.NativeAtol.АтолККТ");
АтолККТ.Инициализировать(КаталогВременныхФайлов()+"fptr10.dll");
АтолККТ.КаналСвязи = "2";
АтолККТ.ИПАдрес = СокрЛП(Константы.ИпАдресСервераККТ.Получить());
АтолККТ.ИППорт = "5555";
Попытка
СтруктураАтолКомпонента = Новый Структура("АтолККТ",АтолККТ);
АдресАтолККТ = ПоместитьВоВременноеХранилище(СтруктураАтолКомпонента,Новый УникальныйИдентификатор);
ПараметрыСеанса.АдресХранилищаАтолСоединение = АдресАтолККТ;
Возврат АтолККТ;
Исключение
ЗаписьЖурналаРегистрации("АтолККТ",УровеньЖурналаРегистрации.Ошибка,,ОписаниеОшибки());
Возврат Неопределено;
КонецПопытки;
КонецФункции
Функция СформироватьJSONЧек(Продажа,ТелоЧека) Экспорт //Продажа(истина) - продажа, возврат продажи
//ТелоЧека-структура с данными чека(Оператор;Итог;ЕмаилИлиТелефон,ИмяКлиента,ИННКлиента;СтрокиЧека-массив со структурами(Наименование,Цена,Количество,Сумма,НДС))
Чек = Новый Структура;
Позиции = Новый Массив;
Оплаты = Новый Массив;
Для Каждого ПозицияЧека Из ТелоЧека.СтрокиЧека Цикл
Позиция = Новый Структура;
Позиция.Вставить("type","position");
Позиция.Вставить("name",ПозицияЧека.Наименование);
Позиция.Вставить("price",ПозицияЧека.Цена);
Позиция.Вставить("quantity",ПозицияЧека.Количество);
Позиция.Вставить("amount",ПозицияЧека.Сумма);
Позиция.Вставить("department",1);
Позиция.Вставить("paymentMethod","fullPayment");
Позиция.Вставить("paymentObject","service");
Позиция.Вставить("tax",Новый Структура("type",ПолучитьНалог(ПозицияЧека.НДС)));
Позиции.Добавить(Позиция);
КонецЦикла;
Оплаты.Вставить(0,Новый Структура("type,sum","electronically",ТелоЧека.Итог));
Чек.Вставить("type",?(Продажа = Истина,"sell","sellReturn"));
Чек.Вставить("taxationType","osn");
Чек.Вставить("electronically",Истина);
Чек.Вставить("operator",Новый Структура("name",ТелоЧека.Оператор));
Чек.Вставить("clientInfo",Новый Структура("emailOrPhone,name,vatin",ТелоЧека.ЕмаилИлиТелефон,ТелоЧека.ИмяКлиента,ТелоЧека.ИННКлиента));
Чек.Вставить("items",Позиции);
Чек.Вставить("payments",Оплаты);
Чек.Вставить("total",ТелоЧека.Итог);
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON,Чек);
ДанныеJson = ЗаписьJSON.Закрыть();
Возврат ДанныеJson;
КонецФункции
Функция ПолучитьСтруктуруJSON(ОтветJson) Экспорт
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ОтветJson);
СтруктураJson = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
fiscalParams = ЗначениеСвойстваJSON(СтруктураJson,"fiscalParams"); //чек
shiftStatus = ЗначениеСвойстваJSON(СтруктураJson,"shiftStatus"); //состояние смены
ОтветСтруктура = Новый Структура;
Если НЕ fiscalParams = Неопределено Тогда
ОтветСтруктура.Вставить("ДатаВремяЧека",ПрочитатьДатуJSON(fiscalParams.fiscalDocumentDateTime,ФорматДатыJSON.ISO));
ОтветСтруктура.Вставить("ФПДЧека",fiscalParams.fiscalDocumentSign);
ОтветСтруктура.Вставить("РегНомерККТ",fiscalParams.registrationNumber);
ОтветСтруктура.Вставить("НомерФДЧека",fiscalParams.fiscalDocumentNumber);
КонецЕсли;
Если НЕ shiftStatus = Неопределено Тогда
ОтветСтруктура.Вставить("СтатусСмены",shiftStatus.state);
ОтветСтруктура.Вставить("СменаИстечет",ПрочитатьДатуJSON(shiftStatus.expiredTime,ФорматДатыJSON.ISO));
КонецЕсли;
Возврат ОтветСтруктура;
КонецФункции
Функция ОткрытьПроверитьСмену(ИмяОператора) Экспорт
АтолККТ = ПодключитьАтолКомпоненту();
СостояниеСмены = АтолККТ.СостояниеСмены;
Если АтолККТ.КодОшибки = 0 Тогда
Если СостояниеСмены = 0 Тогда //закрыта
json="{""type"": ""openShift"",""electronically"":""true"",""operator"": {""name"": """+ИмяОператора+"""}}";
ОтветJSON = АтолККТ.ОтправитьJSON(json);
Если АтолККТ.КодОшибки = 0 Тогда
Возврат Истина;
//Результат = ПолучитьСтруктуруJSON(ОтветJSON);
Иначе
ПоказатьОповещениеПользователя("Ошибка открытия смены!",,АтолККТ.Ошибка,БиблиотекаКартинок.Остановить);
КонецЕсли;
ИначеЕсли СостояниеСмены = 1 Тогда //открыта
Возврат Истина;
ИначеЕсли СостояниеСмены = 2 Тогда //просрочена
ПоказатьОповещениеПользователя("Внимание!",,"Смена истекла",БиблиотекаКартинок.Остановить);
Возврат Ложь;
КонецЕсли;
Иначе
ПоказатьОповещениеПользователя("Ошибка проверки состояния смены!",,АтолККТ.Ошибка,БиблиотекаКартинок.Остановить);
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ЗакрытьСмену(ИмяОператора) Экспорт
АтолККТ = ПодключитьАтолКомпоненту();
СостояниеСмены = АтолККТ.СостояниеСмены;
Если АтолККТ.КодОшибки = 0 Тогда
Если НЕ СостояниеСмены = 0 Тогда
json="{""type"": ""closeShift"",""electronically"":""true"",""operator"": {""name"": """+ИмяОператора+"""}}";
ОтветJSON = АтолККТ.ОтправитьJSON(json);
Если АтолККТ.КодОшибки = 0 Тогда
Возврат Истина;
//Результат = ПолучитьСтруктуруJSON(ОтветJSON);
Иначе
ПоказатьОповещениеПользователя("Ошибка закрытия смены!",,АтолККТ.Ошибка,БиблиотекаКартинок.Остановить);
КонецЕсли;
ИначеЕсли СостояниеСмены = 0 Тогда //закрыта
Возврат Истина;
КонецЕсли;
Иначе
ПоказатьОповещениеПользователя("Ошибка проверки состояния смены!",,АтолККТ.Ошибка,БиблиотекаКартинок.Остановить);
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ПолучитьНалог(НДС) //НДС - текст
Налог = "none"; //БезНДС
Если НДС = Перечисления.СтавкиНДС.БезНДС Тогда
Налог = "none";
ИначеЕсли НДС = Перечисления.СтавкиНДС.НДС18 Тогда
Налог = "vat18";
ИначеЕсли НДС = Перечисления.СтавкиНДС.НДС20 Тогда
Налог = "vat20";
ИначеЕсли НДС = Перечисления.СтавкиНДС.НДС0 Тогда
Налог = "vat0";
ИначеЕсли НДС = Перечисления.СтавкиНДС.НДС10 Тогда
Налог = "vat10";
КонецЕсли;
Возврат Налог;
КонецФункции
Функция ЗначениеСвойстваJSON(ОбъектСвойства,Свойство)
Если ОбъектСвойства = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
ВремЗначение = Неопределено;
Если ОбъектСвойства.Свойство(Свойство,ВремЗначение) Тогда
Возврат ВремЗначение;
Иначе
Возврат Неопределено;
КонецЕсли;
КонецФункции
Функция печати чека:
функция Чек()
АтолККТ = МодульККТ.ПодключитьАтолКомпоненту();
Если АтолККТ.Открыть() Тогда
//ЕСЛИ СМЕНА ЗАКРЫТА ОТКРЫВАЕМ
Если МодульККТ.ОткрытьПроверитьСмену(Объект.Оператор.Наименование) Тогда
СтрокиЧека = Новый Массив;
Позиция = Новый Структура("Наименование,Цена,Количество,Сумма,НДС","сапоги",154.12,2,308.24, Перечисления.СтавкиНДС.БезНДС);
СтрокиЧека.Добавить(Позиция);
ТелоЧека = Новый Структура;
ТелоЧека.Вставить("Оператор","оператор1");
ТелоЧека.Вставить("ЕмаилИлиТелефон","a@a.a");//если поле будет пустым, чек распечатается.
ТелоЧека.Вставить("ИмяКлиента","Пупкин.П.П");
ТелоЧека.Вставить("ИННКлиента","12121212121");
ТелоЧека.Вставить("Итог",308.24);
ТелоЧека.Вставить("СтрокиЧека",СтрокиЧека);
//отправка чека
//ТелоЧека-структура с данными чека(Оператор;Итог;ЕмаилИлиТелефон,ИмяКлиента,ИННКлиента;СтрокиЧека-массив со структурами(Наименование,Цена,Количество,Сумма,НДС))
ОтветJSON = АтолККТ.ОтправитьJSON(МодульККТ.СформироватьJSONЧек(Продажа,ТелоЧека));
Если АтолККТ.КодОшибки = 0 Тогда
//ошибок нет получаем результат
Результат = МодульККТ.ПолучитьСтруктуруJSON(ОтветJSON);
//обрабатываем результат
Иначе
//АтолККТ.Ошибка;
//АтолККТ.КодОшибки;
КонецЕсли;
Если НЕ АтолККТ.КодОшибки = 0 Тогда
ПоказатьОповещениеПользователя("Ошибка чека, отправка прервана!",,АтолККТ.Ошибка,БиблиотекаКартинок.Остановить);
Возврат Ложь;
КонецЕсли;
КонецЕсли;
АтолККТ.Закрыть();
Возврат Истина;
Иначе
ПоказатьПредупреждение(,АтолККТ.Ошибка,0,"Ошибка подключения к кассе!");
Возврат Ложь;
КонецЕсли;
конецфункции