Почему метод ФабрикаXDTO.Тип() возвращает Неопределено при переносе заполнения по ИНН и как это исправить?

Программист 1С v8.3 (Обычные формы) 1C:Бухгалтерия Бухгалтерский учет IT и автоматизация бизнеса
← На главную

Перенос популярного и удобного функционала автозаполнения реквизитов контрагента по ИНН из современных конфигураций (например, Бухгалтерия предприятия 3.0) в более старые решения (такие как Бухгалтерия предприятия 2.0, Управление торговлей 10.3 или Комплексная автоматизация 1.1) — частая задача для разработчиков 1С. Однако в процессе адаптации кода программисты регулярно сталкиваются с ошибкой выполнения, когда метод ФабрикаXDTO.Тип() возвращает Неопределено при попытке инициализировать структуры контактной информации.

В этой статье мы подробно разберем, почему возникает данная проблема, рассмотрим технические особенности работы с фабрикой XDTO в платформе «1С:Предприятие», пошагово выполним процесс переноса необходимых объектов конфигурации и изучим альтернативные, более простые архитектурные варианты решения этой задачи.

Выясняем причину: почему ФабрикаXDTO.Тип() возвращает Неопределено?

Метод ФабрикаXDTO.Тип() предназначен для получения типа данных XDTO по его пространству имен (URI) и локальному имени. Если этот метод возвращает Неопределено, это означает, что платформа не смогла сопоставить переданные параметры ни с одним из известных ей типов. Рассмотрим основные технические нюансы, которые приводят к такому поведению:

  1. Отсутствие XDTO-пакета в метаданных конфигурации. Это самая частая и очевидная причина. Если вы перенесли общий модуль СервисДанныхЕдиныхГосРеестров, но забыли скопировать сам XDTO-пакет, в котором описаны типы адресов, глобальная фабрика конфигурации просто не будет знать о существовании таких типов, как АдресРФ.
  2. Различие между типами и свойствами в схемах (XSD). В XML-схемах объекты могут быть объявлены как типы данных (ComplexType/SimpleType) или как глобальные свойства (Element). Метод ФабрикаXDTO.Тип() работает исключительно с типами данных. Если разработчики сервиса объявили целевой объект как свойство, этот метод вернет пустой результат. В таком случае тип необходимо извлекать из самого свойства через пакет:
    
    ТипИзСвойства = ФабрикаXDTO.Пакеты.Получить(ПространствоИменКИ).Свойства.Получить("АдресРФ").Тип;
    
  3. Чувствительность к регистру и символам в URI. Платформа 1С крайне чувствительна к строковому представлению пространства имен. Малейшее несовпадение в написании URI (например, отсутствие или наличие закрывающего слэша "/" в конце строки, различие между протоколами "http" и "https") приведет к тому, что фабрика не найдет нужный тип. Строковое значение в переменной ПространствоИменКИ должно посимвольно совпадать с аналогичным свойством пакета в конфигураторе.
  4. Локальная фабрика WS-Прокси против Глобальной фабрики. Если обращение к веб-сервису выполняется динамически через создание объекта WSПрокси, его типы регистрируются во внутренней фабрике этого прокси-объекта, а не в глобальном объекте ФабрикаXDTO всей конфигурации. В таком случае обращаться к типам необходимо через прокси: ТипАдреса = МойПараметрПрокси.ФабрикаXDTO.Тип(ПространствоИменКИ, "АдресРФ");
  5. Проблемы кэширования метаданных на сервере. При динамическом обновлении конфигурации базы данных («демонском» обновлении) в многосерверных кластерах кэш некоторых рабочих процессов rphost может обновиться некорректно. На одном сервере вызов отработает штатно, а на другом — вернет ошибку. Для решения этой проблемы требуется полная очистка серверного кэша и перезапуск службы кластера.

Пошаговый перенос механизма автозаполнения по ИНН

Для того чтобы перенести функционал заполнения реквизитов из БП 3.0 в старую базу, нам потребуется аккуратно перенести ключевые объекты метаданных и связать их между собой. Проанализируем этот процесс по шагам:

Шаг 1. Перенос XDTO-пакета

Откроем конфигуратор базы-источника (БП 3.0) и базы-приемника (например, БП 2.0). Найдем в ветке Общие -> XDTO-пакеты пакет с именем КонтактнаяИнформация. Перетащим его методом Drag-and-Drop или скопируем через буфер обмена в нашу целевую конфигурацию. Убедимся, что его URI пространства имен точно соответствует используемому в коде (как правило, это http://www.v8.1c.ru/ssl/contactinfo).

Шаг 2. Перенос общих модулей

Нам потребуется скопировать модуль СервисДанныхЕдиныхГосРеестров. Обратите внимание, что этот модуль активно взаимодействует с подсистемой контактной информации БСП. Чтобы не переносить десятки связанных модулей БСП, мы можем точечно перенести или дописать несколько функций в модуль УправлениеКонтактнойИнформацией целевой конфигурации:

Шаг 3. Настройка авторизации и защита данных

Для получения данных от веб-сервиса 1С требуется авторизация под учетной записью Портала ИТС (у вас должна быть активна подписка на сервис «1С:Контрагент»). Данные авторизации (логин и пароль) обычно хранятся в константах или регистрах сведений (например, в регистре настроек интернет-поддержки). Нам необходимо убедиться, что эти данные корректно считываются в коде модуля СервисДанныхЕдиныхГосРеестров.

Важный совет по безопасности кода: при возникновении ошибок подключения (например, падение авторизации) платформа может вывести подробное описание исключения в Журнал регистрации, содержащее логин и пароль к ИТС в открытом виде! Рассмотрим, как можно обезопасить эти конфиденциальные данные с помощью простой функции маскирования в блоке перехвата исключений:


Попытка
    WSОпределения = Новый WSОпределения(АдресWSDL, ИмяПользователя, Пароль);
Исключение
    ОписаниеОшибки = ИнформацияОбОшибке().Описание;
    // Маскируем учетные данные, чтобы они не попали в журнал регистрации в открытом виде
    ОписаниеОшибки = СтрЗаменить(ОписаниеОшибки, ПараметрыАутентификации.login, "указан_логин");
    ОписаниеОшибки = СтрЗаменить(ОписаниеОшибки, ПараметрыАутентификации.password, "указан_пароль");
    
    ЗаписатьВЖурналРегистрации("ИнтеграцияСЕГРЮЛ", 
                               УровеньЖурналаРегистрации.Ошибка, 
                               , , 
                               "Ошибка инициализации веб-сервиса: " + ОписаниеОшибки);
    ВызватьИсключение "Не удалось подключиться к сервису авторизации. Проверьте настройки ИТС.";
КонецПопытки;

Альтернативные и более простые архитектурные решения

Перенос подсистем БСП «в лоб» часто превращается в кошмар из-за лавинообразного роста зависимостей: один переносимый модуль требует функции второго, второй — третьего, и в итоге вам приходится менять структуру метаданных всей конфигурации. Посмотрим на альтернативные варианты реализации этой задачи, которые помогут сэкономить время.

Вариант 1. Использование сторонних API (например, DaData.ru)

Если вам не принципиально использовать именно встроенный сервис «1С:Контрагент», отличным решением будет интеграция со сторонними сервисами стандартизации данных, такими как DaData.ru. Этот подход имеет ряд весомых преимуществ:

Вариант 2. Использование COM-соединения к базе БП 3.0

Рассмотрим очень красивое и простое решение, если на предприятии параллельно с вашей старой базой развернута и обновляется актуальная база Бухгалтерия предприятия 3.0. Вместо того чтобы дублировать сложный код парсинга XML и XDTO, мы можем использовать COM-соединение:

  1. На форме карточки контрагента в старой базе создаем кнопку «Заполнить по ИНН».
  2. При нажатии программно инициируем COM-соединение к рабочей базе БП 3.0.
  3. Передаем ИНН в экспортный метод БП 3.0, который выполняет штатный запрос к веб-сервису средствами своей конфигурации.
  4. Возвращаем результат обратно в виде простой плоской таблицы или структуры и заполняем реквизиты в нашей старой базе.

Проанализируем пример программной реализации такого COM-запроса:


&НаКлиенте
Процедура ЗаполнитьПоИННЧерезCOM(Команда)
    
    ИНН = Объект.ИНН;
    Если ПустаяСтрока(ИНН) Тогда
        ПоказатьПредупреждение(, "Пожалуйста, заполните ИНН контрагента!");
        Возврат;
    КонецЕсли;
    
    // Формируем строку подключения к базе БП 3.0
    СтрокаПодключения = "Srvr=""MyServer"";Ref=""Accounting_Production"";Usr=""COM_Exchange"";Pwd=""SuperPassword"";";
    
    Попытка
        COMСоединитель = Новый COMОбъект("V83.COMConnector");
        БазаБП3 = COMСоединитель.Connect(СтрокаПодключения);
    Исключение
        ВызватьИсключение "Не удалось установить связь с базой БП 3.0 для получения данных: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
    КонецПопытки;
    
    // Вызываем функцию автозаполнения на стороне БП 3.0 
    // Предполагается, что в БП 3.0 есть функция, возвращающая простую структуру данных
    ДанныеКонтрагента = БазаБП3.ОбщиеМодули.СервисДанныхЕдиныхГосРеестров.ПолучитьПлоскиеДанныеКонтрагента(ИНН);
    
    Если ДанныеКонтрагента = Неопределено Тогда
        ПоказатьПредупреждение(, "Контрагент с таким ИНН не найден в ЕГРЮЛ!");
        Возврат;
    КонецЕсли;
    
    // Заполняем реквизиты на форме нашей старой конфигурации
    Объект.НаименованиеПолное = ДанныеКонтрагента.НаименованиеПолное;
    Объект.КПП = ДанныеКонтрагента.КПП;
    Объект.ЮридическийАдрес = ДанныеКонтрагента.ЮридическийАдресТекст;
    
    ПоказатьОповещениеПользователя("Успешно", , "Реквизиты заполнены из базы БП 3.0");
    
КонецПроцедуры

Преимущество этого метода очевидно: при любых изменениях в структуре веб-сервисов со стороны фирмы «1С» вам не придется переписывать код в вашей старой доработанной базе. Достаточно будет просто своевременно обновлять базу-донор БП 3.0 до актуальных релизов.

Выводы

Мы выяснили, что ошибка получения типа XDTO чаще всего связана с отсутствием соответствующего пакета в конфигурации или неточным сопоставлением пространств имен. Мы рассмотрели варианты исправления этой ситуации как путем прямого переноса пакетов и доработки общих модулей, так и через создание обходных архитектурных решений, которые могут оказаться значительно более дешевыми в поддержке и внедрении.

← На главную