Имя: Пароль:
1C
1С v8
ФФД 1.2 - пробитие чека через через COM драйвер ККМ v10 (АТОЛ) - пример с маркировкой
0 wylde
 
12.12.21
18:59
Особенностью новой версии правил передачи данных ФФД1.2 является валидация кодов маркировки на самой онлайн-кассе перед тем как чек будет пробит. Если валидацию код прошел то в чеке напротив позиции товара отобразится [M+] если не прошел [M-]

Прежде всего убедитесь что сама касса после прошивки и обновления функционирует адекватно. Обязательно убедитесь что установлен 32x драйвер ккт АТОЛ. Через программу которая идет в поставке "Тест драйвера ККТ", проверьте соединение, попробуйте открыть / закрыть смену, распечатайте чек о тех. состоянии кассы. В моем случае сотрудники банка смогли перепрошить/обновить кассу только с третьего раза.

Ссылка на документацию по драйверу АТОЛ (выбираем раздел "Python")
http://integration.atol.ru/api/

Кусок кода надеюсь поможет тем у кого сильно переписанная конфигурация. В моем случае это была УТ10.


    //1. Соединение с ККТ
        COM_port = "4";
        
        FR = Новый COMОбъект("AddIn.Fptr10");            
        FR.setSingleSetting(FR.LIBFPTR_SETTING_MODEL, Строка(FR.LIBFPTR_MODEL_ATOL_AUTO));
        FR.setSingleSetting(FR.LIBFPTR_SETTING_PORT, Строка(FR.LIBFPTR_PORT_COM));
        FR.setSingleSetting(FR.LIBFPTR_SETTING_COM_FILE, "COM"+COM_port); //СОМ порт кассы - например "COM4"
        FR.setSingleSetting(FR.LIBFPTR_SETTING_BAUDRATE, Строка(FR.LIBFPTR_PORT_BR_115200));
        FR.applySingleSettings();
            
        Если FR.open()<>0 Тогда // Отправка команды на кассу
            Result=FR.errorCode();
            Сообщить(FR.errorDescription());
            FR.cancelReceipt();  //Отмена чека в случае неудачи
        КонецЕсли;

    
    //2. Открытие чека
        FR.setParam(1021, СокрЛП("Кассир"));
        
        Если FR.operatorLogin()<>0 Тогда // Отправка команды на кассу
            Result=FR.errorCode();
            Сообщить(FR.errorDescription());
            FR.cancelReceipt();  //Отмена чека в случае неудачи
        КонецЕсли;    
        
        FR.setParam(FR.LIBFPTR_PARAM_RECEIPT_TYPE, FR.LIBFPTR_RT_SELL); //LIBFPTR_RT_SELL - Продажа;  LIBFPTR_RT_SELL_RETURN - возврат    
        FR.setParam(FR.LIBFPTR_PARAM_RECEIPT_ELECTRONICALLY, False); //Печать электронного чека (False - печатаем, True - не печатаем)

        //Емейл (тег 1008)
        FR.SetParam(1008, "[email protected]");
        //================
        
        Если FR.openReceipt() <> 0 Тогда // Отправка команды на кассу
            Result=FR.errorCode();
            Сообщить(FR.errorDescription());
            FR.cancelReceipt();  //Отмена чека в случае неудачи
        КонецЕсли;    
    
    
    //3. РЕГИСТРИРУЕМ ТОВАРЫ В ЧЕКЕ

    //===========Табличная часть ЦИКЛ Начало===========
        
        //3.1 - ВАРИАНТ Регистрации обычного товара (не маркировка)        
        FR.setParam(FR.LIBFPTR_PARAM_COMMODITY_NAME, "Вода минеральная" ); //Наименование товара
        FR.setParam(FR.LIBFPTR_PARAM_PRICE, 250.00 ); //Цена
        FR.setParam(FR.LIBFPTR_PARAM_QUANTITY, 1 ); //Количество
        FR.setParam(FR.LIBFPTR_PARAM_TAX_TYPE, FR.LIBFPTR_TAX_NO ); //Ставка НДС - LIBFPTR_TAX_NO - не облагается; LIBFPTR_TAX_VAT10 - НДС 10%; LIBFPTR_TAX_VAT20 - НДС 20%    
        FR.setParam(1212, 32); //Обязательный параметр для ФФД 1.2!!! 32 - товар не имеющий код маркировки, 33 - товар имеющий код маркировки
        
        
        //3.2 - ВАРИАНТ Регистрации маркированного товара (ФФД 1.2)        
                    
        //Рутинная часть с маркировкой
        //=============================================================================================
        
            //Пример кода маркировки
            //КодDataMatrix = '014494550435306821QXYXSALGLMYQQ\u001D91EE06\u001D92YWCXbmK6SN8vvwoxZFk7WAY8WoJNMGGr6Cgtiuja04c='
            
            //Делим "КодDataMatrix" на три части чтобы потом соединить через спец символ "Символ(29)"
            //Ходят легенды что настроив сканер ШК особым способом можно сразу получать с него строку со спец символами, но представим что у нас стандартная ситуация
            Часть1=Лев(КодDataMatrix,31);
            Часть2=Сред(КодDataMatrix,32,6);
            Часть3=Сред(КодDataMatrix,38,СтрДлина(КодDataMatrix));
                        
            mark = Часть1+Символ(29)+Часть2+Символ(29)+Часть3;
            status = 2;
            
            // Запускаем проверку КМ (параметры оставляем как есть по умолчанию)
            FR.setParam(FR.LIBFPTR_PARAM_MARKING_CODE_TYPE, FR.LIBFPTR_MCT12_AUTO);
            FR.setParam(FR.LIBFPTR_PARAM_MARKING_CODE, mark);
            FR.setParam(FR.LIBFPTR_PARAM_MARKING_CODE_STATUS, status);
            FR.setParam(FR.LIBFPTR_PARAM_QUANTITY, 1); //Количество
            FR.setParam(FR.LIBFPTR_PARAM_MEASUREMENT_UNIT, FR.LIBFPTR_IU_PIECE);
            FR.setParam(FR.LIBFPTR_PARAM_MARKING_WAIT_FOR_VALIDATION_RESULT, True);
            FR.setParam(FR.LIBFPTR_PARAM_MARKING_PROCESSING_MODE, 0);
            
            FR.beginMarkingCodeValidation();

            //Задержка на 1 секунду - опционально можно убрать, но без задержки касса (АТОЛ 55Ф) часто зависала
            //С задержкой перестала виснуть
            ЗадержкаСекунд = 1;    
            КомандаWindows = "Timeout /T " + Формат(ЗадержкаСекунд, "ЧГ=0") + " /NoBreak";
            ЗапуститьПриложение(КомандаWindows,,Истина);
            //=============================================            
            
            // Дожидаемся окончания проверки и запоминаем результат
            ДатаНачПроверки=ТекущаяДата();   //На случай зависания проверки ставим отсечку
            ДатаКонПроверки=ТекущаяДата()+5; //5 секунд даем на проверку максимум
                        
            Пока FR.getMarkingCodeValidationStatus() Цикл
                
                Если FR.getParamBool(FR.LIBFPTR_PARAM_MARKING_CODE_VALIDATION_READY) Тогда                        
                    Прервать;
                КонецЕсли;
                
                Если ТекущаяДата() > ДатаКонПроверки Тогда
                    Прервать;
                КонецЕсли;
                
            КонецЦикла;
            
            validationResult = FR.getParamInt(FR.LIBFPTR_PARAM_MARKING_CODE_ONLINE_VALIDATION_RESULT); // если validationResult возвращает "15" значит все ок! код прошел проверку
            
            FR.acceptMarkingCode();    
            
            //=============================================================================================

            //Начало похожее как в обычном товаре
            FR.setParam(FR.LIBFPTR_PARAM_COMMODITY_NAME, "Ботинки"); //Наименование товара
            FR.setParam(FR.LIBFPTR_PARAM_PRICE, 250.00 ); //Цена
            FR.setParam(FR.LIBFPTR_PARAM_QUANTITY, 1 ); //Количество
            FR.setParam(FR.LIBFPTR_PARAM_TAX_TYPE, FR.LIBFPTR_TAX_NO ); //Ставка НДС - LIBFPTR_TAX_NO - не облагается; LIBFPTR_TAX_VAT10 - НДС 10%; LIBFPTR_TAX_VAT20 - НДС 20%    
            FR.setParam(1212, 33); //Обязательный параметр для ФФД 1.2!!! 32 - товар не имеющий код маркировки, 33 - товар имеющий код маркировки
        
            FR.setParam(FR.LIBFPTR_PARAM_MEASUREMENT_UNIT, FR.LIBFPTR_IU_PIECE);
            FR.setParam(FR.LIBFPTR_PARAM_MARKING_CODE, mark);
            FR.setParam(FR.LIBFPTR_PARAM_MARKING_CODE_STATUS, status);
            FR.setParam(FR.LIBFPTR_PARAM_MARKING_CODE_ONLINE_VALIDATION_RESULT, validationResult);
            FR.setParam(FR.LIBFPTR_PARAM_MARKING_PROCESSING_MODE, 0);            
            
            //Регистрируем позицию в чеке
            Если FR.registration() <> 0 тогда
                Result=FR.errorCode();
                Сообщить(FR.errorDescription());
                FR.cancelReceipt();  //Отмена чека в случае неудачи
            КонецЕсли;
            
    //===========Табличная часть ЦИКЛ Конец===========
        
        
        
        
    //4. Итоговая сумма чека    
    FR.setParam( FR.LIBFPTR_PARAM_SUM, 250.00 ); //Итоговая сумма чека
    
    Если FR.receiptTotal() <> 0 тогда
        Result=FR.errorCode();
        Сообщить(FR.errorDescription());
        FR.cancelReceipt();  //Отмена чека в случае неудачи
    КонецЕсли;
    
    //5. Оплата  (Наличные или Электронные)
    FR.setParam(FR.LIBFPTR_PARAM_PAYMENT_TYPE, FR.LIBFPTR_PT_CASH);  //LIBFPTR_PT_CASH - наличные; LIBFPTR_PT_ELECTRONICALLY - электронные (безнал)
    FR.setParam(FR.LIBFPTR_PARAM_PAYMENT_SUM, 250.00 );
    
    Если FR.payment() <> 0 тогда
        Result=FR.errorCode();
        Сообщить(FR.errorDescription());
        FR.cancelReceipt();  //Отмена чека в случае неудачи
    КонецЕсли;        
        
    //6. Закрытие чека    (Пробитие по кассе)
    Если FR.closeReceipt() <> 0 тогда
        Result=FR.errorCode();
        Сообщить(FR.errorDescription());
        FR.cancelReceipt();  //Отмена чека в случае неудачи
    КонецЕсли;
1 vis_tmp
 
12.12.21
21:59
Спасибо за пример пробивки чека по ФФД 1.2 для УТ 10.3.
2 victuan1
 
13.12.21
05:25
(0) Особенно умилило "//Ходят легенды что настроив сканер ШК особым способом можно сразу получать с него строку со спец символами"
;)
Похоже, это клон VKOSH из этой темы Проблемы с ФФД 1.2
3 Галахад
 
гуру
13.12.21
07:52
Примеры, всегда хорошо.
4 tgu82
 
13.12.21
09:30
Очень полезная ветка.
Особенно что касается кода 29.
Часть1=Лев(КодDataMatrix,31);
            Часть2=Сред(КодDataMatrix,32,6);
            Часть3=Сред(КодDataMatrix,38,СтрДлина(КодDataMatrix));
                        
            mark = Часть1+Символ(29)+Часть2+Символ(29)+Часть3;
Мне правда уже подсказали это но кашу маслом не испорчу
5 Garykom
 
гуру
13.12.21
10:31
(0) Муахаха

>Обязательно убедитесь что установлен 32x драйвер
смотря какая версия платформы 1С

>выбираем раздел "Python"
Delphi там надо выбирать и смотреть, один в один примеры готовые

>Задержка на 1 секунду - опционально можно убрать, но без задержки касса (АТОЛ 55Ф) часто зависала
там не задержка нужна а переделать свой код на правильный

"Проверка КМ включает состоит из нескольких операций, которые должны быть выполнены для каждого кода маркировки:

-начать проверку КМ (beginMarkingCodeValidation()), драйвер запускает процедуру отправки данных КМ на сервер для онлайн-проверки. Следующий КМ можно проверить только после окончания предыдущей проверки

-дождаться ответа на проверку (getMarkingCodeValidationStatus()). Метод нужно вызывать до тех пор, пока выходной параметр LIBFPTR_PARAM_MARKING_CODE_VALIDATION_READY не станет равным true, метод вернёт результат онлайн проверки.

-подтвердить реализацию КМ (acceptMarkingCode()) или отказаться (declineMarkingCode()). Это обязательная операция в обоих режимах проверки.

Онлайн проверку можно прервать методом cancelMarkingCodeValidation()."

И даже реализация дана как https://integration.atol.ru/api/?pascal#proverka-km


while True do
    begin
        fptr.getMarkingCodeValidationStatus;
        if fptr.getParamBool(fptr.LIBFPTR_PARAM_MARKING_CODE_VALIDATION_READY) then
            break;
    end;
validationResult := fptr.getParamInt(fptr.LIBFPTR_PARAM_MARKING_CODE_ONLINE_VALIDATION_RESULT);