Примеры работы с API в Честный знак (обувь)
Файлы
ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.
Подписка PRO — скачивайте любые файлы со скидкой до 85% из Базы знаний
Оформите подписку на компанию для решения рабочих задач
Оформить подписку и скачать решение со скидкойВы можете заказать платную доработку или адаптацию этой разработки под вашу конфигурацию на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.
Для начала вы должны быть зарегистрированы в Честном знаке(https://shoes.crpt.ru/) и иметь сертификат для входа. Честный знак нам предлагает воспользоватся инструкцией по ссылке https://shoes.crpt.ru/docs/API_Track_and_Trace_Government_Information_System_v18_en.pdf она вам поможет, но обращайте внимание, что там довольно много неточностей и устаревших данных.
Начнем с того что нам нужно получить токен для работы с API честного знака. Для этого нам нужно сделать GET запрос в ответ на который мы получим поля GUID(Уникальный идентификатор) и DATA(Данные).
GET Запрос из 1с выглядит следующим образом:
сайт = "ismp.crpt.ru";
хСоединение = Новый HTTPСоединение(Сайт,443,,,,,Новый ЗащищенноеСоединениеOpenSSL);
Запрос = новый HTTPЗапрос("/api/v3/auth/cert/key");
хОтвет = хСоединение.ВызватьHTTPМетод("GET",Запрос);
Если хОтвет.КодСостояния <> 200 Тогда
Сообщить("Ошибка. Код ответа " + хОтвет.КодСостояния);
Возврат;
КонецЕсли;
Сообщение = хОтвет.ПолучитьТелоКакСтроку("UTF-8");
//десериализуем данные о клиенте из JSON
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Сообщение);
ОборудованиеJSON = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
УИД = ОборудованиеJSON.uuid;
Данные = ОборудованиеJSON.data;
Файл = Новый ЗаписьТекста("C:\1\test.txt");
Файл.ЗаписатьСтроку(Данные);
Файл.Закрыть();
Данные нам необходимо подписать нашей электронной подписью и прислать в ответ ЧЗ. Для того что бы подписать данные воспользуемся сайтом КриптоПРО https://www.cryptopro.ru/sites/default/files/products/cades/demopage/cades_bes_sample.html Там нам нужно выбрать наш сертификат, а в поле "Данные для подписи" вставить полученные данные(в моем случае текст из файла test.txt).
Сформированную подпись копируем в текстовый файл и с помощью Notepad избавляемся от пробелов и переносов строки. Выделяем весь текст жмем Ctrl+H в поле поиска пишем \n затем \r поле замены оставляем пустым. Жмем заменить все.
GUID и текст из получившегося файла нам нужно отправить POST запросом в ЧЗ.
Процедура ПолучитьТокенНаСервере()
Текст = Новый ТекстовыйДокумент;
ПолноеИмяФайла = "C:\1\out.txt";
Текст.Прочитать(ПолноеИмяФайла);
КоличествоСтрок = Текст.КоличествоСтрок();
Данные = "";
Для Счетчик = 1 по КоличествоСтрок Цикл
ТекСтрока = Текст.ПолучитьСтроку(Счетчик);
Данные = Данные + ТекСтрока;
КонецЦикла;
Соединение = Новый HTTPСоединение("ismp.crpt.ru",443,,,,,Новый ЗащищенноеСоединениеOpenSSL);
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "application/json; charset=UTF-8");
Заголовки.Вставить("Accept", "application/json");
Запрос = Новый HTTPЗапрос("/api/v3/auth/cert/",Заголовки);
ЗаписьJOIN = Новый ЗаписьJSON;
ЗаписьJOIN.УстановитьСтроку();
ДанныеДляЗапроса = Новый Структура;
ДанныеДляЗапроса.Вставить("uuid",УИД);
ДанныеДляЗапроса.Вставить("data",Данные);
ЗаписатьJSON(ЗаписьJOIN,ДанныеДляЗапроса);
СтрокаДляЗапроса = ЗаписьJOIN.Закрыть();
//Формируем ответ клиенту
Запрос.УстановитьТелоИзСтроки(СтрокаДляЗапроса,КодировкаТекста.UTF8,
ИспользованиеByteOrderMark.НеИспользовать);
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Если Ответ.КодСостояния <> 200 Тогда
Сообщить("Ошибка. Код ответа " + Ответ.КодСостояния);
ЧтениеJSON = Новый ЧтениеJSON;
Сообщение = Ответ.ПолучитьТелоКакСтроку("UTF-8");
ЧтениеJSON.УстановитьСтроку(Сообщение);
СообщениеJSON = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
Сообщить(СообщениеJSON.error_message);
Возврат;
КонецЕсли;
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
Токен = ПрочитатьJSON(ЧтениеJSON, Ложь).token;
КонецПроцедуры
В ответ мы получим токен который нужно будет использовать в любых дальнейших запросах.
После получения токена можно использовать любые методы работы с документами и маркировками описанными в документации. Вот мой пример получения маркировок находящихся в обороте.
сайт = "ismp.crpt.ru";
хСоединение = Новый HTTPСоединение(Сайт,443,,,,,Новый ЗащищенноеСоединениеOpenSSL);
Запрос = новый HTTPЗапрос("/api/v3/facade/identifytools/listV2?cisStatus=INTRODUCED&limit=10000");
запрос.Заголовки.Вставить("Authorization","Bearer "+Токен);
хОтвет = хСоединение.ВызватьHTTPМетод("GET",Запрос);
Если хОтвет.КодСостояния <> 200 Тогда
Сообщить("Ошибка. Код ответа " + хОтвет.КодСостояния);
ЧтениеJSON = Новый ЧтениеJSON;
Сообщение = хОтвет.ПолучитьТелоКакСтроку("UTF-8");
ЧтениеJSON.УстановитьСтроку(Сообщение);
СообщениеJSON = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
Сообщить(СообщениеJSON.error_message);
Возврат;
КонецЕсли;
Сообщение = хОтвет.ПолучитьТелоКакСтроку("UTF-8");
//десериализуем данные о клиенте из JSON
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Сообщение);
ОборудованиеJSON = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
Результат = ОборудованиеJSON.results;
Для Каждого Строка Из Результат Цикл
НоваяСтрока = ТаблицаВыбывших.Добавить();
НоваяСтрока.Маркировка = Строка.cis;
КонецЦикла;
Теперь нам необходимо отгрузить маркировки другому юр.лицу. Изначально я пытался создать документ с помощью API в формате JSON, но постоянные ошибки заставили меня сделать это через XML. Выглядело это следующим образом. Сначала я создаю JSON документ
РеквизитыДокумента = Новый Структура;
РеквизитыДокумента.Вставить("trade_participant_inn_sender",ИННСобственника); //ИНН собственника
РеквизитыДокумента.Вставить("trade_participant_inn_receiver",ИННПолучателя); //ИНН получателя
РеквизитыДокумента.Вставить("trade_participant_inn_owner",ИННСобственника); //ИНН собственника
РеквизитыДокумента.Вставить("transfer_date",Формат(ТекущаяДата(),"ДФ=dd.MM.yyyy")); //Дата передачи маркированных товаров
РеквизитыДокумента.Вставить("move_document_number",НомерДокумента); //Номер первичного документа
РеквизитыДокумента.Вставить("move_document_date",Формат(ДатаДокумента,"ДФ=dd.MM.yyyy")); //Дата первичного документа
РеквизитыДокумента.Вставить("turnover_type","SELLING"); //Код типа отгрузки
Товары = Новый Массив;
Для Каждого Строка ИЗ ТаблицаМаркировок Цикл
Отбор = Новый Структура;
Отбор.Вставить("Маркировка",Строка.Маркировка);
Если ТаблицаВыбывших.НайтиСтроки(Отбор).Количество() > 0 Тогда
СтруктураТоваров = Новый Структура;
СтруктураТоваров.Вставить("ki","<![CDATA["+Строка.Маркировка+"]]>"); //Уникальный идентификатор товара
СтруктураТоваров.Вставить("cost",Строка.Цена);
СтруктураТоваров.Вставить("vat_value",Строка.НДС);
Товары.Добавить(СтруктураТоваров);
КонецЕсли;
КонецЦикла;
РеквизитыДокумента.Вставить("product",Товары); //ИНН собственника
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.ОткрытьФайл("C:\1\pills.json");
ЗаписатьJSON(ЗаписьJSON,РеквизитыДокумента);
ЗаписьJSON.Закрыть();
На структуру полей можно ориентироваться с помощью документации и данного шаблона XML
<?xml version="1.0" encoding="UTF-8"?>
<shipment version="4" action_id="10">
<trade_participant_inn_sender>6317136467</trade_participant_inn_sender>
<trade_participant_inn_receiver>7721546864</trade_participant_inn_receiver>
<trade_participant_inn_owner>6317136467</trade_participant_inn_owner>
<transfer_date>05.12.2019</transfer_date>
<move_document_number>123</move_document_number>
<move_document_date>05.12.2019</move_document_date> <!-- Комментарий -->
<turnover_type>SELLING</turnover_type>
<products_list>
<product>
<ki><![CDATA[0147012334793726213D6uKeCK7LtuO]]></ki>
<cost>33030.5</cost>
<vat_value>270.85</vat_value>
</product>
</products_list>
</shipment>
Полученный JSON файл мы загружаем в конвентер JSON-XML. Я использовал этот https://www.convertjson.com/json-to-xml.htm Он немного криво конвентирует поэтому после конвертации приводим вид файла по шаблону.
Полученный xml файл нам остается загрузить в честный знак. Для этого заходим в список документов в ЧЗ. Внизу нажимаем кнопку загрузить, выбираем пункт отгрузка и загружаем наш XML файл. После успешной загрузки без единой ошибки другое юр. лицо может принят себе отгруженные маркировки с помощью создания документа приемки.
Обработка тестировалась на платформе: 8.3.11.3034.
Вступайте в нашу телеграмм-группу Инфостарт
См. также
Обмен с ГосИС Бюджетный учет Регламентированный учет и отчетность Бухгалтер Пользователь 1С:Предприятие 8 1С:Бухгалтерия 3.0 1С:Управление холдингом Химическая промышленность Государственные, бюджетные структуры Электротехника и микроэлектроника Машиностроение и приборостроение Металлургическая промышленность Россия Бухгалтерский учет Бюджетный учет Платные (руб)
Автоматизация раздельного учета в 1С:Бухгалтерии по ГОЗ в соответствии с 275-ФЗ. Готовое решение для учета госконтрактов, формирования отчетности и контроля исполнения. Поддержка военной приемки, НИОКР и требований Минпромторга. Профессиональный консалтинг и регулярные обновления продукта
40000 руб.
28.08.2020 576287 4237 145
Бюджетный учет Обмен с ГосИС Бухгалтер 1С:Предприятие 8 1С:Бухгалтерия 3.0 Государственные, бюджетные структуры Россия Бухгалтерский учет Платные (руб)
Доработка конфигурации 1С:Бухгалтерия предприятия, редакция 3.0. реализована в виде расширения. Предназначена для ведения раздельного учета и автоматизации заполнения отчетности исполнения контрактов ГОЗ в конфигурациях 1С БП КОРП, ПРОФ, Базовая, БИТ.ФИНАНС.
62220 руб.
16.08.2019 108357 338 97
Оптовая торговля Розничная торговля Обмен с ГосИС Разработчик Бухгалтер Пользователь 1С:Предприятие 8 1C:Бухгалтерия Розничная и сетевая торговля (FMCG) Оптовая торговля, дистрибуция, логистика Россия Бухгалтерский учет Управленческий учет Платные (руб)
Решение создано для помощи разработчикам, интеграторам и другим заинтересованным лицам по настройке системы маркировки обуви, одежды, лекарств, табака, фото, молока, духов(парфюма), питьевой воды, велосипедов и шин. Задавайте вопросы по работе с ЦРПТ, GS1, ЭДО, Национальным каталогом, накоплен опыт и знания по данным темам.
20900 руб.
18.03.2019 128325 111 115
Оптовая торговля Розничная торговля Обмен с ГосИС Бухгалтер 1С:Предприятие 8 1С:Управление торговлей 10 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 Розничная и сетевая торговля (FMCG) Оптовая торговля, дистрибуция, логистика Рестораны, кафе и фаст-фуд Россия Бухгалтерский учет Управленческий учет Акцизы Платные (руб)
Автоматизация учета ЕГАИС в 1С для оптовой торговли, производства и импорта алкогольной продукции. Получение и отправка ТТН, отправка акта о постановке на баланс и акта о списании. Получение остатков. Загрузка и сопоставление номенклатуры и контрагентов. Оправка в ЕГАИС отчетов о производстве и импорте.
1091 руб.
15.12.2015 188356 1403 374
Обмен с ГосИС Бухгалтер Пользователь 1С 8.3 1С 8.5 1С:Бухгалтерия 3.0 1С:ERP Управление предприятием 2 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 1.6 1С:Управление нашей фирмой 3.0 1С:Управление торговлей 11 1С:Розница 2 1С:Розница 3.0 1С:РМК Ювелирная промышленность и торговля Россия Управленческий учет Платные (руб)
Интеграция для работы 1С с ГИИС ДМДК. Государственная интегрированная информационная система в сфере контроля за оборотом драгоценных металлов, драгоценных камней и изделий из них на всех этапах этого оборота.
80000 руб.
12.04.2022 28008 216 34
Обмен с ГосИС Логистика, склад и ТМЦ Разработчик Пользователь 1С:Предприятие 8 1С:Розница 2 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Россия Платные (руб)
Внешняя обработка для инвентаризации кодов маркировки в системе "Честный знак". Позволяет быстро определить и списать коды маркировки проданного, испорченного, утраченного (полный перечень причин списания указан ниже) товара, которые всё ещё числятся за организацией. Привести в соответствие остатки маркированного товара программы 1С и системы "Честного знака".
6649 руб.
09.01.2024 22119 228 30
Обмен с ГосИС Разработчик 1С:Предприятие 8 1C:Бухгалтерия Оптовая торговля, дистрибуция, логистика Россия Управленческий учет Платные (руб)
Универсальная конфигурация ХамелеонЗерно для взаимодействия с системой ФГИС Зерно (тестовый+рабочий контур) может использоваться для интеграции в любую конфигурацию на базе 1С, версии ПРОФ и выше. Работа через API 1.0.7 и на API 1.0.8. Для удобства реализован общий интерфейс в виде обработки, схожей с интерфейсом ФГИС Зерно, но возможностей гораздо больше, т.к. при интеграции в Вашу учетную систему, можно на основании Ваших справочников и документов, создавать соответствующие документы и справочники в системе ФГИС Зерно и наоборот.
25498 руб.
27.06.2023 9805 53 2
Оптовая торговля Производство готовой продукции (работ, услуг) Розничная торговля Обмен с ГосИС Разработчик Бухгалтер Пользователь 1С:Предприятие 8 1C:Бухгалтерия Сельское хозяйство и рыболовство Розничная и сетевая торговля (FMCG) Оптовая торговля, дистрибуция, логистика Рестораны, кафе и фаст-фуд Пищевая промышленность Россия Бухгалтерский учет Управленческий учет Платные (руб)
Универсальная конфигурация Хамелеон Меркурий для взаимодействия с системой Меркурий (тестовый+рабочий+демо контур) может использоваться для интеграции в любую конфигурацию на базе 1С, версии ПРОФ и выше. Основное отличие от других решений - работа через веб-интерфейс и API 2.0(API 2.1). Для удобства реализован общий интерфейс в виде обработки, схожей с интерфейсом Меркурий, но возможностей гораздо больше, т.к. при интеграции в Вашу учетную систему, можно на основании Ваших справочников и документов, создавать соответствующие документы и справочники в системе Меркурий и наоборот.
11000 руб.
08.11.2017 132033 293 153
Функция ПодписатьЭЦПЧерезСОМОбъекты(СтрокаДляПодписи, СтрокаВBase64 = Истина, Открепл) Экспорт
Попытка
comStore = Новый COMОбъект("CAdESCOM.Store");
comCPSigner = Новый COMОбъект("CAdESCOM.CPSigner"); // Аналог "CAPICOM.Signer".
comSignedData = Новый COMОбъект("CAdESCOM.CadesSignedData");
Исключение
Сообщить("Не установлен КриптоПро!");
Возврат "";
КонецПопытки;
comStore.Open(
2, // StoreLocation - CAPICOM_CURRENT_USER_STORE.
"MY", // StoreName
); // OpenMode - CAPICOM_STORE_OPEN_READ_ONLY.
comCertificates = comStore.Certificates;
comStore.Close();
comStore = Неопределено;
КоличествоСертификатов = comCertificates.Count;
Если КоличествоСертификатов > 0 Тогда
// Убрать "сертификаты, в которых отсутствует закрытый ключ".
comCertificates = comCertificates.Find(6, 2); // (CAPICOM_CERTIFICATE_FIND_EXTENDED_PROPERTY, CAPICOM_PROPID_KEY_PROV_INFO)
КоличествоСертификатов = comCertificates.Count;
КонецЕсли;
Если КоличествоСертификатов > 0 Тогда
// Оставить "только сертификаты, действительные в настоящее время".
comCertificates = comCertificates.Find(9, ); // (CAPICOM_CERTIFICATE_FIND_TIME_VALID, "the current time is assumed")
КоличествоСертификатов = comCertificates.Count;
КонецЕсли;
Если КоличествоСертификатов = 1 Тогда
comСертификат = comCertificates.Item(1); // Выбрать единственный.
ИначеЕсли КоличествоСертификатов = 0 Тогда
comCertificates = Неопределено;
comCPSigner = Неопределено;
comSignedData = Неопределено;
Сообщить("Не найдены актуальные ключи ЭЦП для подписи данных!");
Возврат "";
Иначе
СертификатыДляВыбора = Новый СписокЗначений;
флНашли = Ложь;
Для i = 1 По КоличествоСертификатов Цикл
СертификатыДляВыбора.Добавить(i, comCertificates.Item(i).SubjectName);
comСертификат = comCertificates.Item(i);
Если (Найти(comСертификат.SubjectName,"ИНН="+Док.Фирма.ИНН)>0) ИЛИ
(Найти(comСертификат.SubjectName,"ИНН=00"+Док.Фирма.ИНН)>0) Тогда
флНашли = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Если НЕ флНашли Тогда
i = СертификатыДляВыбора.ВыбратьЭлемент();
Если i = Неопределено Тогда
comCertificates = Неопределено;
comCPSigner = Неопределено;
comSignedData = Неопределено;
Сообщить("Не выбран ключ ЭЦП!");
Возврат "";
Иначе
comСертификат = comCertificates.Item(i.Значение); // Выбрать указанный пользователем.
КонецЕсли;
КонецЕсли;
КонецЕсли;
comCertificates = Неопределено;
comCPSigner.Certificate = comСертификат;
// + Что-то из этого может быть нужным.
// comCPSigner.TSAAddress = "http://cryptopro.ru/tsp/";
// comCPSigner.Options = 0; // CAPICOM_CERTIFICATE_INCLUDE_CHAIN_EXCEPT_ROOT. Ещё есть CAPICOM_CERTIFICATE_INCLUDE_WHOLE_CHAIN и CAPICOM_CERTIFICATE_INCLUDE_END_ENTITY_ONLY.
// -
comСертификат = Неопределено;
Если СтрокаВBase64 Тогда // Очень важно!
comSignedData.ContentEncoding = 1; // CADESCOM_BASE64_TO_BINARY
//Иначе // Так и остаётся 0 - CADESCOM_ENCODE_BINARY
КонецЕсли;
comSignedData.Content = СтрокаДляПодписи;
ПодписанныеДанные = comSignedData.SignCades(
comCPSigner, // Signer
1, // CadesType, CADESCOM_CADES_BES.
Открепл, // bDetached - "флаг открепленной подписи (исходное сообщение не включается в итоговый CMS-контейнер)".
); // EncodingType - по умолчанию CAPICOM_ENCODE_BASE64.
comCPSigner = Неопределено;
comSignedData = Неопределено;
Возврат УбратьСимволы1013(ПодписанныеДанные);
КонецФункции ПоказатьТелоЗапроса = Новый Структура;
ТелоЗапроса.Вставить("document_num", СокрЛП(Док.Номер));
ТелоЗапроса.Вставить("document_date", ДатаUTC(Док.Дата));//"2019-11-14T00:00:00.000Z");
ТелоЗапроса.Вставить("transfer_date", ДатаUTC(ТекущаяДата()));//(Док.Дата));
ТелоЗапроса.Вставить("receiver_inn", СокрЛП(Док.Контрагент.ИНН));
ТелоЗапроса.Вставить("sender_inn", СокрЛП(Док.Фирма.ИНН));
ТелоЗапроса.Вставить("turnover_type", "SELLING");
ТелоЗапроса.Вставить("to_not_participant", "false");
ТелоЗапроса.Вставить("products", Новый Массив);
Запрос = Новый Запрос("ВЫБРАТЬ
| ОтгрузкаСоСкладаТоварыШК.ШК,
| ОтгрузкаСоСкладаТоварыШК.Номенклатура
|ИЗ
| Документ.ОтгрузкаСоСклада.ТоварыШК КАК ОтгрузкаСоСкладаТоварыШК
|ГДЕ
| ОтгрузкаСоСкладаТоварыШК.Ссылка.Основание = &Основание");
Запрос.Параметры.Вставить("Основание", Док);
Выб = Запрос.Выполнить().Выбрать();
Пока Выб.Следующий() Цикл
СтрокаТЧ = Новый Структура;
СтрокаТЧ.Вставить("uit_code", СокрЛП(Выб.ШК));
СтрокаТЧ.Вставить("product_description", СокрЛП(Выб.Номенклатура.Наименование));
ТелоЗапроса.products.Добавить(СтрокаТЧ);
КонецЦикла;
ЗаписьJSON = Новый ЗаписьJSON();
ПараметрыЗаписиJSON = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет, "");
ЗаписьJSON.УстановитьСтроку(ПараметрыЗаписиJSON);
ЗаписатьJSON(ЗаписьJSON, ТелоЗапроса);
ТекстJSON = ЗаписьJSON.Закрыть();
ТекстXML64 = ШтрихкодВBase64(ТекстJSON);
ПодписанныеДанные = ПодписатьЭЦПЧерезСОМОбъекты(ТекстXML64, Истина, Истина);
HTTP = Новый HTTPСоединение("ismp.crpt.ru", 443, , , , , Новый ЗащищенноеСоединениеOpenSSL);
//URLЗапроса = "/api/v3/lk/documents/shipment/create";
URLЗапроса = "/api/v3/lk/documents/create";
HTTPЗапрос = Новый HTTPЗапрос(URLЗапроса);
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json");
HTTPЗапрос.Заголовки.Вставить("Authorization", "Bearer "+СокрЛП(Док.Фирма.ТокенЧЗ));
ТелоЗапроса = Новый Структура;
ТелоЗапроса.Вставить("product_document", ТекстXML64);
ТелоЗапроса.Вставить("document_format", "MANUAL");
ТелоЗапроса.Вставить("product_group", "shoes");
ТелоЗапроса.Вставить("type", "LP_SHIP_GOODS");
ТелоЗапроса.Вставить("signature", ПодписанныеДанные);
ЗаписьJSON = Новый ЗаписьJSON();
ПараметрыЗаписиJSON = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет, "");
ЗаписьJSON.УстановитьСтроку(ПараметрыЗаписиJSON);
ЗаписатьJSON(ЗаписьJSON, ТелоЗапроса);
ТекстJSON = ЗаписьJSON.Закрыть();
HTTPЗапрос.УстановитьТелоИзСтроки(ТекстJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Ответ = HTTP.ОтправитьДляОбработки(HTTPЗапрос);
ИДДок = Ответ.ПолучитьТелоКакСтроку();
Сообщить(ИДДок);
ДокОб = Док.ПолучитьОбъект();
ДокОб.ИдентификаторЧЗ=ИДДок;
ДокОб.СтатусЧЗ="";
ДокОб.ОшибкаЧЗ="";
ДокОб.ДействиеЧЗ="";
Попытка
ДокОб.Записать(РежимЗаписиДокумента.Запись);
Исключение
КонецПопытки; ПоказатьВ честный знак захожу без проблем, а при получении токена вот такая ошибка:
Ошибка. Код ответа 400
Организация не зарегистрирована
согласен взять любую конфу от 1с за день разобраться не составит труда.
но есть сам апи честного знака это УГ часть функций не работают как нужно, за два месяца работы с ними они уже сменили 2 версии причем функции постоянно устаревают. нужна была функция для получения информации по марке.
непонятно зачем делать несколько функций для одного и того же но, одна функция возвращает данные по марке, другая нет, причем по другой марке все с точностью до наоборот, техподдержка ни разу не ответила.
Выкладываю их описание, написано коряво но разобраться можно.
я всё сделал для 1С 7.7 и это несколько сложнее чем для 1С 8.3 т.к. не было примеров
но даже то, что ты тут "наваял" вообще полная хрень - зачем использовать конвентер JSON-XML ?
проще сразу XML формировать !
а уж подпись обрабатывать через блокнот вообще хрень полная...
подумай тем ли ты занимаешься? может пора сменить профессию?!?
Как там с типовой 1С, где всё есть, всё ещё никаких сложностей?
а что касается "всё есть в типовой" - то действительно есть, маркировка там есть, а если ты не отличаешь ЭДО от маркировки, то это твои личные трудности. Если ты напишешь чего нет в типовой по маркировке в контексте темы автора, то я ещё смогу что-то ответить, а так считаю тебя троллем с весенним обострением :-)
В контексте темы автора, лично к автору я вообще ни одной претензии не предъявил, он как раз молодец, очень подробно написал. Я ответил на твой первый коммент. Может, ЧСВ у тебя плохо влияет на память, так я напомню. Ты спросил у автора, зачем он вообще заморачивался с АПИ Честного знака, если "в типовой всё есть". Любые инструкции по интеграции типовых с Честным знаком первым пунктом включают настройку ЭДО. Это по поводу того. что я "не отличаю ЭДО от маркировки". Я пока только разбираюсь с реализацией функционала маркировок Честный знак (в УТ11.4), поэтому и ищу по форумам ответы на появляющиеся вопросы. Вот, на Мисте нашёл что в принципе маркировки можно не через ЭДО загружать, а вносить вручную. Пока тестирую...
хорошо, что ты написал про "Я пока только разбираюсь с реализацией функционала маркировок", теперь хоть мне понятен твой уровень претензии :-)
ты не понял вообще сути того, что я написал автору. Автор изобретал собственный велосипед вместо того чтобы разобраться с нормальной реализацией API в типовых и при этом он дал ссылку на документацию на английском языке... видимо он был на той же стадии что и ты сейчас и таких как ты запутает вместо того чтобы помогать ;-)
И тебе советую найти правильные места где брать информацию, а то будешь на мисте узнавать то, что есть на сайте честного знака.
Болтать с тобой я больше не буду, просто очень разный уровень понимания маркировки: то, что для тебя "вау открытие", для меня "блин, так делать нельзя - это не правильно"
Героически написали что то для семерки. Это много проще чем для 8, промеров работы с json и веб запросами для 7.7 в интернете много было задолго до, искать надо правильно. Автор молодец хотя бы в том что разобрался и смог получить результат. Сейчас наверняка уже допилил и взаимодействует с API без необходимости монстров в виде типовых модулей.
пост автора был написан 15 мая 2020, а не 2019-м году и уже было где посмотреть...
Пост автора про обувь, а не про сигареты, поэтому не знаю зачем ты тут про них написал
Если думаешь, что в 7.7 работать с json и подписью проще, чем в 8.3, то это далеко не так, но ты всё равно останешься при своём мнении :-)
даже здесь на инфостарте если написать поиск "api/v3/auth/cert/", то найдём публикацию
от 22.03.2020, соответственно в типовых уже был механизм взаимодействия с API с Честный знак о чём я и написал
и ещё раз - мне не понравился ОЧЕНЬ КРИВОЙ подход автора и поэтому я написал, что нет смысла изобретать свой велосипед...
Я делал и для 7.7 и для 8. В 7.7 получилось быстрее, меньше заморочек. Помню что в 8 были заморочки с битовостью платформы, а так же некоторые релизы не работали нормально с json, В 7 было проще она одна, одной версии.
Про 19 год я говорю не в том смысле когда автор сделал, а в том смысле что 1С с типовыми решениями не успевает вовремя и работать по принципу выйдет в типовой - оттуда вырежу - это подход не верный.
Если вы не помните, то маркировка обуви началась сильно раньше марта 2020 года. с 01.03.20 она должна уже была быть обязательной, но утром 1 марта перенесли,а нужно было быть уже готовыми. Стабильный релиз появился только к июню. При чем тут сигареты? Вы не знали что там один оператор и по сути один API, только местами методы отличаются.
У автора вполне себе нормальный подход, просто он не знал как подписать data. Потом ему подсказали и он исправил. И кому то наверное помог.
почему-то меня в который раз пытаются убедить, что работая в 1С нужно убирать переносы строк в блокноте, а xml получать из json
вы точно про 1С тут со мной общаетесь или это ветка для студентов "как сдать лабораторную работу по информатике" ???
такое можно делать когда сам разбираешься, но выкладывать как публикацию, чтобы все думали "вау как круто!" - это уже слишком :-)
Вопрос: как Вы разбираете json в 7.7 и пробовали ли разбирать большие документы?
Средняя поставка это 350 тысяч кизов. И да, все надо парсить и проверять.
Если парсер сходу не может проглотить весь набор данных, никто же не мешает кормить его порциями, зачем вы из мелкой проблемы раздуваете такие трудности. Тем более что структура то статическая. Вы реально считаете чем то серьезным разделить json и xml и обработать отдельно? По мне так рядовая задача...
Если мы говорим о накладных, то какой смысл туда пихать 7 тысяч кизов, если в обуви агрегация доступна не только для производителей а для любого УОТ? Я делал агрегацию коробок обуви в паллеты и накладные получались маленькие и удобные. Можно вообще агрегировать всю поставку в один код.
Что касается накладных, то передача кодов между УОТ в табаке только посредством ЭДО, накладные действительно небольшие, это уже ограничения операторов ЭДО.
В общем тема закрыта, дальнейшее обсуждение совершенно не касается публикации. Каждый при своем. Я считаю что автор статьи дал старт многим. Если бы я прочел такую статью в 2019 году, наверняка бы мне помогло. И это было бы быстрее чем, разобраться с тем как это сделали в типовой.
"то какой смысл туда пихать 7 тысяч кизов" - не я их пихаю, я их разбираю :-)
"Если бы я прочел такую статью в 2019 году" - согласен, только вот статья от мая 2020-го и только по этому поводу мой комментарий ;-)
для работы по API нужна цифровая подпись, но ставить её всем менеджерам "не хорошо", у меня 1С на терминальном сервере и сейчас сделано подписание запуском командного файла с утилитой RunAsUser.exe, т.е. сертификат подписи установлен в реестр windows для специального пользователя, а у обычных пользователей доступа к сертификату нет.
Ищу вариант вообще убрать сертификат подписи с сервера и обрабатывать запросы на рабочей станции в которую воткнут ключ.
Если есть такой опыт, то прошу рекомендаций :-)
токен у меня и так хранится в справочнике, точнее два токена для СУЗ и ГИС МТ
но менеджеры отправляют и принимают документы, поэтому нужна подпись произвольных данных, думаю, что именно это и делает веб сервис
Вот эти куски помогут - сам веб и работа с сертами.
listener = new HttpListener();
t = new Thread(Listen);
t.Start();
public void Listen()
{
//return;
string url = "http://*";
string port = ""+portnum;
string prefix = String.Format("{0}:{1}/", url, port);
try
{
listener.Stop();
}
catch
{ };
listener.Prefixes.Add(prefix);
try
{
listener.Start();
}
catch (Exception E)
{
SetText("!!!"+E.Message);
SetText(@"Запустите программу от имени администратора вот такую команду:netsh http add urlacl url=""http://*:9999/"" user=%username%",true);
return;
}
while (true)
{
if (closing) return;
//Ожидание входящего запроса
HttpListenerContext context;
try
{
context = listener.GetContext();
}
catch
{ break; }
var thread = new Thread(SendReply);
thread.Start(context);
}
}
public void SendReply(object parameter)
{
try
{
var context = (HttpListenerContext)parameter;
//Объект запроса
HttpListenerRequest request = context.Request;
//Объект ответа
HttpListenerResponse response = context.Response;
//Создаем ответ
string requestBody;
Stream inputStream = request.InputStream;
Encoding encoding = request.ContentEncoding;
StreamReader reader = new StreamReader(inputStream, encoding);
requestBody = reader.ReadToEnd();
//this.textBox1.Text += "" + request.HttpMethod + " request was caught: " + request.Url;
string qry;
try
{
qry = "" + Uri.UnescapeDataString(request.Url.OriginalString);
}
catch
{
return;
}
if (qry.Contains("favicon.ico"))
{
return;
}
//SetText(" request was caught: " + qry);
qry = qry.Replace("http://", "");
try
{
string res;
res = "Error";
string rr = qry.Split('/')[0];
bool error = false;
if (qry.Contains("кусочек урла - команда"))
{
Вот тут берем содержимео запроса (requestBody ), подписываем и отправляем в чз, читаем ответ, присваем его res, отдаем клиенту.
}
response.StatusCode = (int)HttpStatusCode.OK;
byte[] buffer = Encoding.UTF8.GetBytes(res);
response.ContentLength64 = buffer.Length;
Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
}
//Работа с сертификатами
public byte[] SignMe(byte[] msg, X509Certificate2 signerCert, bool detached = true)
{
ContentInfo contentInfo = new ContentInfo(msg);
SignedCms signedCms = new SignedCms(contentInfo, detached);
CmsSigner cmsSigner = new CmsSigner(signerCert);
cmsSigner.IncludeOption = X509IncludeOption.EndCertOnly;
signedCms.ComputeSignature(cmsSigner);
return signedCms.Encode();
}
//Список сертификатов
private void GetCerList(string certid)
{
X509Store store = new X509Store(StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
X509CertificateCollection certCollection = store.Certificates;
foreach (X509Certificate2 c in certCollection)
{
this.comboBox1.Items.Add(c.Subject);
if (c.GetSerialNumberString() == certid)
{
this.comboBox1.SelectedIndex = this.comboBox1.Items.Count - 1;
}
}
store.Close();
}
Показать
// Получаем случайные данные для формирования запроса на новый токен
// 1.2.1. Запрос авторизации при единой аутентификации
WinHttp = Создатьобъект("WinHttp.WinHttpRequest.5.1");
//ТекстЗапроса=Маркировка_АдресИСМП+"/auth/cert/key";
ТекстЗапроса=Маркировка_АдресTrueAPI+"/auth/key";
WinHttp.Open("GET",ТекстЗапроса,0);
WinHttp.SetRequestHeader("Content-type","application/json;charset=UTF-8");
WinHttp.SetRequestHeader("Accept","application/json;charset=UTF-8");
WinHttp.SetRequestHeader("Cache-Control","no-cache");
Если флОтладка=1 Тогда
Сообщить(_ПрефикСообщений+"Текст запроса GET "+ТекстЗапроса);
КонецЕсли;
WinHttp.Send();
ТекстОтвета=WinHttp.ResponseText();
Если WinHttp.Status=200 Тогда
// имеем ответ такого вида
// {"uuid":"d5933dc7-d9a5-40cf-ada4-6425c080dfae","data":"SCKSQQSXCVFRHNOZVXQAQOQTPEZFFD"}
спРезультатРазбора=ТекстJSONВОбъект(ТекстОтвета); // Список из двух значений uuid и data
Если флОтладка=1 Тогда
Сообщить(_ПрефикСообщений+"Ответ на запрос "+Лев(ТекстОтвета,400));
ВывестиРезультатРазбора(спРезультатРазбора);
КонецЕсли;
//Возврат спРезультатРазбора;
Иначе
Сообщить(_ПрефикСообщений+"Не получилось получить исходные данные для формирования токена !!!","!!!");
Сообщить("WinHttp.Status="+WinHttp.Status+" --> "+РасшифровкаСтатусовОтветовСистемы(WinHttp.Status));
Сообщить(Лев(ТекстОтвета,400));
Возврат ПолучитьПустоеЗначение("Справочник.Токены");
КонецЕсли;
// Подписываем полученные случайные даные
Если флОтладка=1 Тогда
Сообщить(_ПрефикСообщений+"Подписываем ""data"" подписью с отпечатком "+Токены.ОтпечатокСертификатаДляПодписи);
КонецЕсли;
ПодписанныеДанные=ПодписатьТекст(спРезультатРазбора.Получить("data"),Токены.ОтпечатокСертификатаДляПодписи,0,1);
спРезультатРазбора.Установить("data",ПодписанныеДанные); // Меняем значение data на "Подписанные УКЭП зарегистрированного УОТ случайные данные в base64 (электронная подпись присоединенная)"
Если ПустоеЗначение(ПодписанныеДанные)=1 Тогда
Сообщить(_ПрефикСообщений+"ошибка при подписании ""data""");
Возврат ПолучитьПустоеЗначение("Справочник.Токены");
КонецЕсли;
Если Токены.Объект.Вид()="Фирмы" Тогда
_omsConnection="";
Иначе
_omsConnection="/"+Токены.Объект.ИдентификаторСоединения;
КонецЕсли;
// Отправляем подписанные случайные данные для получения токена
// 1.2.2. Получение ключа сессии при единой аутентификации
WinHttp = Создатьобъект("WinHttp.WinHttpRequest.5.1");
//ТекстЗапроса=Маркировка_АдресИСМП+"/auth/cert";
ТекстЗапроса=Маркировка_АдресTrueAPI+"/auth/simpleSignIn"+_o msConnection;
WinHttp.Open("POST",ТекстЗапроса,0);
WinHttp.SetRequestHeader("Content-Type","application/json");
WinHttp.SetRequestHeader("Accept","application/json");
//WinHttp.SetRequestHeader("Content-Type","application/json;charset=UTF-8");
//WinHttp.SetRequestHeader("Accept","application/json;charset=UTF-8");
//WinHttp.SetRequestHeader("Cache-Control","no-cache");
//WinHttp.Option(2, "UTF-8");
//ТелоСообщенияPOST="{""uuid"":"""+спРезультатРазбора.Получить("uuid")+""",""data"":"""+спРезультатРазбора.Получить("data")+"""}";
ТелоСообщенияPOST=ОбъектВТекстJSON(спРезультатРазбора);
Если флОтладка=1 Тогда
Текст=СоздатьОбъект("Текст");
Текст.ДобавитьСтроку(ТелоСообщенияPOST);
Текст.Записать(КаталогПользователя()+"ТелоСообщенияPOST.txt");
Сообщить(_ПрефикСообщений+"Текст запроса POST "+Лев(ТекстЗапроса,400));
Сообщить("Сохранён файл для просмотра параметров POST "+КаталогПользователя()+"ТелоСообщенияPOST.txt");
КонецЕсли;
WinHttp.Send(ТелоСообщенияPOST);
//WinHttp.Send(ADODB_Stream(ТелоСообщенияPOST));
//Stream = CreateObject("ADODB.Stream");
//Stream.Open();
//Stream.loadFromFile(КаталогПользователя()+"ТелоСообщенияPOST.txt");
//WinHttp.Send(Stream);
ТекстОтвета=WinHttp.ResponseText();
Если WinHttp.Status=200 Тогда
// имеем ответ такого вида
// {"token":"токен в формате JWT или простой токен для СУЗ"}
спРезультатРазбора=ТекстJSONВОбъект(ТекстОтвета);
Если флОтладка=1 Тогда
Сообщить(_ПрефикСообщений+"Ответ на запрос "+Лев(ТекстОтвета,400));
ПросмотрПараметра=ТекстОтвета;
ВывестиРезультатРазбора(спРезультатРазбора);
КонецЕсли;
Токены.Токен=спРезультатРазбора.Получить("token");
Если ПустоеЗначение(_omsConnection)=1 Тогда // Токен ИС МП
ТокенJWT=РасшифроватьТокенJWT(Токены.Токен); // Данные товкена JWT как строка таблицы значений
Если ПустоеЗначение(ТокенJWT.exp)=0 Тогда // Наименование нужно вычислять из значения exp - Время окончания срока действия, формат Unix time (number)
// вот так сдлеано в 1С 8 Наименование = МестноеВремя('19700101' + Цел(РезультатРазбораТокена.exp));
Токены.Наименование=ИзменитьДатуВремя("19700101 03:00:00",Цел(ТокенJWT.exp)); // 03:00:00 - это часовой пояс Москвы
Если флОтладка=1 Тогда
Сообщить("Срок действия: расчет по exp="+Цел(ТокенJWT.exp)+" >> "+Токены.Наименование);
КонецЕсли;
Иначе // ТокенJWT.exp не заполнено, тогда добавим 5 часов к текущему времени
Токены.Наименование=ИзменитьДатуВремя(Формат(ТекущаяДата(),"ДГГГГММДД")+" "+ТекущееВремя(),10*60*60);
Если флОтладка=1 Тогда
Сообщить("Срок действия: добавим 10 часов к текущему времени");
КонецЕсли;
КонецЕсли;
//тзТокены.clientToken=ТокенJWT.jti;
Иначе // Токен СУЗ
Токены.Наименование=ИзменитьДатуВремя(Формат(ТекущаяДата(),"ДГГГГММДД")+" "+ТекущееВремя(),10*60*60);
КонецЕсли;
Токены.Записать();
Иначе
Сообщить(_ПрефикСообщений+"Не получилось получить данные токена !!!","!!!");
Сообщить("WinHttp.Status="+WinHttp.Status+" --> "+РасшифровкаСтатусовОтветовСистемы(WinHttp.Status));
Сообщить(Лев(ТекстОтвета,400));
ПросмотрПараметра=ТекстОтвета;
Возврат ПолучитьПустоеЗначение("Справочник.Токены");
КонецЕсли;
Показать
//*******************************************
// RFC 8259 The JavaScript Object Notation (JSON) Data Interchange Format
// в базе есть обработка JSON_Туда_И_Обратно
//
//Соответствие значений JSON значениям 1С
//Запись(Object) - СписокЗначений
//Массив(Array) - ТаблицаЗначений
//Число - Число
//Строка - Строка с поддержкой \', \", \\, \/, \t, \n, \r, \f, \b; без поддержки \uFFFF.
//Литерал true - "true"
//Литерал false - "false"
//Литерал null - "null"
Функция ОбъектВТекстJSON(Объект,ПереноситьСтроки=0,ВходящийОтступ="",Время="") Экспорт
// ^ ^ ^-время если для даты нужно точно указать время отличное от "00:00:00"
// ^ ^-отступ текущего уровня
// ^-признак формирования удобочитаемого файла (в основном для отладки)
Если ПереноситьСтроки=1 Тогда
ТекущийОтступ=РазделительСтрок+ВходящийОтступ;
Отступ=" ";
Двоеточие=": ";
Иначе
ТекущийОтступ="";
Отступ="";
Двоеточие=":";
КонецЕсли;
СтрокаJSON="";
Если ТипЗначенияСтр(Объект)="СписокЗначений" Тогда // Object
СтрокаJSON=СтрокаJSON+"{";
Для iii=1 По Объект.РазмерСписка() Цикл
ИмяСвойства="";
ЗначениеСвойства=Объект.ПолучитьЗначение(iii,ИмяСвойства);
Если ИмяСвойства="signature" Тогда
СтрокаJSON=СтрокаJSON+ТекущийОтступ+Отступ+""""+ИмяСвойства+ """"+Двоеточие+""""+ЗначениеСвойства+"""";
//////Текст=СоздатьОбъект("Текст");
//////Текст.ДобавитьСтроку(""""+ЗначениеСвойства+"""");
//////Текст.ДобавитьСтроку(ОбъектВТекстJSON(ЗначениеСвойства,ПереноситьСтроки,ВходящийОтступ+Отступ));
//////Текст.Записать(КаталогПользователя()+"signature.txt");
Иначе
СтрокаJSON=СтрокаJSON+ТекущийОтступ+Отступ+""""+ИмяСвойства+ """"+Двоеточие+ОбъектВТекстJSON(ЗначениеСвойства,ПереноситьСтроки,ВходящийОтступ+Отступ);
КонецЕсли;
Если iii<Объект.РазмерСписка() Тогда
СтрокаJSON=СтрокаJSON+",";
КонецЕсли;
КонецЦикла;
СтрокаJSON=СтрокаJSON+?(Объект.РазмерСписка()>0,ТекущийОтступ,"")+"}";
ИначеЕсли ТипЗначенияСтр(Объект)="ТаблицаЗначений" Тогда // Array
СтрокаJSON=СтрокаJSON+"[";
Для iii=1 По Объект.КоличествоСтрок() Цикл
ЗначениеСтроки=Объект.ПолучитьЗначение(iii,1); // берём данные только из первой колонки !!!
СтрокаJSON=СтрокаJSON+ТекущийОтступ+Отступ+ОбъектВТекстJSON(ЗначениеСтроки,ПереноситьСтроки,ВходящийОтступ+Отступ);
Если iii<Объект.КоличествоСтрок() Тогда
СтрокаJSON=СтрокаJSON+",";
КонецЕсли;
КонецЦикла;
СтрокаJSON=СтрокаJSON+?(Объект.КоличествоСтрок()>0,ТекущийОтступ,"")+"]";
ИначеЕсли ТипЗначенияСтр(Объект)="Строка" Тогда
Если Объект="true" Тогда
СтрокаJSON=СтрокаJSON+"true";
ИначеЕсли Объект="false" Тогда
СтрокаJSON=СтрокаJSON+"false";
ИначеЕсли Объект="null" Тогда
СтрокаJSON=СтрокаJSON+"null";
////////ИначеЕсли Лев(Объект,5)="<?xml" Тогда
//////// СтрОбъект=Объект;
//////// СтрОбъект=СтрЗаменить(СтрОбъект,"\n","");
//////// СтрокаJSON=СтрокаJSON+""""+СтрОбъект+"""";
Иначе
СтрОбъект=Объект;
СтрОбъект=СтрЗаменить(СтрОбъект,"\", "\\");
// СтрОбъект=СтрЗаменить(СтрОбъект,"/", "\/"); убрал 09.06.2021 т.к. в КМТ не проходило подписание
СтрОбъект=СтрЗаменить(СтрОбъект,"""","\""");
СтрОбъект=СтрЗаменить(СтрОбъект,Симв( 8),"\b");
СтрОбъект=СтрЗаменить(СтрОбъект,Симв( 9),"\t");
СтрОбъект=СтрЗаменить(СтрОбъект,Симв(10),"\n");
СтрОбъект=СтрЗаменить(СтрОбъект,Симв(12),"\f");
СтрОбъект=СтрЗаменить(СтрОбъект,Симв(13),"\r");
СтрокаJSON=СтрокаJSON+""""+СтрОбъект+"""";
КонецЕсли;
ИначеЕсли ТипЗначенияСтр(Объект)="Число" Тогда
СтрокаJSON=СтрокаJSON+Строка(Объект);
ИначеЕсли ТипЗначенияСтр(Объект)="Дата" Тогда
СтрОбъект=Формат(Объект,"ДГГГГММДД");
СтрОбъект=Лев(СтрОбъект,4)+"-"+Сред(СтрОбъект,5,2)+"-"+Прав(СтрОбъект,2);
Если ПустоеЗначение(Время)=1 Тогда
Время="00:00:00"+".000Z";
Иначе
Если Время="23:59:59" Тогда
Время=Время+".999Z";
Иначе
Время=Время+".000Z";
КонецЕсли;
КонецЕсли;
СтрОбъект=СтрОбъект+"T"+Время;
СтрокаJSON=СтрокаJSON+""""+СтрОбъект+"""";
КонецЕсли;
Возврат СтрокаJSON;
КонецФункции // ОбъектВТекстJSON
Показать//*********************************************************************************
// RFC 8259 The JavaScript Object Notation (JSON) Data Interchange Format
// в базе есть обработка JSON_Туда_И_Обратно
// в Install есть обработка КОП_JSON.ert там всё
// есть обработка
// здесь используется
//
// Функция JSON(Объект, Детализация=0) Экспорт
Функция ОбъектВТекстJSON_(Объект,Детализация=0) Экспорт
Тип = ТипЗначенияСтр(Объект);
Если Тип = "Справочник" Тогда
Результат = СоздатьОбъект("Текст");
Вид = Объект.Вид();
Идентификатор = Метаданные.Справочник(Вид).Идентификатор;
ПолныйИдентификатор = Метаданные.Справочник(Вид).ПолныйИдентификатор();
Результат.ДобавитьСтроку("{");
Результат.ДобавитьСтроку(""""+ПолныйИдентификатор+""""+": {");
Код = Объект.Код;
Результат.ДобавитьСтроку("""Код"": "+""""+Код+""",");
Наименование = Объект.Наименование;
Результат.ДобавитьСтроку("""Наименование"": "+""""+Наименование+"""");
Если Детализация>=1 Тогда
Результат.ДобавитьСтроку(",");
КоличествоРеквизитов = Метаданные.Справочник(Вид).Реквизит();
Для НомерРеквизита=1 По КоличествоРеквизитов Цикл
Реквизит = Метаданные.Справочник(Вид).Реквизит(НомерРеквизита);
РеквизитИдентификатор = Реквизит.Идентификатор;
Результат.ДобавитьСтроку(""""+РеквизитИдентификатор+""""+": ");
РеквизитЗначение = Объект.ПолучитьАтрибут(РеквизитИдентификатор);
лТекстРеквизит = ОбъектВТекстJSON(РеквизитЗначение, Детализация-1);
КоличествоСтрокРеквизит = лТекстРеквизит.КоличествоСтрок();
Для НомерСтрокиРеквизит=1 По КоличествоСтрокРеквизит Цикл
Результат.ДобавитьСтроку(лТекстРеквизит.ПолучитьСтроку(НомерСтрокиРеквизит));
КонецЦикла;
Если НомерРеквизита<КоличествоРеквизитов Тогда
Результат.ДобавитьСтроку(",");
Иначе
КонецЕсли;
КонецЦикла;
КонецЕсли;
Результат.ДобавитьСтроку("}");
Результат.ДобавитьСтроку("}");
Возврат Результат;
ИначеЕсли (Тип = "Документ") Тогда
// еще не наваяно
ИначеЕсли (Тип = "ТаблицаЗначений") ИЛИ (Тип = "СписокЗначений") Тогда
// еще не наваяно
ИначеЕсли Тип = "Строка" Тогда
Если Объект = "true" Тогда
_Рез="true";
ИначеЕсли Объект = "false" Тогда
_Рез="false";
ИначеЕсли Объект = "null" Тогда
_Рез="null";
Иначе
_Рез = СокрЛП(Объект);
_Рез = СтрЗаменить(_Рез, "\", "\\");
_Рез = СтрЗаменить(_Рез, "/", "\/");
_Рез = СтрЗаменить(_Рез, """", "\""");
_Рез = СтрЗаменить(_Рез, Симв(8), "\b"); // Символ Backspace
_Рез = СтрЗаменить(_Рез, Симв(9), "\t"); // СимволТабуляции
_Рез = СтрЗаменить(_Рез, Симв(10), "\n"); // перевод строки
_Рез = СтрЗаменить(_Рез, Симв(12), "\f"); // перевод страницы
_Рез = СтрЗаменить(_Рез, Симв(13), "\r"); // возврат каретки
_Рез = """" + _Рез + """";
Возврат _Рез;
КонецЕсли;
ИначеЕсли Тип = "Число" Тогда
//Результат = СоздатьОбъект("Текст");
//Результат.ДобавитьСтроку(Объект);
//Возврат Результат;
Возврат Строка(Объект);
ИначеЕсли Тип = "Дата" Тогда
//Результат = СоздатьОбъект("Текст");
Если ПустоеЗначение(Детализация)=1 Тогда
_Время="00:00:00"+".000Z";
Иначе
Если Детализация="23:59:59" Тогда
_Время=Детализация+".999Z";
Иначе
_Время=Детализация+".000Z";
КонецЕсли;
КонецЕсли;
_Рез=ОбъектВТекстJSON(Формат(Объект,"ДГГГГ-ММ-ДД")+"T"+_Время);
//Результат.ДобавитьСтроку();
Возврат _Рез;
Иначе
//Результат = СоздатьОбъект("Текст");
//Результат.ДобавитьСтроку(ОбъектВТекстJSON(Строка(Объект)));
//Возврат Результат;
Возврат Строка(Объект);
КонецЕсли;
КонецФункции // ОбъектВТекстJSON Показать//******************************************************************************
Функция РасшифроватьТокенJWT(Токен) Экспорт
ТокенJWT=СоздатьОбъект("ТаблицаЗначений");
//ТокенJWT.НоваяКолонка("user_status"); // текущий статус пользователя в системе ИС МП
//ТокенJWT.НоваяКолонка("inn"); // ИНН
//ТокенJWT.НоваяКолонка("id"); // Регистрационный номер участника в ИС МП
//ТокенJWT.НоваяКолонка("exp"); // Время окончания срока действия, формат Unix time (number)
//ТокенJWT.НоваяКолонка("organisation_status"); // Статус регистрации участника в ИС МП
//ТокенJWT.НоваяКолонка("client_id"); // Служебный атрибут ИС МП
//ТокенJWT.НоваяКолонка("jti"); // Надеюсь, что это clientToken
ТокенJWT.НоваяСтрока();
ЧастиТокена = СтрЗаменить(Токен,".",РазделительСтрок);
Если СтрКоличествоСтрок(ЧастиТокена) <> 3 Тогда
Сообщить("Токен не соответствует формату JWT");
Возврат 0;
КонецЕсли;
ДанныеТокена = base64_decode(СтрПолучитьСтроку(ЧастиТокена,2));
спРезультатРазбора=ТекстJSONВОбъект(ДанныеТокена);
Для iii=1 По спРезультатРазбора.РазмерСписка() Цикл
ПараметрJWT="";
ЗначениеJWT=спРезультатРазбора.ПолучитьЗначение(iii,ПараметрJWT);
ТокенJWT.НоваяКолонка(ПараметрJWT);
ТокенJWT.УстановитьЗначение(1,ПараметрJWT,ЗначениеJWT);
Если флОтладка=1 Тогда
Сообщить("ТокенJWT "+ПараметрJWT+": "+Преобразовать_из_UTF8(ЗначениеJWT));
КонецЕсли;
КонецЦикла;
Если флОтладка=1 Тогда
//ыыы=1;ТокенJWT.ВыбратьСтроку(iii); // вывод результата разбора
КонецЕсли;
Возврат ТокенJWT;
КонецФункции // РасшифроватьТокенJWT Показатьэто своего рода "костыль", но работает
Функция ПодписатьТекст(Знач ТекстДляПодписи,ОтпечатокСертификата,ОткрепленнаяПодпись=1,ВКодировкеBase64=1)
ПапкаДляПодписываемыхФайлов=КаталогПользователя();
РезультатПодписания="";
// Сначала сохраним ТекстДляПодписи
ФайлДляПодписи=ПапкаДляПодписываемыхФайлов+"TextForSigning.txt";
Текст=СоздатьОбъект("Текст");
Текст.ДобавитьСтроку(ТекстДляПодписи);
Текст.Записать(ФайлДляПодписи);
ФайлГотовойПодписи=ПапкаДляПодписываемыхФайлов+"SigningResul t.txt";
Если ФС.СуществуетФайл(ФайлГотовойПодписи)=1 Тогда
ФС.УдалитьФайл(ФайлГотовойПодписи);
КонецЕсли;
// Определим параметры запуска
ПутьCryptCP="C:\Program Files\Crypto Pro\CSP";
WshShell=СоздатьОбъект("WScript.Shell");
СтрокаЗапускаCryptCP="CryptCP.x64.exe -sign -addchain"+?(ОткрепленнаяПодпись=1," -detached","")+?(ВКодировкеBase64=1,"","-der")+" -thumbprint "+ОтпечатокСертификата+" """+ФайлДляПодписи+""" """+ФайлГотовойПодписи+"""";
WshShell_CurrentDirectory=WshShell.CurrentDirectory; // Сохраним путь текущего каталога
WshShell.CurrentDirectory=ПутьCryptCP; // Установим текущий каталог ПутьCryptCP
WshShell.Run(СтрокаЗапускаCryptCP,0,1); // Выполним скрипт подписания
WshShell.CurrentDirectory=WshShell_CurrentDirectory; // Установим текущий каталог на первоначальный
Если ФС.СуществуетФайл(ФайлГотовойПодписи)=1 Тогда
Текст.Открыть(ФайлГотовойПодписи);
Для iii=1 По Текст.КоличествоСтрок() Цикл
РезультатПодписания=РезультатПодписания+СокрЛП(Текст.ПолучитьСтроку(iii));
КонецЦикла;
РезультатПодписания=СокрЛП(РезультатПодписания);
КонецЕсли;
Если ПустоеЗначение(РезультатПодписания)=1 Тогда
Сообщить("Ошибка в процедуре ПодписатьТекстCryptCP при подписании текста");
КонецЕсли;
Возврат РезультатПодписания; // Подпись в формате Base64
КонецФункции // ПодписатьТекстCryptCP
ПоказатьВы случайно с csptest не пробовали делать? Есть ощущение что выходной файл не содержит исходного вложения файла, по крайней мере то что получаю через cades плагин, и csptest отличается. На машине стоит csp4, и пока обновлять не планируют.
csptest -sfsign -sign -in C:\motp\tosign.txt -out C:\motp\signed.txt -my "thumbprint" -detached -base64 –addМы новички в этой сфере. Можете посоветовать у кого можно получить "платную консультацию" по работе с этим API?
Возможно с Вами можем пообщаться.
Будем благодарны за любую помощь.
Спасибо!
Вероника
На сайте ЧЗ в разделе Табак в разделе Коды маркировки есть столбик Товар. Я бы экспортировал в Эксельку, но там постранично, а как пропарсить я не знаю.
UUID не найден в хранилище ключей. UUID = ". В чем может быть проблема?
и этот токен будет действовать только 10часов или до окончания сертификата?
PowerShell |
|---|
$baseURI = "https://ismotp.crptech.ru/api/v3/true-api"
#$baseURI = "https://int01.gismt.crpt.tech/api/v3/true-api"
function Sign-Content($signString){
# тут была первая проблема, в utf приходило "подпись не действительна"
$signString | Out-File -Encoding ascii C:\motp\tosign.txt -NoNewline
# cryptcp качаем с сайта crypto-pro
$rescmd = cmd /c """C:\Program Files\Crypto Pro\CSP\CryptCP.x64.exe"" -sign -addchain -thumbprint #### c:\motp\tosign.txt c:\motp\signed.txt"
# -Raw чтобы целиком прочитал и можно было замену сделать
$res = Get-Content "c:\motp\signed.txt" -Raw
$res = $res -replace "\s//.*`r`n" -replace "`r`n" -replace "`t" -replace "`n"
return $res;
};
function get-crpt_auth_token(){
$crpt_request = $baseURI + "/auth/key"
Write-Host $crpt_request
# в какой-то момент без этого перестало подключаться
[net.servicepointmanager]::securityprotocol = 'ssl3,tls,tls11,tls12'
$crpt_key = Invoke-WebRequest -Uri $crpt_request -Headers @{"Content-Type" = "application/json; charset=utf-8" }
if ($crpt_key.StatusCode -ne 200){
Write-Error "/auth/key status code not 200", $crpt_key.StatusCode
return $false;
}
Write-Host $crpt_key.Content
$res = ConvertFrom-Json $([String]::new($crpt_key.Content));
# sign data
$toSign = $res.data
$signeddata = Sign-Content -signString $toSign;
$jsonBody = ConvertTo-Json @{"uuid" = $res.uuid; "data" = $signeddata}
$simplesignin = $baseURI + "/auth/simpleSignIn"
Write-Host $simplesignin
try{
#тут была вторая проблема, нужно было правильно собрать jsonBody
$res = Invoke-RestMethod -Uri $simplesignin `
-Method Post `
-Headers @{'Content-Type' = 'application/json; charset=utf-8';} `
-Body $jsonBody
} catch{
Write-Host $_;
return $false;
};
return $res.token;
}
function Main(){
$res = get-crpt_auth_token;
if (!$res){
return $false;
}
$res | Out-File -Encoding ascii C:\motp\token.txt
}
Main;
Показать |
Вы можете заказать платную консультацию или разработку у автора. Будет создан приватный заказ на «Бирже заказов» для автора.
№ 1236219
Создание 15.05.20 14:37
Обновление 04.09.20 07:31
Просмотры 64928
Загрузки 54
Рейтинг
24
Комментарии 69
Код открыт Да
Рубрики Обмен с ГосИС
Кому Разработчик
Тип файла Внешняя обработка (ert,epf)
Платформа 1С:Предприятие 8
Конфигурация 1C:Бухгалтерия
Операционная система Не имеет значения
Страна Россия
Отрасль Розничная и сетевая торговля (FMCG)
Налоги Не имеет значения
Вид учета Не имеет значения
Доступ к файлу Абонемент ($m)