Полезной оказалась эта ссылка:
Но там было предложено решение использовать внешний прокси адаптер. Т.к. проблем с обратным вызовом веб-сервиса (из SAP вызывался веб-сервис 1с) не возникло, то решил, что вполне можно обойтись без внешнего прокси адаптера, только штатными средствами 1С.
Собственно все решение приводить не буду, приведу основные функции, которые в итоге получились.
Не знаю, как тут оформлять код, поэтому пока функции выложу так:
1. Сначала подготавливаем структуру 1С, которая по реквизитам аналогична структуре объекта XDTO: на верхнем уровне она должна содержать ИмяКлюча, соответствующее ИмениПараметра операции WS-сервиса. Значениями структуры могут быть: Значение / Массив / Структура, где в свою очередь Массив может содержать Значения / Структуры
Массив используется для передачи таблиц (Список XDTO)
2. Получаем объект Прокси фабрики XDTO
… описывать не буду, все стандартно (я использовал динамическую ссылку, скорее всего можно и статическую)
3. Вызываем функцию:
// Функция инициализирует параметры метода WS и вызывает метод WS
//
Функция ВыполнитьОперациюWS(ПроксиФабрикиXDTO, ИмяОперацииWS, СтруктураПараметров1С = Неопределено) Экспорт
Перем СтруктураПараметровОперацииWS;
СтруктураПараметровОперацииWS = ИнициализироватьСтруктуруПараметровОперацииWS(СтруктураПараметров1С);
ПолучитьСтруктуруПараметровОперацииWS(ПроксиФабрикиXDTO, ИмяОперацииWS, СтруктураПараметровОперацииWS);
ПреобразоватьСтруктуруПараметровОперацииWS(ПроксиФабрикиXDTO, ИмяОперацииWS, СтруктураПараметровОперацииWS);
СтрокаПараметровОперацииWS = ПолучитьСтрокуПараметровОперацииWSПоСтруктуре(СтруктураПараметровОперацииWS, "СтруктураПараметровОперацииWS");
Попытка
Если СтруктураПараметровОперацииWS.ВозвращаемоеЗначение = Неопределено Тогда
Выполнить("ПроксиФабрикиXDTO." + ИмяОперацииWS + "(" + СтрокаПараметровОперацииWS + ")");
Иначе
Выполнить("СтруктураПараметровОперацииWS.ВозвращаемоеЗначение = ПроксиФабрикиXDTO." + ИмяОперацииWS + "(" + СтрокаПараметровОперацииWS + ")");
КонецЕсли;
Исключение
КонецПопытки;
СтруктураПараметровОперацииWS.ВозвращаемоеЗначение = ПреобразоватьОбъектXDTOвСтруктуру(СтруктураПараметровОперацииWS.ВозвращаемоеЗначение);
Если ТипЗнч(СтруктураПараметровОперацииWS.Параметры) = Тип("Структура") Тогда
Для Каждого Пар Из СтруктураПараметровОперацииWS.Параметры Цикл
СтруктураПараметровОперацииWS.Параметры.Вставить("Значение", ПреобразоватьОбъектXDTOвСтруктуру(Пар.Значение));
КонецЦикла;
КонецЕсли;
Возврат СтруктураПараметровОперацииWS;
КонецФункции //ВыполнитьОперациюWS
// Процедура заполняет структуру параметров WS по структуре параметров 1С
//
// Параметры:
// ПроксиФабрикиXDTO, ИмяОперацииWS, СтруктураПараметров1С, СтруктураПараметровОперацииWS
//
Процедура ПолучитьСтруктуруПараметровОперацииWS(ПроксиФабрикиXDTO, ИмяОперацииWS, СтруктураПараметровОперацииWS)
Перем ТипОперацииWS;
ПроверятьПараметр1С = (СтруктураПараметровОперацииWS.Параметры1С <> Неопределено);
Для каждого ОперацияWS Из ПроксиФабрикиXDTO.ТочкаПодключения.Интерфейс.Операции Цикл
Если ОперацияWS.Имя = ИмяОперацииWS Тогда
Если ОперацияWS.ВозвращаемоеЗначение <> Неопределено Тогда
СтруктураПараметровОперацииWS.ВозвращаемоеЗначение = ПроксиФабрикиXDTO.ФабрикаXDTO.Создать(ОперацияWS.ВозвращаемоеЗначение.Тип);
КонецЕсли;
// Добавим URIПространстваИмен и Объект типа операции
Для каждого ПакетXDTO ИЗ ПроксиФабрикиXDTO.ФабрикаXDTO.Пакеты Цикл
Для каждого СвойствоXDTO Из ПакетXDTO.КорневыеСвойства Цикл
Если СвойствоXDTO.Имя = ИмяОперацииWS Тогда
СтруктураПараметровОперацииWS.URIПространстваИмен = ПакетXDTO.URIПространстваИмен;
ТипОперацииWS = СвойствоXDTO.Тип;
КонецЕсли;
КонецЦикла;
КонецЦикла;
ОбъектXDTO = ПроксиФабрикиXDTO.ФабрикаXDTO.Создать(ТипОперацииWS);
Для каждого ПараметрОперацииWS Из ОперацияWS.Параметры Цикл
Объект1С = Неопределено;
Если ПроверятьПараметр1С И СтруктураПараметровОперацииWS.Параметры1С.Свойство(ПараметрОперацииWS.Имя, Объект1С) Тогда
ОбъектПараметраОперацииWS = ПолучитьОбъектXDTOпоСтруктуреОбъекта1С(ПроксиФабрикиXDTO, ПараметрОперацииWS.Тип, Объект1С);
ОбъектXDTO[ПараметрОперацииWS.Имя] = ОбъектПараметраОперацииWS;
СтруктураПараметровОперацииWS.Параметры.Вставить(ПараметрОперацииWS.Имя, ОбъектПараметраОперацииWS);
Иначе
СтруктураПараметровОперацииWS.Параметры.Вставить(ПараметрОперацииWS.Имя, Неопределено);
КонецЕсли;
КонецЦикла;
//СтруктураПараметровОперацииWS.ОбъектОперацииWS = ОбъектXDTO;
КонецЕсли;
КонецЦикла;
КонецПроцедуры // ЗаполнитьСтруктуруПараметровОперацииWS(ПроксиФабрикиXDTO, ИмяОперацииWS, СтруктураПараметровОперацииWS)
// Процедура Преобразует формат параметров WS 1С в формат WS внешней системы (SAP)
//
// Параметры:
// ПроксиФабрикиXDTO, ИмяОперацииWS, СтруктураПараметровОперацииWS
//
Процедура ПреобразоватьСтруктуруПараметровОперацииWS(ПроксиФабрикиXDTO, ИмяОперацииWS, СтруктураПараметровОперацииWS)
Для каждого ОперацияWS Из ПроксиФабрикиXDTO.ТочкаПодключения.Интерфейс.Операции Цикл
Если ОперацияWS.Имя = ИмяОперацииWS Тогда
Для каждого Параметр Из СтруктураПараметровОперацииWS.Параметры Цикл
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку("UTF-8");
ЗаписьXML.ЗаписатьОбъявлениеXML();
ЗаписьXML.ЗаписатьНачалоЭлемента(ИмяОперацииWS);
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("", СтруктураПараметровОперацииWS.URIПространстваИмен);
ПроксиФабрикиXDTO.ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, Параметр.Значение, Параметр.Ключ);
ЗаписьXML.ЗаписатьКонецЭлемента();
Стр = ЗаписьXML.Закрыть();
// Преобразуем XML (для более сложных случаев надо задействовать XSLT)
Стр = СтрЗаменить(Стр, ИмяОперацииWS, "n0:" + ИмяОперацииWS);
Стр = СтрЗаменить(Стр, "xmlns=", "xmlns:n0=");
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(Стр);
ЧтениеXML.ПерейтиКСодержимому();
ЧтениеXML.Прочитать();
Попытка
СтруктураПараметровОперацииWS.Параметры.Вставить(Параметр.Ключ, ПроксиФабрикиXDTO.ФабрикаXDTO.ПрочитатьXML(ЧтениеXML));
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
КонецЕсли;
КонецЦикла;
КонецПроцедуры // ПреобразоватьСтруктуруПараметровОперацииWS(ПроксиФабрикиXDTO, ИмяОперацииWS, СтруктураПараметровОперацииWS)
// Функция возвращает строку параметров через запятую из структуры
//
// Параметры:
// Нет
//
Функция ПолучитьСтрокуПараметровОперацииWSПоСтруктуре(СтруктураПараметровОперацииWS, ИмяПеременнойСтруктурыПараметровОперацииWS)
Перем ВозвращаемоеЗнач;
ВозвращаемоеЗнач = "";
Если ТипЗнч(СтруктураПараметровОперацииWS) = Тип("Структура") Тогда
Для каждого Пар Из СтруктураПараметровОперацииWS.Параметры Цикл
ВозвращаемоеЗнач = ВозвращаемоеЗнач + ", " + ИмяПеременнойСтруктурыПараметровОперацииWS + ".Параметры." + Пар.Ключ;
КонецЦикла;
Если ВозвращаемоеЗнач <> "" Тогда
ВозвращаемоеЗнач = Сред(ВозвращаемоеЗнач, 3);
КонецЕсли;
КонецЕсли;
Возврат ВозвращаемоеЗнач;
КонецФункции // ПолучитьСтрокуПараметровОперацииWSПоСтруктуре(СтруктураПараметровОперацииWS, ИмяСтруктурыПараметровОперацииWS)
// Функция возвращает структуру по объекту XDTO
//
Функция ПреобразоватьОбъектXDTOвСтруктуру(ОбъектXDTO)
Перем ВозвращаемоеЗнач;
Если ОбъектXDTO = Неопределено Тогда
ВозвращаемоеЗнач = Неопределено;
ИначеЕсли ТипЗнч(ОбъектXDTO) = Тип("ЗначениеXDTO") Тогда
ВозвращаемоеЗнач = ОбъектXDTO.Значение;
ИначеЕсли ТипЗнч(ОбъектXDTO) = Тип("ОбъектXDTO") Тогда
ВозвращаемоеЗнач = Новый Структура;
Для каждого СвойствоXDTO Из ОбъектXDTO.Свойства() Цикл
ВозвращаемоеЗнач.Вставить(СвойствоXDTO.Имя);
Попытка // свойство - списокXDTO
СписокXDTO = ОбъектXDTO.ПолучитьСписок(СвойствоXDTO);
КоличествоСписка = СписокXDTO.Количество();
МассивЗначений = Новый Массив;
Для Сч = 0 По КоличествоСписка - 1 Цикл
МассивЗначений.Добавить(ПреобразоватьОбъектXDTOвСтруктуру(СписокXDTO.ПолучитьXDTO(Сч)));
КонецЦикла;
ВозвращаемоеЗнач[СвойствоXDTO.Имя] = МассивЗначений;
Исключение // свойство - объектXDTO/значениеXDTO
ВозвращаемоеЗнач[СвойствоXDTO.Имя] = ПреобразоватьОбъектXDTOвСтруктуру(ОбъектXDTO.ПолучитьXDTO(СвойствоXDTO));
КонецПопытки;
КонецЦикла;
КонецЕсли;
Возврат ВозвращаемоеЗнач;
КонецФункции
4. Ключевой является преобразование функция ПреобразоватьСтруктуруПараметровОперацииWS
Я ее реализовал простой СтрЗаменить, т.к. этого оказалось достаточно, но в принципе можно было бы провести XSLT- преобразование (в 1С эта возможность тоже штатная).
Причина возникновения этой функции в том, что 1С добавляет и в узел, и в его подчиненные элементы префикс имени (не знаю, точно ли передаю термины, т.к. не силен в веб технологиях, надеюсь смысл понятен). А SAP эти префиксы не воспринимает, и потому считает соответствующие значение пустыми. Фактические же префикс надо добавлять только в сам узел (в данном случае узел параметра операции). Это я и делаю с помощью СтрЗаменить.
Отвечать и оформлять если что, буду позже, просто думаю, что данный материал может пригодится не только для вызова сервисов SAP, но и для других Web-сервисов.
Спасибо, интересно!
http://infostart.ru/public/66592/
Для оформления
Оформлю позднее.
Выявил, что ответные параметры из SAP в виде объектов XDTO все же не принимаются (со значениями опять же проблем нет). Входные/выходные параметры, тоже не отрабатывают, в ту сторону уходят, а назад платформа 1с выдает ошибку. Пока для обработной передачи остаются только параметры значения (например в виде строки), что конечно не достаточно, но похоже ограничения самой платформы не обойти. Может ее когда нибудь исправят.
Пример выдаваемой ошибки:
Проверка дополнительного свойства:
форма: Элемент
имя: NameItem: Ошибка преобразования данных XDTO:
Чтение объекта типа: {urn:sap-com:document:sap:soap:functions:mc-style}NameType — [13,26]
Проверка дополнительного свойства:
форма: Элемент
имя: item: Ошибка проверки данных XDTO:
не могли бы вы привести более полный код?
потому что никак не могу понять что же за структуру надо сделать в СтруктураПараметров1С
и что делает процедура ИнициализироватьСтруктуруПараметровОперацииWS
заранее благодарен!
(3) Извиняюсь за задержку, здесь не очень часто бываю. Код скорее всего уже не найду, т.к. сменил место работы. СтруктураПараметров1С это:
Массив используется для передачи таблиц (Список XDTO)
Насколько помню:
ИнициализироватьСтруктуруПараметровОперацииWS по структуре параметров 1С создает по сути не заполненный объект XDTO
В общем попробую найти код, если найду, выложу
Спасибо!
Я знаешь как пробовал делать, указываешь в качестве параметра метода anyType для веб-сервиса и он может у тебя все принимать и все передавать
(6) Trise, а если веб-сервис не мой, как я могу изменить данные о параметрах?
По сути самая важная процедура в данном примере — это «ПреобразоватьСтруктуруПараметровОперацииWS». Она отвязывает значения параметров от пространства имен функции. Совсем не обязательно, как в данном примере, прогонять все параметры через эту процедуру, достаточно обработать только параметры со сложных типов.
Кто-нибудь сталкивался с проблемой, что имя метода содержит точку. Соответственно при вызове
возникает исключительная ситуация «Поле объекта не обнаружено».
(9) harmer, (опять поздно отвечаю), но разве можно имя метода через точку писать, разве правила имени не такие же, как у любых переменных 1С? Или это не 1с веб-сервис?
Это не 1С, это SAP.
Подтверждаю — если 1с-кий Web-сервис в связке с SAP работает на ура! То в SAP-кий Web-сервис — смог передать только элементарные типы данных — строка, число. Структуру — ни в какую. 2-й день не могу АБАПЕРУ передать структуру состоящую из двух реквизитов строчного типа. Автору статьи огромнейший респект.
Есть другой проверенный подход. В SAP передавать заранее подготовленную строку файла XML (тип string). SAP имеет ограничение длины этой строки — 2 Гб. Для обменов — этого будет достаточно. В 1с создаем пакет XDTO (с таблицами, списками значений и так далее), с помощью которого создадим строку XML. Собственно ее и передадим на Веб-сервис SAP.
Вот код:
Показать
Собственно, WS-ссылка и пакета XDTO — прикрепляю в картинках.