Попросили поделиться своим кодом для получения и разбора данных из 1С:Контрагент по их новому rest интерфейсу. Ничего сложного там нет, для разбора json использован и немного переработан код из Парсер JSON для платформы 7.7
Для работы нужен 1с++
Основная функция - глПолучитьРеквизитыКонтрагентаПоИНН(ИНН), ИНН нужно передавать уже "очищенный" от КПП.
Результат - Структура с данными, по коду, думаю, разберётесь какие свойства заполняются.
В моей конфигурации в справочнике "Контрагенты" есть реквизиты "Страна" и "Город", "Страна" - это обычный "ОКСМ", "Город" - это по сути аналог справочника "Регионы" в каких то типовых, у вас может ничего этого не быть
Ах да, ещё, я не смогла найти список кодов статуса, которые выдаёт сервис, поэтому добавила в конфигурацию справочник, куда добавляю коды статуса, которые являются допустимыми для добавления контрагента, на сегодняшний день я смогла "вычислить" три таких: 001,112,132
17.06.2022
В процессе работы потребовалось вернуться к заполнению адреса контрагента по правилам МНС, и я наткнулась на проблему: данные о корпусах и квартирах в json это массивы.
А т.к. я переделала оригинальный код разбора json - вместо списка значений получаю структуру. Оказалось что структура из 1cpp не работает с ключами в виде цифр. Можно было бы извернуться, добавив к индексу в массиве какой-нибудь буквенный префикс, но я решила поступить по другому - заполнять значение структуры вектором из того же 1cpp
Заодно и немного подшаманила типовой код обработки "ВводАдреса", чтобы заполнялось поле КодСтраны с строке адреса
Процедура ПредставитьАдресВФорматеМНС(Адрес)
АдресСписком = глРазложить(Адрес);
Попытка
КодСтраны = АдресСписком.ПолучитьЗначение(1);
//<--Вставка кода страны по умолчанию
Если (ПустоеЗначение(КодСтраны) = 1) или (Врег(КодСтраны) = "РОССИЯ") или (Врег(КодСтраны) = "РФ") Тогда
КодСтраны = "643";
КонецЕсли;
//->
Индекс = АдресСписком.ПолучитьЗначение(2);
Для Номер = 1 По 5 Цикл
УстановитьЗначенияОбъекта(ВидПоНомеру(Номер), "", АдресСписком.ПолучитьЗначение(Номер + 2));
КонецЦикла;
Дом = глНомерИзАдреснойСтроки(Адрес, 8);
Корпус = глНомерИзАдреснойСтроки(Адрес, 9);
Квартира = глНомерИзАдреснойСтроки(Адрес, 10);
ТипДома = глТипИзАдреснойСтроки(АдресСписком.ПолучитьЗначение(8), "ТипыДомов");
ТипКорпуса = глТипИзАдреснойСтроки(АдресСписком.ПолучитьЗначение(9), "ТипыКорпусов");
ТипКвартиры = глТипИзАдреснойСтроки(АдресСписком.ПолучитьЗначение(10), "ТипыКвартир");
Исключение
КонецПопытки;
КонецПроцедуры // ПредставитьАдресВФорматеМНС()
Код в публикации исправлен
Функция НайтиГородПоНаименованию(НаимГорода)
НаимГорода = глПреобразоватьРегистр(НаимГорода);
спрГорода = СоздатьОбъект("Справочник.Города");
Если спрГорода.НайтиПоНаименованию(наимГорода, 0, 1) = 1 Тогда
Возврат спрГорода.ТекущийЭлемент();
КонецЕсли;
Возврат "";
КонецФункции
Функция НайтиСтрануПоКоду(КодСтраны)
спрСтраны = СоздатьОбъект("Справочник.ОКСМ");
Если спрСтраны.НайтиПоКоду(КодСтраны, 0) = 1 Тогда
Возврат спрСтраны.ТекущийЭлемент();
КонецЕсли;
Возврат "";
КонецФункции
Функция jsonВСтруктуру(obj)
scriptCtrl = СоздатьОбъект("MSScriptControl.ScriptControl");
scriptCtrl.Language="jscript";
код = "
|
| // Получить элемент массива
| function aGet(Array, index) {
| return(Array[index]);
| }
|
| // Получить ключ пары по индексу
| function oKey(Obj, index) {
| var size = 0, key;
| for (key in Obj) {
| if (size == index) break;
| if (Obj.hasOwnProperty(key)) size++;
| }
| return(key);
| }
|
| // Получить значение пары по ключу
| function oValueByKey(Obj, key) {
| return(Obj[key]);
| }
|
| //Получить количество пар в объекте
| Object.size = function(obj) {
| var size = 0, key;
| for (key in obj) {
| if (obj.hasOwnProperty(key)) size++;
| }
| return(size);
| }
|
| //Получить размер объекта (количество пар в нём)
| function oSize(Obj) {
| return(Object.size(Obj));
| }
|
| // Получить тип объекта (number, string, object, array)
| function eType(Element) {
| if (Element instanceof Array) {
| return(""array"");
| } else if (Object.prototype.toString.call(Element) === '[object Array]') {
| return(""array"");
| } else {
| return(typeof(Element));
| }
| }
|";
scriptCtrl.AddCode(код);
РезультатРазбора = СоздатьОбъект("Структура");
ТипОбъекта = scriptCtrl.run("eType", obj);
Если ТипОбъекта = "object" Тогда
Для н=0 По scriptCtrl.run("oSize", obj)-1 Цикл
Ключ = scriptCtrl.run("oKey", obj, н);
Значение = scriptCtrl.run("oValueByKey", obj, Ключ);
ТипЗнач = scriptCtrl.run("eType", Значение);
//Сообщить(Ключ + " = " + Значение + " ("+ ТипЗнач +")");
Если Найти("number, string", ТипЗнач) > 0 Тогда
РезультатРазбора.Вставить(Ключ, Значение);
ИначеЕсли Найти("object, array", ТипЗнач) > 0 Тогда
РезультатРазбора.Вставить(Ключ, jsonВСтруктуру(Значение));
КонецЕсли;
КонецЦикла;
ИначеЕсли ТипОбъекта = "array" Тогда
МассивЗначений = СоздатьОбъект("Вектор");
Для н = 0 По obj.length - 1 Цикл
Значение = scriptCtrl.run("aGet", obj, н);
ТипЗнач = scriptCtrl.run("eType", Значение);
Если Найти("number, string", ТипЗнач) > 0 Тогда
МассивЗначений.Добавить(Значение);
ИначеЕсли Найти("object, array", ТипЗнач) > 0 Тогда
МассивЗначений.Добавить(jsonВСтруктуру(Значение));
КонецЕсли;
КонецЦикла;
Возврат МассивЗначений;
КонецЕсли;
Возврат РезультатРазбора;
КонецФункции //jsonВСписок(obj)
Функция глРазборJSON(Знач Стр) Экспорт //На входе строка в текущей системной кодировке
scriptCtrl = СоздатьОбъект("MSScriptControl.ScriptControl");
scriptCtrl.Language="jscript";
Рез = scriptCtrl.Eval("("+СтрЗаменить(стр, РазделительСтрок,"")+");");
РезультатРазбора = jsonВСтруктуру(Рез);
Возврат РезультатРазбора;
КонецФункции //глРазборJSON(Знач Стр)
Функция МассивВСтроку(МассивЗначений)
СтрокаИзМассива = "";
Для Н = 0 По МассивЗначений.Количество() - 1 Цикл
Структура = МассивЗначений.Получить(Н);
Номер = СтрЗаменить(Структура.number, ",", ";");
СтрокаИзМассива = СтрокаИзМассива + Структура.type + " " + Номер + " ";
КонецЦикла;
Возврат СтрокаИзМассива;
КонецФункции
Функция глПолучитьРеквизитыКонтрагентаПоИНН(ИНН) Экспорт
РеквизитыКонтрагента = СоздатьОбъект("Структура");
РеквизитыКонтрагента.Вставить("КодСтатус", 0);
РеквизитыКонтрагента.Вставить("ЗапретитьОтгрузку", 0);
спрКодСтатусаКонтрагента = СоздатьОбъект("Справочник.КодыСтатусаКонтрагента");
Если СтрДлина(СокрЛП(ИНН)) = 10 Тогда
Ресурс = "/rest/corporation/v1/find-corporation-by-inn";
Иначе
Ресурс = "/rest/person/v1/find-person-by-inn"
КонецЕсли;
Параметр = "?inn=" + ИНН;
Запрос = СоздатьОбъект("WinHttp.WinHttpRequest.5.1");
Запрос.Open("GET", "https://api.orgregister.1c.ru" + Ресурс + Параметр, 0);
Запрос.SetCredentials(СокрЛП(Константа.ЛогинИТС), СокрЛП(Константа.ПарольИТС), 0);
Запрос.Send("");
Если Запрос.Status = 200 Тогда
РезультатРазбора = глРазборJSON(Запрос.ResponseText);
Если РезультатРазбора.Количество() = 1 Тогда
Предупреждение("Контагента с ИНН = " + ИНН + " не существует!");
РеквизитыКонтрагента.ЗапретитьОтгрузку = 1;
Возврат РеквизитыКонтрагента;
КонецЕсли;
Если СтрДлина(СокрЛП(ИНН)) <= 10 Тогда
Наименование = РезультатРазбора.name;
РеквизитыКонтрагента.Вставить("Наименование", Наименование.commonName);
РеквизитыКонтрагента.Вставить("ПолнНаименование", Наименование.fullName);
Статус = РезультатРазбора.status;
РеквизитыКонтрагента.Вставить("КодСтатус", Статус.code);
Если спрКодСтатусаКонтрагента.НайтиПоКоду(РеквизитыКонтрагента.КодСтатус) = 0 Тогда
РеквизитыКонтрагента.ЗапретитьОтгрузку = 1;
Предупреждение("Контрагент в статусе " + Статус.name);
Возврат РеквизитыКонтрагента;
КонецЕсли;
РеквизитыКонтрагента.Вставить("ОГРН", РезультатРазбора.ogrn);
КПП = РезультатРазбора.kpp;
РеквизитыКонтрагента.Вставить("КПП", КПП.value);
Если РезультатРазбора.Свойство("headPersonInfo") = 1 Тогда
Руководители = РезультатРазбора.headPersonInfo;
Директор = Руководители.director;
Контакт = СоздатьОбъект("Структура");
Контакт.Вставить("Должность", Директор.position);
Контакт.Вставить("ФИО", Директор.lastName + " " + Директор.name + " " + Директор.patronymic);
РеквизитыКонтрагента.Вставить("Контакт", Контакт);
КонецЕсли;
//{Юридический адрес
Адрес = РезультатРазбора.address;
Страна = Адрес.country;
КодСтраны = Адрес.countryCode;
спрСтрана = НайтиСтрануПоКоду(КодСтраны);
Если ПустоеЗначение(спрСтрана) = 0 Тогда
РеквизитыКонтрагента.Вставить("Страна", спрСтрана);
КонецЕсли;
Если Адрес.Свойство("city") = 1 Тогда
Город = Адрес.city;
Иначе
Город = Адрес.area;
КонецЕсли;
спрГород = НайтиГородПоНаименованию(Город);
Если ПустоеЗначение(спрГород) = 0 Тогда
РеквизитыКонтрагента.Вставить("Город", спрГород);
КонецЕсли;
АдресСтрока = Адрес.countryCode
+ "," + Адрес.postalCode
+ "," + ?(Адрес.Свойство("area") = 1, Адрес.area + ?(Адрес.Свойство("areaType") = 1, " " + Адрес.areaType, ""), "")
+ "," + ?(Адрес.Свойство("city") = 1, Адрес.city + " " + Адрес.cityType, "")
+ "," + ?(Адрес.Свойство("district") = 1, Адрес.district + " " + Адрес.districtType,
?(Адрес.Свойство("munDistrict") = 1, Адрес.mundistrictType + " " + Адрес.mundistrict, ""))
+ "," + ?(Адрес.Свойство("locality") = 1, Адрес.locality + " " + Адрес.localityType, "")
+ "," + ?(Адрес.Свойство("street") = 1, Адрес.street + " " + Адрес.streetType, "")
+ "," + ?(Адрес.Свойство("house") = 1, Адрес.houseType + " " + Адрес.house, "")
+ "," + ?(Адрес.Свойство("buildings") = 1, МассивВСтроку(Адрес.buildings), "")
+ "," + ?(Адрес.Свойство("apartments") = 1, МассивВСтроку(Адрес.apartments), "");
РеквизитыКонтрагента.Вставить("ЮридическийАдрес", АдресСтрока);
//}
Иначе
СвФЛ = РезультатРазбора.person;
РеквизитыКонтрагента.Вставить("Наименование", СвФЛ.lastName + " " + Лев(СвФЛ.name, 1) + ". " + Лев(СвФЛ.patronymic, 1) + ". ИП");
РеквизитыКонтрагента.Вставить("ПолнНаименование", "ИП " + СвФЛ.fio);
РеквизитыКонтрагента.Вставить("Пол", СвФЛ.gender);
Информация = РезультатРазбора.registrationInfo;
Статус = Информация.status;
РеквизитыКонтрагента.Вставить("КодСтатус", Статус.code);
Если спрКодСтатусаКонтрагента.НайтиПоКоду(РеквизитыКонтрагента.КодСтатус) = 0 Тогда
РеквизитыКонтрагента.ЗапретитьОтгрузку = 1;
Предупреждение("Контрагент в статусе " + Статус.name);
Возврат РеквизитыКонтрагента;
КонецЕсли;
Гражданство = РезультатРазбора.citizenship;
Страна = Гражданство.countryName;
КодСтраны = Гражданство.countryCode;
спрСтрана = НайтиСтрануПоКоду(КодСтраны);
Если ПустоеЗначение(спрСтрана) = 0 Тогда
РеквизитыКонтрагента.Вставить("Страна", спрСтрана);
КонецЕсли;
КонецЕсли;
Иначе
Предупреждение("Не удалось связазться с сервером: " + Запрос.statusText);
КонецЕсли;
Возврат РеквизитыКонтрагента;
КонецФункции