Как настроить работу 1С 7.7 с онлайн-кассами (54-ФЗ) для АТОЛ и Штрих-М?

Программист 1С v7.7 1С:Управление торговлей Торговля и дистрибуция
← На главную

Переход платформы «1С:Предприятие 7.7» на работу с онлайн-кассами по требованиям 54-ФЗ требует обновления механизмов взаимодействия с кассовым оборудованием. В отличие от старых версий фискальных регистраторов с ЭКЛЗ, современные аппараты требуют обязательной передачи номенклатурного состава, ставок НДС, реквизитов кассира, систем налогообложения и контактных данных покупателя для отправки электронного чека.

Разберем подробно два основных подхода к интеграции: использование стандартизированного XML-пакета через компоненту интеграции (БПО) и прямое управление регистрацией через низкоуровневые COM-драйверы производителей.

Формирование чека через XML-пакет для оборудования АТОЛ

При использовании драйверов АТОЛ (библиотека FprnM1C82_54FZ.dll / ATOL_KKM_1C82_54FZ) передача данных о чеке выполняется через XML-структуру определенного формата. Для корректной обработки данных платформой 1С 7.7 требуется сформировать документ в кодировке UTF-8 без BOM и передать его в метод драйвера СформироватьЧек.

Рассмотрим пример функции печати фискального чека с передачей товарных позиций, безналичной оплаты и контактов покупателя:


Функция ПечататьЧекАТОЛ(Объект, Кассир, ПризнВозврата, СНО, МылоПолучателя, ТелПолучателя, СписокТоваров, СуммаЧека, СуммаНал, СуммаБезнал)
    
    Перем XMLАнализатор, XMLДанныеЧека, XMLCheckPackage, XMLParameters, XMLPositions, XMLPayments;
    Перем XMLFiscalString, АдоДБСтрим, ТекстXML, ОписаниеОшибки, КодОшибки;
    Перем НомерЧека, НомерСмены, ФискальныйПризнак, АдресСайтаПроверки;
    
    XMLАнализатор = СоздатьОбъект("AddIn.XMLParser");
    XMLДанныеЧека = XMLАнализатор.СоздатьДокумент();
    XMLДанныеЧека.Кодировка = "UTF-8";
    
    XMLCheckPackage = XMLДанныеЧека.СоздатьПодчиненныйЭлемент("CheckPackage");
    XMLParameters = XMLCheckPackage.СоздатьПодчиненныйЭлемент("Parameters");
    
    // Тип расчета: 1 - Приход, 2 - Возврат прихода
    Атрибут(XMLParameters, "PaymentType", ?(ПризнВозврата = 1, 2, 1));
    Атрибут(XMLParameters, "TaxVariant", СНО);
    
    Если ПустаяСтрока(МылоПолучателя) = 0 Тогда
        Атрибут(XMLParameters, "CustomerEmail", СокрЛП(МылоПолучателя));
    КонецЕсли;
    Если ПустаяСтрока(ТелПолучателя) = 0 Тогда
        Атрибут(XMLParameters, "CustomerPhone", СокрЛП(ТелПолучателя));
    КонецЕсли;
    
    XMLPositions = XMLCheckPackage.СоздатьПодчиненныйЭлемент("Positions");
    
    СписокТоваров.ВыбратьСтроки();
    Пока СписокТоваров.ПолучитьСтроку() = 1 Цикл
        XMLFiscalString = XMLPositions.СоздатьПодчиненныйЭлемент("FiscalString");
        Атрибут(XMLFiscalString, "Name", СокрЛП(СписокТоваров.ТовНаим));
        Атрибут(XMLFiscalString, "Quantity", СписокТоваров.Количество);
        Атрибут(XMLFiscalString, "Price", Окр(СписокТоваров.Цена, 2));
        Атрибут(XMLFiscalString, "Amount", Окр(СписокТоваров.Сумма, 2));
        Атрибут(XMLFiscalString, "Tax", СписокТоваров.СтавкаНДС); // Значения: "18", "10", "0", "none"
        Атрибут(XMLFiscalString, "Department", СписокТоваров.Секция);
    КонецЦикла;
    
    XMLPayments = XMLCheckPackage.СоздатьПодчиненныйЭлемент("Payments");
    Атрибут(XMLPayments, "Cash", СуммаНал);
    Атрибут(XMLPayments, "CashLessType1", "0");
    Атрибут(XMLPayments, "CashLessType2", "0");
    Атрибут(XMLPayments, "CashLessType3", СуммаБезнал); // Оплата платежной картой
    
    XMLДанныеЧека.Записать(КаталогПользователя() + "check.xml");
    
    // Чтение XML в формате UTF-8
    АдоДБСтрим = CreateObject("Adodb.Stream");
    АдоДБСтрим.Charset = "utf-8";
    АдоДБСтрим.Type = 2;
    АдоДБСтрим.Mode = 3;
    АдоДБСтрим.Open();
    АдоДБСтрим.LoadFromFile(КаталогПользователя() + "check.xml");
    ТекстXML = АдоДБСтрим.ReadText();
    АдоДБСтрим.Close();
    
    Электронно = ?((ПустаяСтрока(МылоПолучателя) = 0) ИЛИ (ПустаяСтрока(ТелПолучателя) = 0), 1, 0);
    
    Объект.СформироватьЧек(глФРИДУстройства, Кассир, Электронно, ТекстXML, НомерЧека, НомерСмены, ФискальныйПризнак, АдресСайтаПроверки);
    
    ОписаниеОшибки = "";
    КодОшибки = Объект.GetLastError(ОписаниеОшибки);
    
    Если КодОшибки <> 0 Тогда
        Сообщить("Ошибка печати чека: " + ОписаниеОшибки, "!");
        Возврат 0;
    КонецЕсли;
    
    Возврат 1;
КонецФункции

Прямая регистрация чека через низкоуровневый драйвер АТОЛ

Если используется прямое подключение через объект AddIn.FprnM45 (драйвер ККТ 8.x), чек пробивается последовательным вызовом методов устройства. Важным моментом является передача тега кассира (тег 1021) перед открытием чека или снятием Z-отчета:


// Установка кассира и открытие чека продажи
глФР.DeviceEnabled = 1;
глФР.Mode = 1; // Режим регистрации
глФР.SetMode();

// Запись реквизита "Кассир" (Тег 1021)
глФР.AttrNumber = 1021;
глФР.AttrValue = "Кассир Иванов И.И.";
глФР.AttrPrint = 1;
глФР.WriteAttribute();

глФР.CheckType = 1; // 1 - Продажа, 2 - Возврат продажи
глФР.OpenCheck();

// Регистрация позиции
глФР.Name = "Товар 1";
глФР.Price = 150.00;
глФР.Quantity = 2;
глФР.Department = 1;
глФР.TaxTypeNumber = 4; // 4 - Без НДС, 1 - 18%, 2 - 10%, 3 - 0%
глФР.Registration();

// Закрытие чека с типом оплаты
глФР.Summ = 300.00;
глФР.TypeClose = 0; // 0 - Наличные, 3 - Электронными (карта)
глФР.Delivery();
глФР.CloseCheck();

Печать чеков на фискальных регистраторах Штрих-М

При интеграции ККТ семейства «Штрих-М» через библиотеку DrvFR.dll часто возникает проблема, когда наименование товара печатается на бумажной ленте, но не уходит в электронном виде в ОФД. Проанализируем причину: свойство StringForPrinting должно заполняться строго до вызова метода регистрации продажи Sale(), а вызов методов печати нефискального текста не должен перекрывать фискальные реквизиты.

Посмотрим на пример правильной регистрации продажи на ККТ «Штрих-М»:


// Вход в режим регистрации
глФР.Password = 30; // Пароль системного администратора
глФР.SetMode();

// Установка ФИО кассира в таблицу паролей (Таблица №2, поле №2)
глФР.TableNumber = 2;
глФР.RowNumber = 1; // Номер кассира
глФР.FieldNumber = 2;
глФР.ValueOfFieldString = "Иванов И.И.";
глФР.WriteTable();

глФР.Password = 1; // Пароль кассира
глФР.OpenCheck();

СписокТоваров.ВыбратьСтроки();
Пока СписокТоваров.ПолучитьСтроку() = 1 Цикл
    // Передаем наименование в StringForPrinting ДО вызова фискальной операции
    глФР.StringForPrinting = Лев(СписокТоваров.ТовНаим, 64);
    глФР.Price = Окр(СписокТоваров.Цена, 2);
    глФР.Quantity = СписокТоваров.Количество;
    глФР.Department = 1;
    глФР.Tax1 = 0; // Налоговая группа
    глФР.Sale();
КонецЦикла;

// Закрытие чека
глФР.Summ1 = СуммаНал;      // Оплата наличными
глФР.Summ2 = СуммаБезнал;  // Оплата безналичными (тип 2/3)
глФР.StringForPrinting = "";
глФР.CloseCheck();

Особенности и частые технические проблемы

  1. Округление и дробные копейки: Драйверы ККТ требуют строгого равенства суммы чека сумме строк. Передача цен с тысячными долями копеек (например, 5.005 при выделении НДС «сверху») приводит к ошибкам драйвера или подстановке значений из предыдущих строк. Всегда применяйте явное округление: Цена = Окр(Сумма / Количество, 2, 1).
  2. Сброс параметров в RDP-сессиях: При работе в терминале настройки портов в реестре пользователя могут сбрасываться. Рекомендуется перед каждой операцией явно передавать номер COM-порта и скорость обмена программно в свойства объекта драйвера.
  3. Службы передачи в ОФД: Для аппаратов АТОЛ служба EthOverUsb требует жесткого закрепления номеров виртуальных COM-портов в файле settings.xml. Для аппаратов Штрих-М при сбоях протокола RNDIS оптимальным решением является подключение ККТ по интерфейсу Ethernet.
← На главную