Ку-Ку Код

Печать листа QR-кодов из 1С через API: внешняя обработка, запрос и PDF

Три куска кода для внешней обработки: запрос к номенклатуре, функция запроса к API и команда формы, плюс две строки запроса, которых нет в других языках: запрет метки BOM и защищенное соединение.

Массовая генерация 8 мин на чтение 19.10.2026

Список товаров или объектов учета уже лежит в базе 1С, и выгружать его в таблицу ради листа с QR-кодами не обязательно. Внешняя обработка берет строки запросом, отправляет их на API генератора одним POST-запросом и получает готовый PDF с сеткой кодов на A4. Код на встроенном языке приведен целиком.

Запрос, ответ, лимиты и ключ разобраны в статье API генерации QR-кодов с примерами на Python, Node.js и PowerShell. Эта статья только про 1С: код обработки, строки из справочника и два параметра запроса, которых в примерах на Python и Node.js нет.

Откуда взять строки

В примере строки берутся из справочника Номенклатура, у него есть код и наименование; имена сверьте в конфигураторе своей конфигурации. Код уходит в QR-код как часть ссылки на карточку товара на вашем сайте, наименование становится подписью под кодом. Адрес карточки задает поле url_template: на место {value} API подставляет часть строки до первого пробела, остаток строки остается подписью. В примере стоит https://example.com/catalog/{value}, замените его на адрес своего каталога.

Запрос берет не больше 1500 строк, потому что столько помещается в один запрос к API, а список целиком должен уложиться в 256 КБ: при ответе 413 уменьшите число в ПЕРВЫЕ. Подпись длиннее 100 символов API не примет, поэтому наименование обрезается функцией Лев. Отбор под свою задачу, например по виду номенклатуры или по остатку на складе, добавьте в условие запроса.

&НаСервереБезКонтекста
Функция СтрокиСписка()
	Запрос = Новый Запрос(
		"ВЫБРАТЬ ПЕРВЫЕ 1500
		|	Номенклатура.Код КАК Код,
		|	Номенклатура.Наименование КАК Наименование
		|ИЗ
		|	Справочник.Номенклатура КАК Номенклатура
		|ГДЕ
		|	НЕ Номенклатура.ПометкаУдаления
		|	И НЕ Номенклатура.ЭтоГруппа
		|УПОРЯДОЧИТЬ ПО
		|	Код");
	Строки = Новый Массив;
	Выборка = Запрос.Выполнить().Выбрать();
	Пока Выборка.Следующий() Цикл
		Строки.Добавить(СокрЛП(Выборка.Код) + " " + Лев(Выборка.Наименование, 100));
	КонецЦикла;
	Возврат Строки;
КонецФункции

Запрос к API из обработки

Функция ниже собирает JSON, отправляет его на qqkod.ru и при ответе 200 пишет PDF в файл, а при любом другом ответе разбирает JSON с ошибкой. Она объявлена без контекста, поэтому одинаково вызывается с клиента и с сервера.

&НаКлиентеНаСервереБезКонтекста
Функция ЗапроситьЛистКодов(Строки, ИмяФайла)
	Тело = Новый Структура;
	Тело.Вставить("lines", Строки);
	Тело.Вставить("url_template", "https://example.com/catalog/{value}");
	Тело.Вставить("output", "pdf");
	Запись = Новый ЗаписьJSON;
	Запись.УстановитьСтроку();
	ЗаписатьJSON(Запись, Тело);
	ТекстJSON = Запись.Закрыть();

	Заголовки = Новый Соответствие;
	Заголовки.Вставить("Content-Type", "application/json");
	Запрос = Новый HTTPЗапрос("/api/v1/sheets", Заголовки);
	// метка BOM в начале тела дает ответ 400
	Запрос.УстановитьТелоИзСтроки(ТекстJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);

	Соединение = Новый HTTPСоединение("qqkod.ru", 443, , , , 30, Новый ЗащищенноеСоединениеOpenSSL());
	Ответ = Соединение.ОтправитьДляОбработки(Запрос);

	Результат = Новый Структура("КодСостояния", Ответ.КодСостояния);
	Если Ответ.КодСостояния = 200 Тогда
		Ответ.ПолучитьТелоКакДвоичныеДанные().Записать(ИмяФайла);
		Результат.Вставить("Листов", ЗначениеЗаголовка(Ответ.Заголовки, "X-QQkod-Total-Sheets"));
	Иначе
		Чтение = Новый ЧтениеJSON;
		Чтение.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
		Результат.Вставить("Ошибка", ПрочитатьJSON(Чтение, Истина));
		Результат.Вставить("ПовторЧерез", ЗначениеЗаголовка(Ответ.Заголовки, "Retry-After"));
	КонецЕсли;
	Возврат Результат;
КонецФункции

// имена заголовков HTTP не различают регистр, поэтому ищем без учета регистра
&НаКлиентеНаСервереБезКонтекста
Функция ЗначениеЗаголовка(Заголовки, Имя)
	Для Каждого Заголовок Из Заголовки Цикл
		Если ВРег(Заголовок.Ключ) = ВРег(Имя) Тогда
			Возврат Заголовок.Значение;
		КонецЕсли;
	КонецЦикла;
	Возврат "";
КонецФункции

Две строки в этой функции отличают 1С от других языков. Первая это третий параметр УстановитьТелоИзСтроки: он запрещает метку порядка байтов (BOM), три байта перед первой скобкой JSON. С меткой в теле API отвечает 400 BAD_JSON, хотя сам текст JSON правильный. Вторая это объект ЗащищенноеСоединениеOpenSSL седьмым параметром конструктора соединения вместе с портом 443: адрес API начинается с https, а защищенное соединение в 1С задается этим объектом.

Заголовок Content-Type ставится явно, без него API ответит 415. Кириллица в подписях уходит в JSON так, как ее записала ЗаписьJSON: API принимает и буквы, и \u-коды.

Ответ и ошибки

Команда формы вызывает функции выше и печатает результат в окно сообщений. При 200 это путь к PDF и число листов из заголовка X-QQkod-Total-Sheets, при 429 число секунд до повтора из заголовка Retry-After, при остальных ошибках код, текст и каждая строка из fields отдельным сообщением, например «Строка №2: подпись длиннее 100 символов», если убрать из запроса обрезку Лев. Что значат ответы 422 и 429 и куда писать с request_id, разобрано в статье про API.

&НаКлиенте
Процедура НапечататьЛист(Команда)
	ИмяФайла = ПолучитьИмяВременногоФайла("pdf");
	Результат = ЗапроситьЛистКодов(СтрокиСписка(), ИмяФайла);
	Если Результат.КодСостояния = 200 Тогда
		Сообщить("Листов: " + Результат.Листов + ", файл " + ИмяФайла);
	ИначеЕсли Результат.КодСостояния = 429 Тогда
		Сообщить("Лимит запросов, повторите через " + Результат.ПовторЧерез + " с");
	Иначе
		Ошибка = Результат.Ошибка.Получить("error");
		Сообщить(Строка(Результат.КодСостояния) + " " + Ошибка.Получить("code") + ": " + Ошибка.Получить("message"));
		Поля = Ошибка.Получить("fields");
		Если ТипЗнч(Поля) = Тип("Соответствие") Тогда
			Для Каждого Поле Из Поля Цикл
				Для Каждого Текст Из Поле.Значение Цикл
					Сообщить(Поле.Ключ + ": " + Текст);
				КонецЦикла;
			КонецЦикла;
		КонецЕсли;
		Сообщить("request_id " + Результат.Ошибка.Получить("meta").Получить("request_id"));
	КонецЕсли;
КонецПроцедуры

Где это запускать

Код кладется в модуль формы внешней обработки или расширения, конфигурацию менять не нужно. Запускается в тонком клиенте на платформе 8.3.9 и выше: параметр BOM и объекты для JSON есть с 8.3.6, а TLS 1.2 в защищенном соединении с 8.3.9. С версии 8.3.21 платформа считает синхронные вызовы HTTP на клиенте устаревшими, асинхронные в этой статье не разбираются. В веб-клиенте этот код не выполнится, потому что синхронных методов HTTPСоединение там нет. Код проверен интерпретатором OneScript против живого API, а не на платформе.

С сервера функция ЗапроситьЛистКодов работает так же, но PDF ляжет на диск сервера. Чтобы отдать его пользователю, файл передают через временное хранилище, а работу с временным файлом на сервере завершают в том же вызове, в котором его создали. В облаке 1С:Фреш обработка проходит аудит, а профиль безопасности регулирует доступ с сервера к адресам в интернете. В этом примере запрос идет с клиента, и PDF сразу у пользователя.

Когда хватит родной печати 1С

1С:Бухгалтерия 8 с версии 3.0.142 сама печатает инвентарные этикетки основных средств (ОС) со штрихкодами для терминала сбора данных (ТСД): команда «Инвентарные этикетки» в документах «Поступление ОС» и «Принятие к учету ОС», сервис «ОС и НМА, Сервис, Печать инвентарных этикеток». Если ОС ведутся в ней и обход идет с ТСД, печатайте этикетки там. QR-код со ссылкой на карточку эта печать не дает, за ним и нужен запрос к API.

Какой код выбрать под сканер и под телефон, разобрано в статье штрих-код или QR-код для инвентаризации, а другие сценарии с кодами из учетной системы собраны в базе знаний.

FAQ

Как напечатать больше 1500 кодов из 1С?

Разбейте выборку на части по 1500 строк и отправьте каждую отдельным запросом, на каждую часть придет свой PDF. Без ключа проходит 10 запросов в минуту, лимит на сутки и ключ описаны в статье про API.

Что печатать, если у товаров нет карточек на сайте?

QR-код с текстом: уберите из тела url_template, добавьте content_type со значением text и собирайте строку как «Код | Наименование», разделитель у текста вертикальная черта. Приложение-сканер покажет код товара строкой, карточку такой QR-код не откроет.

Можно ли получить из 1С не PDF, а SVG или PNG?

Да, той же функцией: поставьте в output значение svg, svg_files или png. Расширение в ПолучитьИмяВременногоФайла заранее известно только у pdf: один лист или один код приходит файлом своего формата, несколько приходят архивом zip, имена файлов есть в таблице «Ответ» статьи про API.

Почему под кодом видна только часть наименования?

При коде 2 см под ним помещается 12 знаков подписи. При 2,5 см помещается 15 знаков, остаток подписи обрезается. Поставьте в тело qr_size_cm побольше или оставьте в подписи только нужное на бирке, например код вместо наименования.

Следующий шаг

Создайте внешнюю обработку с одной командой, вставьте три куска в модуль формы и на время пробы замените в тексте запроса ПЕРВЫЕ 1500 на ПЕРВЫЕ 3. Запустите команду и откройте PDF из сообщения: под кодами должны стоять наименования первых трех позиций справочника по порядку кодов, а телефон по коду должен открыть адрес каталога с кодом номенклатуры на месте {value}. Если вместо пути пришел код ответа, текст рядом говорит, что поправить.

Все поля запроса к API генератора QR-кодов: размер кода, рамка, формат и ориентация листа задаются полями того же JSON.

Соберите свой лист с QR-кодами

Вставьте список ссылок или загрузите файл, а мы разложим коды с подписями по листам A4 и отдадим PDF, SVG или PNG.

Открыть генератор
бесплатно, без регистрации