Вступление
Целью статьи является рассказать о том, как организовать передачу через web-сервис XML-данных в формате универсального обмена данными в информационную базу на платформе 1С:Предприятие 8.1 и старше. А также как получить из базы xml-данные. Cтатья может быть полезна для знакомства с web-сервисами. Если уже знакомы с ними, то, думаю, можете почерпнуть для себя новые полезные приемы.
Универсальный обмен данными XML, он же "1С:Конвертация данных" – это технология обмена данными между различными конфигурациями на платформе 1С.
С помощью этой технологии организованы все "типовые" обмены (УТ Бухгалтерия, УТ Розница, ЗУП Бухгалтерия и т.д.). А также можно организовать свои собственные сценарии обмена с нуля между любыми конфигурациями на платформах 1С (начиная с 7.7). Обучение технологии «1С:Конвертации данных» не является целью данной статьи. Подразумевается, что вы с ней знакомы или познакомитесь из других источников, их предостаточно. Могу порекомендовать материалы на диске ИТС. Или, может быть, вам вообще не нужно с ней знакомиться, а просто автоматизировать саму передачу данных.
Попутно попробую рассказать немного теории. Чтобы «подружить» с web-сервисами тех, кто мало с ними знаком.
Технология «Конвертации данных» предлагает два способа передачи данных: через файлы – в одной базе выгрузили, в другой загрузили, либо через COM-соединение. Оба способа имеют свои недостатки. Для меня, я бы сказал, фатальные. А если серьезно, просто таят в себе существенные неудобства. Расписывать недостатки и убеждать не буду – это отдельная тема. Коротко перечислю достоинства web-сервисов, важные для меня:
- Возможность организовать онлайн-обмен;
- Возможность организовать удаленный онлайн-обмен, т.е. через Интернет;
- База-приемник и база-источник могут работать на разных релизах и даже версиях платформы (COM-соединение в таких ситуациях использовать проблематично, почти невозможно);
- Очень быстрая установка соединения и очень быстрая передача данных. Правда, «холодный» запуск по времени сравним с COM-соединением.
- Удобно для разработчика, возможность использовать одну и ту же технологию трансфера данных как для обменов 1С 1C, так и для обменов 1С Другие системы.
Вообще, я «фанат» web-сервисов. Мог бы ещё много рассказать об их отладке, обмене с «чужеродными» средами, в том числе такими проблемными, как PHP (в виду вольного обращения данной платформы со стандартами SOA). Но это темы для отдельных статей.
Инфраструктура
Вопросы установка и настройка web-сервера, публикации web-сервисов не рассматриваются в данной статье. Подразумевается, что это вы делать умеете или готовы разобраться, или у вас просто есть готовая инфраструктура. Могу порекомендовать документацию к 1С:Предприятию и «погуглить» в Интернете (именно «и», а не «или»).
Реализация. Серверная сторона.
Сервер – это для нас информационная база, которая принимает и отдает данные. Всё делаем на платформе 1С:Предприятие 8.2 (прикладное решение не важно).
Web-сервис
Добавляем web-сервис. Назовем «ОбменДаннымиXML». Свойства следующие:
Ключевым свойством для нас является Пакеты XDTO. Выбранный пакет «http://v8.1c.ru/8.1/data/core» представляет встроенные типы 1С:Предприятия, общие для любых конфигураций, такие как ХранилищеЗначения, Структура, Массив и т.п. Пускай вас не смущает число 8.1 в имени пакета. Имеется в виду, что эти типы есть в платформах 8.1 и выше, и их XML-представление не менялось с платформы 8.1.
URI пространства имен в данном случае совершенно не важен, можно указать любую строку. Их принято строить на базе URL, которые использует ваша организация, чтобы гарантировать глобальную уникальность имен типов, описанных в ваших пакетах, на всякий случай. Но мы описывать свои типы (это делается при помощи пакетов XDTOв соответствующей ветке дерева конфигурации) не будем, так как нам достаточно встроенных типов 1C:Предприятия.
Имя файла публикации может быть любым, но с соблюдением требований к URL. Кириллицу лучше не использовать. Расширение «1cws» тоже лучше не менять (не пробовал, если честно).
Операции
Добавляем операции web-сервиса. Наш web-сервис должен уметь как принимать данные, записывая в свою ИБ, так и отдавать их (выгружать в XML). Поэтому добавляем две операции, "ПринятьДанные" и "ОтдатьДанные".
Операция ПринятьДанные
"ПринятьДанные" записывает в ИБ xml-данные, переданные в первом параметре "Данные". Тип параметра - Хранилище значения. ХранилищеЗначения выбираем, чтобы сжимать данные при передаче, т.к. файлы XML могут быть очень увесистыми и при этом хорошо "жмутся". Но можно было бы использовать и просто Строку, string(http://www.w3.org/2001/XMLSchema).
Операция возвращает целое число – количество успешно записанных объектов.
Второй параметр - ТекстОшибки, строка, входной-выходной, для возврата текста ошибки.
Понятно, что ValueStorage– это ХранилищеЗначения
Код метода:
Функция ПринятьДанные(Данные, ТекстОшибки)
УстановитьПривилегированныйРежим(Истина); ОбработкаОбмена = Обработки.УниверсальныйОбменДаннымиXML.Создать(); ОбработкаОбмена.РежимОбмена = "Загрузка"; РаботаВозможна = ОбработкаОбмена.ВыполнитьДействияПередЧтениемДанных(Данные.Получить()); Если НЕ РаботаВозможна Тогда Возврат 0; КонецЕсли; ОбработкаОбмена.ПроизвестиЧтениеДанных(ТекстОшибки); ОбработкаОбмена.ВыполнитьДействияПослеЗавершенияЧтенияДанных(); Возврат ОбработкаОбмена.мСчетчикЗагруженныхОбъектов; КонецФункции
Операция ОтдатьДанные
"ОтдатьДанные" возвращает xml-данные, выгруженные по переданным правилам обмена. Также в виде ХранилищаЗначения.
Это тоже обертка над Универсальным обменом, только уже более функциональная. Обратите внимание , что Массив и Структура – это уже не простые типы, они попадают в метод в виде XDTO-объектов, и их нужно явно преобразовывать в/из типы 1С:Предприятия. Преобразовывать в/из XDTO нужно и на клиентской стороне.
ПравилаВыгрузки - это массив имен правил выгрузки, по которым следует произвести выборку данных.
ЗначенияПараметров – это структура со значениями параметров конвертации.
Код:
Функция ОтдатьДанные(ПравилаОбмена, ПравилаВыгрузкиXDTO, ЗначенияПараметровXDTO) УстановитьПривилегированныйРежим(Истина); // Иницализация Обмен = Обработки.УниверсальныйОбменДаннымиXML.Создать(); Обмен.РежимОбмена = "Выгрузка"; ИмяВремФайла = ПолучитьИмяВременногоФайла("xml"); Обмен.ИмяФайлаОбмена = ИмяВремФайла; // Загрузка правил ИмяФайлаПравилОбмена = ПолучитьИмяВременногоФайла("xml"); ЗаписьТекста = Новый ЗаписьТекста(ИмяФайлаПравилОбмена); ЗаписьТекста.Записать(ПравилаОбмена.Получить()); ЗаписьТекста.Закрыть(); Обмен.ИмяФайлаПравилОбмена = ИмяФайлаПравилОбмена; Обмен.ЗагрузитьПравилаОбмена(); // Параметры ЗначенияПараметров = СериализаторXDTO.ПрочитатьXDTO(ЗначенияПараметровXDTO); Если ЗначениеЗаполнено(ЗначенияПараметров) Тогда Для каждого КлючИЗнач Из ЗначенияПараметров Цикл Обмен.УстановитьЗначениеПараметраВТаблице(КлючИЗнач.Ключ, КлючИЗнач.Значение); КонецЦикла; КонецЕсли; // Правила выгрузки данных ПравилаВыгрузки = СериализаторXDTO.ПрочитатьXDTO(ПравилаВыгрузкиXDTO); Если ЗначениеЗаполнено(ПравилаВыгрузки) Тогда // Сначала снимаем все отметки Для Каждого Строка из Обмен.ТаблицаПравилВыгрузки.Строки Цикл Строка.Включить = 0; Обмен.УстановитьПометкиПодчиненных(Строка, "Включить"); КонецЦикла; // Теперь устанавливаем по переданным ПВД Для каждого ИмяПравилаВыгрузки Из ПравилаВыгрузки Цикл СтрДерева = Обмен.ТаблицаПравилВыгрузки.Строки.Найти(ИмяПравилаВыгрузки, "Имя", Истина); Если СтрДерева = Неопределено Тогда ВызватьИсключение "ОбменДаннымиXML.ОтдатьДанныеXML(): не удалось найти ПВД """ + ИмяПравилаВыгрузки + """!"; Иначе СтрДерева.Включить = 1; Обмен.УстановитьПометкиРодителей(СтрДерева, "Включить"); КонецЕсли; КонецЦикла; КонецЕсли; // Выгрузка Обмен.ВыполнитьВыгрузку(); // Конец ЧтениеТекста = Новый ЧтениеТекста; ЧтениеТекста.Открыть(ИмяВремФайла, КодировкаТекста.UTF8); Результат = ЧтениеТекста.Прочитать(); ЧтениеТекста.Закрыть(); УдалитьФайлы(ИмяВремФайла); УдалитьФайлы(ИмяФайлаПравилОбмена); ХранилищеДанных = Новый ХранилищеЗначения(Результат, Новый СжатиеДанных(9)); Возврат ХранилищеДанных; КонецФункции
Обработка УниверсальныйОбменДаннымиXML
Если в вашем прикладном решении такая обработка отсутствует, то её нужно добавить из комплекта поставки конфигурации «Конвертация данных» (файл V8Exchan82.epf).
Доступ к web-сервису. Роли и пользователи.
Для обращения к веб-сервисам необходимо подготовить роль и пользователя. Самый простой путь – это добавить отдельную роль, назовем ВебСервисы, этой роли не даем никаких прав, кроме прав на операции веб-сервиса, а сами методы выполняем в привилегированном режиме.
Добавляем пользователя
Назначаем ему только нашу роль ВебСервисы и больше никаких других. Этого достаточно.
На серверной стороне настройка закончена.
Клиент (обращение к web-сервису)
Тут просто приведу примеры обращения к веб-сервисам. Откуда берутся правила обмена , правила выгрузки, значения параметров и т.п. – это уже вопрос вашей прикладной задачи и её реализации.
Передача данных в базу-приемник
Пример передачи xml-данных в базу-приемник, на стороне которой работает вышеописанный web-сервис:
Функция ПередатьНаСервере(СтрокаXML) Данные = Новый ХранилищеЗначения(СтрокаXML, Новый СжатиеДанных(9)); // Подкдючение Определения = Новый WSОпределения("http://server1c8/db_buh/ws/xml-exchange.1cws?wsdl", "WebServices", "12345"); Прокси = Новый WSПрокси(Определения, "http://your-domain.ru/", "ОбменДаннымиXML", "ОбменДаннымиXMLSoap"); Прокси.Пользователь = "WebServices"; Прокси.Пароль = "12345"; // Передача ТекстОшибки = ""; ЗагруженоОбъектов = Прокси.ПринятьДанные(Данные, ТекстОшибки); Если НЕ ПустаяСтрока(ТекстОшибки) Тогда Сообщить(ТекстОшибки); КонецЕсли; Возврат ЗагруженоОбъектов; КонецФункции // ПередатьНСервере()
Данные перед этим получены из этой базы-источника функцией:
Функция ВыгрузитьКонтрагента(Организация, Контрагент) ПравилаОбмена = ПолучитьПравилаОбмена(); // Инициализация Обмен = Обработки.УниверсальныйОбменДаннымиXML.Создать(); Обмен.РежимОбмена = "Выгрузка"; ИмяФайлаДанных = ПолучитьИмяВременногоФайла("xml"); Обмен.ИмяФайлаОбмена = ИмяФайлаДанных; // Загрузка правил ИмяФайлаПравилОбмена = ПолучитьИмяВременногоФайла("xml"); ЗаписьТекста = Новый ЗаписьТекста(ИмяФайлаПравилОбмена); ЗаписьТекста.Записать(ПравилаОбмена); ЗаписьТекста.Закрыть(); Обмен.ИмяФайлаПравилОбмена = ИмяФайлаПравилОбмена; Обмен.ЗагрузитьПравилаОбмена(); // Параметры Обмен.УстановитьЗначениеПараметраВТаблице("Организация", Организация); // Правила выгрузки данных // Сначала все отключаем Для Каждого Строка из Обмен.ТаблицаПравилВыгрузки.Строки Цикл Строка.Включить = 0; Обмен.УстановитьПометкиПодчиненных(Строка, "Включить"); КонецЦикла; // Включаем нужное правило СтрПравил = Обмен.ТаблицаПравилВыгрузки.Строки.Найти("Контрагенты", "Имя", Истина); Если СтрПравил = Неопределено Тогда ВызватьИсключение "ПередатьНСервере(): не удалось найти правило выгрузки ""Контрагенты"" в правилах обмена."; КонецЕсли; СтрПравил.Включить = 1; Обмен.УстановитьПометкиРодителей(СтрПравил, "Включить"); // Отбор Постр = Новый ПостроительОтчета("ВЫБРАТЬ ПЕРВЫЕ 1 _.* ИЗ Справочник.Контрагенты КАК _ |{ГДЕ _.Ссылка.* КАК Справочник_Контрагенты}"); Постр.Отбор.Добавить("Справочник_Контрагенты").Установить(Контрагент); СтрПравил.ИспользоватьОтбор = Истина; СтрПравил.НастройкиПостроителя = Постр.ПолучитьНастройки(); // Выгрузка Обмен.ВыполнитьВыгрузку(); ЧтениеТекста = Новый ЧтениеТекста; ЧтениеТекста.Открыть(ИмяФайлаДанных, КодировкаТекста.UTF8); СтрокаXML = ЧтениеТекста.Прочитать(); ЧтениеТекста.Закрыть(); УдалитьФайлы(ИмяФайлаДанных); УдалитьФайлы(ИмяФайлаПравилОбмена); Возврат СтрокаXML; КонецФункции // ВыгрузитьКонтрагента()
Получение данных от web-сервиса
Пример получения данных от web-сервиса:
Функция ПолучитьДанныеОтВебСервиса(ПравилаСтрокой) // Подкдючение Определения = Новый WSОпределения("http://server1c8/db_buh/ws/xml-exchange.1cws?wsdl", "WebServices", "12345"); Прокси = Новый WSПрокси(Определения, "http://your-domain.ru/", "ОбменДаннымиXML", "ОбменДаннымиXMLSoap"); Прокси.Пользователь = "WebServices"; Прокси.Пароль = "12345"; // Параметры ПравилаВыгрузки = Новый Массив; ПравилаВыгрузки.Добавить("ИерархияКонтрагентов"); ПравилаВыгрузкиXDTO = СериализаторXDTO.ЗаписатьXDTO(ПравилаВыгрузки); ЗначенияПараметров = Новый Структура("КодБазыИсточника", "00001"); ЗначенияПараметровXDTO = СериализаторXDTO.ЗаписатьXDTO(ЗначенияПараметров); // Получение данных Правила = Новый ХранилищеЗначения(ПравилаСтрокой, Новый СжатиеДанных(9)); Данные = Прокси.ОтдатьДанные(Правила, ПравилаВыгрузкиXDTO, ЗначенияПараметровXDTO); // Возвращаем строку XML Возврат Данные.Получить(); КонецФункции // ПолучитьДанныеОтВебСервиса()
Конец
Спасибо за внимание