За основу взята публикация //infostart.ru/public/1276725/. В ней рассмотрен пример обмена через API с Честным знаком с использованием электронной подписи.
В примере //infostart.ru/public/1276725/ использовались:
- метод запроса информации по коду маркировки (коду идентификации КИ): facade/cis/cis_list
(На данный момент метод является устаревшим и удален из документации "Описание True API" (Версия 331.0). Актуальную документацию можно скачать в личном кабинете Честного знака в разделе "Помощь". )
- устаревшие url адреса.
В данной публикации сделан запрос кодов маркировки группы товаров "Табачная продукция" по периоду выпуска кодов (эмиссии). Информация по дате эмиссии отображена в личном кабинете честного знака в разделе "Коды маркировки". Код маркировки с последней датой эмиссии всегда отображен первым (верхним). Сортировка идёт по убыванию даты эмиссии. Таким же образом система "отдаёт" и список марок на запрос API.
Наши действия:
1. Создаем POST запрос /api/v4/true-api/cises/search - метод получения информации о списке КИ по заданным фильтрам (см. Описание True API" (Версия 331.0) ).
2. Получаем ответ. Система "отдаст" только одну страницу найденных кодов маркировки (по умолчанию 100 шт., задаётся параметрами пагинации).
3. Выгружаем ответ в таблицу КМ (Коды Маркировки).
4. Отправляем повторный запрос с изменёнными параметрами пагинации, которые указывают на последний КМ уже находящийся в таблице выгрузки КМ: lastEmissionDate - дата этого КМ и sgtin - сам код маркировки. Система "поймёт", что нужно "отдать" следующую страницу данных.
5. Получаем ответ.
6. выгружаем в таблицу КМ.
7. Повторяем операцию с п.4
Реализация (тестировалось на платформе 8.3.22.1704):
Параметры, необходимые для работы процедуры:
- токен (получение токена описано в публикации //infostart.ru/public/1276725/)
- новые url для запроса - в публикации //infostart.ru/public/1276725/ устарели (см. стр. 16 "Единая
аутентификация" Описание True API" (Версия 331.0 ):
- получение данных для получения токена: HTTPЗапрос = новый HTTPЗапрос("/api/v3/true-api/auth/key"); ,
- получение токена с использованием подписанных данных: HTTPЗапрос = Новый HTTPЗапрос("/api/v3/true-
api/auth/simpleSignIn",Заголовки);
- сервер : Сервер = "markirovka.crpt.ru";
- ДатаЭмиссииОт, ДатаЭмиссииДо - в процедуре преобразуются в строку к виду "2023-06-30T00:00:00.000Z";
- ГруппаТоваров - массив групп товаров (строковых значений, например, "tobacco" см. документацию)
- параметры пагинации (постраничного ответа сервера), при первом запросе можно не указывать данные параметры, но я указал, чтобы было проще и быстрее понять тому, кто в первый раз видит код:
- perPage - количество элементов (строк) на странице (по-умолчанию 100);
- ДатаЭмиссииКИ - дата выпуска кода маркировки (кода идентификации) - параметр обязательный (первый вызов запроса выполняется с указанной даты на форме увеличенной на сутки (86400 секунд), так как попытка запроса первой страницы результата поиска с точной датой даёт результат с начала следующих суток) , для запроса дата преобразуется к виду "2023-06-30T00:00:00.000Z";
- ИдентификационныйНомерSGTIN - GTIN + серийный номер - параметр обязательный (при первом запросе можно присваивать"000000000000000000000", "0" или GTIN+серийный номер, присвоение "" даёт ошибку);
&НаСервере
Процедура ОтправитьЗапросНаСервере()
КМ.Очистить();
// Поддерживаемый запрос POST
Соединение = Новый HTTPСоединение(Сервер,443,,,,,Новый ЗащищенноеСоединениеOpenSSL);
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "application/json; charset=UTF-8");
Заголовки.Вставить("Accept", "application/json");
HTTPЗапрос = Новый HTTPЗапрос("/api/v4/true-api/cises/search",Заголовки);
HTTPЗапрос.Заголовки.Вставить("Authorization","Bearer "+Токен);
//-- тело запроса
ДанныеДляЗапроса = Новый Структура; // собираем в структуру параметры тела POST запроса
// далее записываем в JSON формат
// далее JSON - в строку запроса
// выполняем запроc
//--- Используемые параметры тела запроса
// filter - тип объект - параметры фильтрации - поиск КИ (кодов идентификации) по указанным значениям параметров КИ
// Вложенные параметры:
// *emissionDatePeriod - тип объект (структура) - период эмиссиии
// **from - тип - string (datetime) - дата эмиссии, от // пример "2023-06-20T00:00:00.000Z"
// **to - тип - string (datetime) - дата эмиссии, до // пример "2023-06-29T23:59:59.000Z"
// *states - тип массив объектов (структур)
// **status - тип string - Код статуса КИ - INTRODUCED - в обороте, WITHDRAWN - выбыл, только для табачных групп, RETIRED - выбыл, для остальных групп
// *productGroups - тип массив строк - Список товарных групп // tobacco - табачная продукция
//
//
// pagination - тип объект (структура) - Параметры пагинации - Обеспечивает постраничный вывод результата поиска КИ
// Вложенные параметры:
// *perPage - тип целое число - Максимальное количество записей на странице результата поиска
// Значение по умолчанию: 100. Значение параметра не должно превышать 1000
// *lastEmissionDate - тип - string (datetime) - Дата эмиссии КИ, с которой требуется начать вывод результата поиска
// *sgtin - тип string - Идентификационный номер SGTIN (GTIN + индивидуальный серийный номер),с которого требуется начать вывод результата поиска
//
ДанныеДляЗапроса_filter = Новый Структура; // структура внутреннего параметра filter
//--- Параметр *emissionDatePeriod Период эмиссии
ДатаЭмиссииОтСтр = ЗаписатьДатуJSON(ДатаЭмиссииОт,ФорматДатыJSON.ISO)+".000Z";
ДатаЭмиссииДоСтр = ЗаписатьДатуJSON(КонецДня(ДатаЭмиссииДо),ФорматДатыJSON.ISO)+".000Z";
//--- Параметр
emissionDatePeriod_Структура = Новый Структура;
//ДатаЭмиссииОтСтр = "2023-06-20T00:00:00.000Z";
//ДатаЭмиссииДоСтр = "2023-06-29T23:59:59.000Z";
emissionDatePeriod_Структура.Вставить("from",ДатаЭмиссииОтСтр);
emissionDatePeriod_Структура.Вставить("too",ДатаЭмиссииДоСтр);
ДанныеДляЗапроса_filter.Вставить("emissionDatePeriod",emissionDatePeriod_Структура);
//--- Параметр *states - Список статусов КИ (массив объектов)
СтатусыКМ = Новый Массив;
СтатусКМ = Новый Соответствие;
СтатусКМ.Вставить("status","INTRODUCED"); // **status Код статуса КИ ( INTRODUCED - в обороте )
СтатусыКМ.Добавить(СтатусКМ);
//---
//ДанныеДляЗапроса_filter.Вставить("states",СтатусыКМ);
//--- Параметр *productGroups - Список товарных групп
МассивГруппТоваров = Новый Массив;
//МассивГруппТоваров.Добавить("tobacco");
МассивГруппТоваров.Добавить(ГруппаТоваров);
ДанныеДляЗапроса_filter.Вставить("productGroups",МассивГруппТоваров);
//pagination - структура - пагинация - параметры пагинации - обеспечивает постраничный вывод результата поиска КИ
//ДатаЭмиссииКИ = "2023-06-30T00:00:00.000Z";
ДатаЭмиссииКИ = ЗаписатьДатуJSON(ДатаЭмиссииДо+86400,ФорматДатыJSON.ISO)+".000Z";
ИдентификационныйНомерSGTIN = "000000000000000000000"; // номер кода маркировки, с которого требуется начать вывод
ДанныеДляЗапроса_pagination = Новый Структура;
perPage = Формат(110,"ЧЦ=10");
ДанныеДляЗапроса_pagination.Вставить("perPage",perPage);
ДанныеДляЗапроса_pagination.Вставить("lastEmissionDate",ДатаЭмиссииКИ);
ДанныеДляЗапроса_pagination.Вставить("sgtin",ИдентификационныйНомерSGTIN);
ДанныеДляЗапроса.Вставить("filter",ДанныеДляЗапроса_filter);
ДанныеДляЗапроса.Вставить("pagination",ДанныеДляЗапроса_pagination);
ПоследняяСтраницаОтветаНаЗапрос = ложь;
Запись_JSON = Новый ЗаписьJSON; //ЗаписьJSON
Пока НЕ ПоследняяСтраницаОтветаНаЗапрос Цикл
Запись_JSON.УстановитьСтроку();
ЗаписатьJSON(Запись_JSON,ДанныеДляЗапроса);
СтрокаДляЗапроса = Запись_JSON.Закрыть();
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаДляЗапроса,КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Ответ = Соединение.ОтправитьДляОбработки(HTTPЗапрос);
Если Ответ.КодСостояния = 200 Тогда
Сообщить("Код ответа на запрос: "+Ответ.КодСостояния+ " - выполнен успешно.");
Чтение_JSON = Новый ЧтениеJSON;
Чтение_JSON.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
ОтветНаЗапрос = ПрочитатьJSON(Чтение_JSON, Ложь);
Сообщить("Эта последняя станица результатов: "+ОтветНаЗапрос.isLastPage);
ПоследняяСтраницаОтветаНаЗапрос = ОтветНаЗапрос.isLastPage;
ОтветНаЗапросРезультат = ОтветНаЗапрос.result;
n=0;
Для Каждого элемент Из ОтветНаЗапросРезультат Цикл
строка = КМ.Добавить();
n=n+1;
строка.n = n;
строка.gtin = элемент.gtin;
строка.sgtin = элемент.sgtin;
строка.status = элемент.status;
строка.emissionDate = элемент.emissionDate;
строка.applicationDate = элемент.applicationDate;
строка.generalPackageType = элемент.generalPackageType;
строка.ownerINN = элемент.ownerINN;
строка.productGroup = элемент.productGroup;
Если элемент.Свойство("parent") Тогда
строка.parent = элемент.parent;
КонецЕсли;
КонецЦикла;
Если КМ.Количество()>0 Тогда
ДанныеДляЗапроса.Удалить("pagination");
ДанныеДляЗапроса_pagination.Удалить("lastEmissionDate");
ДанныеДляЗапроса_pagination.Удалить("sgtin");
ДанныеДляЗапроса_pagination.Вставить("lastEmissionDate",строка.emissionDate);
ДанныеДляЗапроса_pagination.Вставить("sgtin",строка.sgtin);
ДанныеДляЗапроса.Вставить("pagination",ДанныеДляЗапроса_pagination);
Иначе
Прервать;
КонецЕсли;
Иначе
Сообщить("Код ответа на запрос: "+Ответ.КодСостояния +" - ошибка!" );
Прервать;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Как работает обработка.
1. Делается запрос кодов маркировки.
2. Полученные коды маркировки со статусом INTRODUCED - "в обороте" переносятся в таблицу "Выбытие" командой
"Перенести в выбытие". Можно сделать перенос выборочно, например, только блоков (упаковок) - GROUP, т.к.
списывая блоки списывается и их содержимое (единицы товара UNIT).
3. Во вкладке "Выбытие" задаются параметры документа списания (выбытия).
4. Выполняется команда "Отправить запрос списания".
5. В случае успешного создания документа в Честном знаке получаем сообщение об идентификаторе созданного
документа (id документа).
6. Статус созданного документа можно проверить в личном кабинете честного знака.
7. После успешной обработки документа коды маркировки перейдут в статус WRITTEN_OFF - списан, можно
выполнить проверку перезапросив коды маркировки на вкладке КМ.
Тестировалось с группой товара "Табачная продукция". В обработку встроен выбор групп: "Альтернативная табачная продукция", "Никотиносодержащая табачная продукция".
"Выбытие (для подачи сведений через Единый метод создания документов)" (см. документацию Описание True API Версия 338.0, стр. 292). Подача сведений доступна для всех товарных групп, кроме товарных групп «Морепродукты», «Товары из натурального меха».
Обработка сохраняет введенные ранее значения:
1. сертификат,
2. токен (действителен 10 часов, нет смысла при каждом открытии обработки получать новый токен),
3. дату эмиссии От, дату эмиссии До,
4. ИНН участника,
5. причину списания,
6. адрес списания,
7. название документа выбытия.