В современной торговле и сфере услуг часто возникает задача автоматизации ввода данных с бумажных носителей. Типичный сценарий: клиент приносит квитанцию на оплату (например, коммунальных услуг, обучения или взносов) с напечатанным двумерным штрихкодом (QR-кодом), и оператору в программе «1С:Управление торговлей» (УТ) необходимо быстро принять платеж или оформить документ продажи, не вводя все реквизиты вручную. В этой статье мы подробно разберем, как устроен этот процесс, как правильно настроить торговое оборудование и как написать программный код для разбора (парсинга) считанных данных.
Многие начинающие разработчики и администраторы считают, что работа с QR-кодом принципиально отличается от работы со стандартными линейными штрихкодами (EAN-13, Code 128). На самом деле физика процесса идентична: сканер считывает графическую информацию, преобразует ее в текстовую строку и передает в информационную систему. Основная сложность заключается в правильном декодировании и интерпретации полученной строки.
Перед тем как переходить к программированию в 1С, нам необходимо определиться со способом подключения сканера к компьютеру. Существует два основных режима работы сканеров штрихкодов:
Для работы с QR-кодами (особенно с платежными квитанциями) настоятельно рекомендуется использовать только режим эмуляции COM-порта. Рассмотрим подробнее, почему режим «в разрыв клавиатуры» здесь не подходит:
= или вертикальная черта |) могут превратиться в нечитаемую «кашу».Для настройки переведите ваш сканер в режим USB-vCOM (обычно это делается путем сканирования специального управляющего штрихкода из инструкции к оборудованию) и установите соответствующий виртуальный драйвер в операционной системе. В самой «1С:Управление торговлей» подключите устройство через меню Администрирование — Подключаемое оборудование, выбрав тип оборудования «Сканеры штрихкода» и стандартный драйвер «1С:Сканеры штрихкода (COM)».
Большинство квитанций, которые приносят клиенты, формируются по национальному стандарту ГОСТ Р 56042-2014. Этот стандарт жестко регламентирует структуру текстовой строки, зашифрованной в графическом коде.
Давайте проанализируем структуру такой строки. Типичный считанный код выглядит следующим образом:
ST00012|Name=ООО "Торговая Компания"|PersonalAcc=40702810400000001111|BankName=ПАО СБЕРБАНК|BIC=044525225|CorrespAcc=30101810400000000225|PayeeINN=7701020304|LastName=Иванов|FirstName=Иван|MiddleName=Иванович|Purpose=Оплата за товары по договору №12|Sum=150000
Разберем эту строку по составляющим:
ST00011 — данные закодированы в кодировке Windows-1251.ST00012 — данные закодированы в UTF-8.ST00013 — данные закодированы в KOI8-R.|.Ключ=Значение.Name — наименование юридического лица или ИП.PersonalAcc — расчетный счет.BankName — наименование банка.BIC — БИК банка.CorrespAcc — корреспондентский счет.PayeeINN — ИНН получателя.Sum — сумма платежа (Внимание: сумма всегда указывается в копейках, то есть значение 150000 соответствует 1500 рублям 00 копейкам).Purpose — назначение платежа.LastName, FirstName, MiddleName — фамилия, имя и отчество плательщика.PersAcc (или PersonalAcc у плательщика) — лицевой счет плательщика в информационной системе.Поскольку сканер подключен в режиме COM-порта через библиотеку подключаемого оборудования (БПО), при сканировании будет генерироваться внешнее событие формы. Выясним, как правильно организовать его перехват.
В управляемых формах «1С:Управление торговлей» для перехвата событий от торгового оборудования используется встроенный механизм БСП. Нам необходимо подключить форму к прослушиванию событий сканера при открытии и отключить при закрытии. Рассмотрим шаблон кода для формы, в которой мы хотим принимать данные от сканера:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
// Подключаем обработчик ожидания для интеграции с БПО
ПодключитьОбработчикОжидания("ПодключитьСканерШтрихкодов", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ПодключитьСканерШтрихкодов()
// Регистрируем форму в подсистеме подключаемого оборудования
ПредупреждениеПриОтключении = Ложь;
ПараметрыПодключения = Новый Структура;
МенеджерОборудованияКлиент.ПодключитьОборудованиеПоТипу(УникальныйИдентификатор,
ПредопределенноеЗначение("Перечисление.ТипыПодключаемогоОборудования.СканерШтрихкода"),
ПараметрыПодключения,
ПредупреждениеПриОтключении);
КонецПроцедуры
&НаКлиенте
Процедура ПриЗакрытии(ЗавершениеРаботы)
// Отключаем оборудование при закрытии формы, чтобы освободить порт
МенеджерОборудованияКлиент.ОтключитьОборудованиеПоТипу(УникальныйИдентификатор,
ПредопределенноеЗначение("Перечисление.ТипыПодключаемогоОборудования.СканерШтрихкода"));
КонецПроцедуры
Когда сканер считает штрихкод, платформа вызовет оповещение. Мы должны перехватить его, переопределив стандартную процедуру ОбработкаОповещения в модуле нашей управляемой формы:
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
// Проверяем, что событие пришло от торгового оборудования
Если Источник = "ПодключаемоеОборудование" И ИмяСобытия = "Штрихкод" Тогда
// Получаем массив считанных данных (в зависимости от версии БПО)
Если ТипЗнч(Параметр) = Тип("Массив") Тогда
ДанныеСканирования = Параметр[0];
Иначе
ДанныеСканирования = Параметр;
КонецЕсли;
// Извлекаем саму строку штрихкода
СтрокаШтрихкода = СокрЛП(ДанныеСканирования.Штрихкод);
// Анализируем считанные данные
ОбработатьСчитанныйШтрихкод(СтрокаШтрихкода);
КонецЕсли;
КонецПроцедуры
Теперь перейдем к самому интересному — программному разбору текстовой строки, полученной от сканера. Нам необходимо проверить, является ли считанный штрихкод платежным QR-кодом по ГОСТу, и если да — разложить его по реквизитам. Напишем универсальную функцию разбора, которую можно разместить в общем модуле или модуле формы.
Проанализируем алгоритм работы парсера. Нам потребуется разбить исходную строку по символу-разделителю |, а затем каждую полученную пару разделить по символу =.
&НаСервереБезКонтекста
Функция РазобратьПлатежныйQRКод(Знач СтрокаДанных)
РезультатРазбора = Новый Структура;
РезультатРазбора.Вставить("ЭтоПлатежныйКод", Ложь);
СтрокаДанных = СокрЛП(СтрокаДанных);
// Проверяем обязательный префикс стандарта ГОСТ Р 56042-2014
ПрефиксГОСТ = Лев(СтрокаДанных, 7);
Если ПрефиксГОСТ <> "ST00011" И ПрефиксГОСТ <> "ST00012" И ПрефиксГОСТ <> "ST00013" Тогда
Возврат РезультатРазбора; // Это не платежный код ГОСТа, обрабатываем как обычный ШК
КонецЕсли;
РезультатРазбора.ЭтоПлатежныйКод = Истина;
// Удаляем префикс и первый разделитель, чтобы начать разбор параметров
РабочаяСтрока = Сред(СтрокаДанных, 9);
// Разбиваем строку на массив параметров по символу вертикальной черты
МассивРеквизитов = СтрРазделить(РабочаяСтрока, "|", Ложь);
Для Каждого СтрокаРеквизита Из МассивРеквизитов Цикл
// Находим позицию первого знака равенства
ПозРавно = Найти(СтрокаРеквизита, "=");
Если ПозРавно = 0 Тогда
Продолжить;
КонецЕсли;
// Выделяем Ключ и Значение
ИмяКлюча = СокрЛП(Лев(СтрокаРеквизита, ПозРавно - 1));
ЗначениеКлюча = СокрЛП(Сред(СтрокаРеквизита, ПозРавно + 1));
// Добавляем параметр в структуру результатов
РезультатРазбора.Вставить(ИмяКлюча, ЗначениеКлюча);
КонецЦикла;
// Корректируем сумму (переводим из копеек в рубли)
Если РезультатРазбора.Свойство("Sum") Тогда
Попытка
РезультатРазбора.Sum = Число(РезультатРазбора.Sum) / 100;
Исключение
РезультатРазбора.Sum = 0;
КонецПопытки;
КонецЕсли;
Возврат РезультатРазбора;
КонецФункции
Эта функция возвращает удобную структуру, содержащую все прочитанные из квитанции реквизиты. Посмотрим, как применить ее результаты на практике для заполнения нового документа в системе.
Рассмотрим сценарий: при сканировании квитанции система должна автоматически создать и заполнить документ «Поступление безналичных денежных средств» или открыть форму подбора чека ККМ, найдя контрагента по ИНН или ФИО.
Напишем процедуру, которая принимает считанную строку, выдыхает структуру данных и выполняет поиск контрагента в базе данных по ИНН или БИК банка:
&НаКлиенте
Процедура ОбработатьСчитанныйШтрихкод(СтрокаШтрихкода)
// Вызываем серверный метод разбора QR-кода
ДанныеQR = РазобратьПлатежныйQRКод(СтрокаШтрихкода);
Если ДанныеQR.ЭтоПлатежныйКод Тогда
// Код успешно распознан по ГОСТу. Начинаем заполнение бизнес-сущностей
ПоказатьПредупреждение(, "Успешно считан платежный QR-код! Получатель: " + ДанныеQR.Name);
// Вызываем серверную процедуру для поиска объектов и создания документа
СоздатьДокументНаОснованииQR(ДанныеQR);
Else
// Обрабатываем как обычный штрихкод номенклатуры или дисконтной карты
ОбработатьОбычныйШтрихкод(СтрокаШтрихкода);
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Процедура СоздатьДокументНаОснованииQR(ДанныеQR)
// 1. Попытаемся найти контрагента в базе по ИНН
КонтрагентСсылка = Справочники.Контрагенты.ПустаяСсылка();
Если ДанныеQR.Свойство("PayeeINN") И ЗначениеЗаполнено(ДанныеQR.PayeeINN) Тогда
КонтрагентСсылка = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", ДанныеQR.PayeeINN);
КонецЕсли;
// 2. Попытаемся найти физическое лицо (плательщика) по ФИО, если это необходимо
ФизическоеЛицоСсылка = Справочники.ФизическиеЛица.ПустаяСсылка();
Если ДанныеQR.Свойство("LastName") Тогда
ПолноеИмя = ДанныеQR.LastName;
Если ДанныеQR.Свойство("FirstName") Тогда
ПолноеИмя = ПолноеИмя + " " + ДанныеQR.FirstName;
КонецЕсли;
Если ДанныеQR.Свойство("MiddleName") Тогда
ПолноеИмя = ПолноеИмя + " " + ДанныеQR.MiddleName;
КонецЕсли;
ФизическоеЛицоСсылка = Справочники.ФизическиеЛица.НайтиПоНаименованию(ПолноеИмя, Истина);
КонецЕсли;
// 3. Создаем новый документ "Поступление безналичных денежных средств" (пример для УТ)
НовыйДокумент = Документы.ПоступлениеБезналичныхДенежныхСредств.СоздатьДокумент();
НовыйДокумент.Дата = ТекущаяДата();
Если ЗначениеЗаполнено(КонтрагентСсылка) Тогда
НовыйДокумент.Контрагент = КонтрагентСсылка;
КонецЕсли;
// Заполняем сумму из QR-кода (уже переведенную в рубли)
Если ДанныеQR.Свойство("Sum") Тогда
НовыйДокумент.СуммаДокумента = ДанныеQR.Sum;
КонецЕсли;
// Заполняем назначение платежа
Если ДанныеQR.Свойство("Purpose") Тогда
НовыйДокумент.НазначениеПлатежа = ДанныеQR.Purpose;
КонецЕсли;
// Записываем документ (в реальной задаче лучше открыть его форму пользователю для проверки)
Попытка
НовыйДокумент.Записать(РежимЗаписиДокумента.Запись);
// Здесь можно открыть форму созданного документа на клиенте
Исключение
ВызватьИсключение "Не удалось записать документ: " + ОписаниеОшибки();
КонецПопытки;
КонецПроцедуры
Разработчикам и аналитикам крайне важно не путать две совершенно разные технологии двумерного кодирования, используемые в финансовой сфере:
https://qr.nspk.ru/...). Оплата по ней со стороны клиента происходит мгновенно (в течение 15 секунд). В современных релизах «1С:Управление торговлей» интеграция с СБП уже встроена «из коробки», однако она предназначена для генерации и вывода кодов вашим покупателям на дисплей или чек, а не для чтения входящих квитанций сторонних банков.Таким образом, если перед вами стоит задача автоматического распознавания бумажных квитанций клиентов (коммунальные платежи, штрафы, обучение), вам необходимо реализовывать парсинг именно стандарта ГОСТ Р 56042-2014 с использованием подключаемого оборудования, как мы разобрали по шагам в данной статье.