При интеграции платформы «1С:Предприятие 8» со сторонними информационными системами разработчики часто сталкиваются со следующей проблемой: опубликованный из 1С Web-сервис формирует структуру WSDL, которая не устраивает стороннего клиента. В частности, вместо ожидаемого сторонней системой названия порта (например, wsportbinding) платформа 1С всегда генерирует две точки подключения с названиями Soap и Soap12. В результате сторонние клиенты на базе Java, .NET или PHP могут выдавать ошибки при подключении, ругаясь на повторное объявление функций или невозможность распарсить схему.
Разберем подробнее, почему платформа 1С ведет себя именно так, какие есть ограничения и какими проверенными способами можно решить эту задачу.
Проанализируем механику работы генератора WSDL-схем в 1С. Когда мы публикуем Web-сервис на веб-сервере (Apache или IIS), платформа автоматический создает файл XML-описания (WSDL). В это описание 1С по умолчанию включает сразу две привязки (bindings):
Soap: привязка для протокола SOAP версии 1.1.Soap12: привязка для протокола SOAP версии 1.2.Каждая из этих привязок содержит полный перечень операций (методов), описанных в веб-сервисе. Множество сторонних генераторов кода и клиенты интеграции считывают весь WSDL-файл целиком. Видя одинаковые функции в секциях SOAP 1.1 и SOAP 1.2, они интерпретируют их как повторное дублирование методов и отказываются создавать клиентские классы для работы с веб-сервисом.
Кроме того, если внешняя система жестко завязана на специфические наименования портов (например, wsportbinding), она не сможет обратиться к портам Soap или Soap12 без изменения своих настроек подключения.
Важно понимать, что в платформе «1С:Предприятие 8» менеджер веб-сервисов жестко зашит в ядро системы. Штатными средствами Конфигуратора нельзя:
port) или привязок (binding).Тем не менее, существуют эффективные архитектурные способы обойти это ограничение на стороне веб-сервера или с использованием других объектов 1С.
Рассмотрим наименее трудоемкий метод. При этом подходе сам Web-сервис остается в 1С в исходном виде, а сторонней системе отдается скорректированный вручную файл WSDL.
Разберем реализацию по шагам:
?wsdl.Soap в требуемое wsportbinding и приведем схему в точное соответствие с шаблоном сторонней системы.myservice.1cws?wsdl веб-сервер должен отдавать наш отредактированный статический файл. При этом все POST-запросы со сторонней системы должны продолжать проксироваться на реальный Web-сервис 1С.Если структура веб-сервиса часто меняется, более удобным выбором станет автоматическая текстовая подмена ответа 1С с помощью модулей веб-сервера.
Посмотрим, как это работает:
sub_filter в Nginx или mod_substitute в Apache) из ответа удаляются фрагменты текста, относящиеся к SOAP 1.2, а имена портов Soap налету заменяются на wsportbinding.Если внешняя система предъявляет нестандартные требования не только к WSDL, но и к структуре самих SOAP-конвертов (Envelope), целесообразно использовать объект HTTP-сервис вместо объекта Web-сервис.
Рассмотрим порядок разработки такого решения:
HTTPСервис и задаем шаблон URL.Проанализируем пример кода 1С для обработки входящего SOAP-запроса внутри HTTP-сервиса:
Функция ОбработатьЗапрос(Запрос)
ВходящийXML = Запрос.ПолучитьТелоКакСтроку();
// Создаем объект для чтения XML
Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(ВходящийXML);
// Используем ФабрикуXDTO или ЧтениеXML для парсинга SOAP-конверта
Пока Чтение.Прочитать() Цикл
Если Чтение.Имя = "MyOperationRequest" И Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
// Извлекаем входные параметры метода
КонецЕсли;
КонецЦикла;
Чтение.Закрыть();
// Формируем исходящий SOAP-ответ
Запись = Новый ЗаписьXML;
Запись.УстановитьСтроку();
Запись.ЗаписатьОбъявлениеXML();
Запись.ЗаписатьНачалоЭлемента("soap:Envelope", "http://schemas.xmlsoap.org/soap/envelope/");
Запись.ЗаписатьНачалоЭлемента("soap:Body");
Запись.ЗаписатьНачалоЭлемента("MyOperationResponse");
Запись.ЗаписатьТекст("Успешно");
Запись.ЗаписатьКонецЭлемента(); // MyOperationResponse
Запись.ЗаписатьКонецЭлемента(); // soap:Body
Запись.ЗаписатьКонецЭлемента(); // soap:Envelope
ОтветТекст = Запись.Закрыть();
Ответ = Новый HTTPСервисОтвет(200);
Ответ.Заголовки.Вставить("Content-Type", "text/xml; charset=utf-8");
Ответ.УстановитьТелоИзСтроки(ОтветТекст);
Возврат Ответ;
КонецФункции
Использование HTTPСервис полностью снимает жесткие ограничения платформы 1С по генерации WSDL и дает полный контроль над протоколом взаимодействия со сторонними системами.