WSОпределения на клиенте
У клиента была настроена интеграция с ГИИС ДМДК (ювелирные изделия).
Все работало хорошо в локальной базе, но перестало работать на облаке. Выдавало ошибку сбоя соединения:
В помощнике настройки подключения на облаке также выдавало такую ошибку.
Обнаружил, что соединение проверяется на сервере.
Но интеграция с ГИИС осуществляется через TTLS туннель, который развернут на клиентском компьютере. Я уж подумал, что код содержит обращения к ГИИС на сервере, но нет, слава богу, обращения были везде на клиенте.
Причем, SOAP запросы формируются как обычные HTTPS-запросы, генерируются непосредственно в XML.
Однако анализ показал, что ответ анализируется через WSОпределения, которые пытаются создаться по WSDL-адресу на сервере, при этом и возникает ошибка.
Но WSОпределения нельзя создать на клиенте…
Поэтому было решено считывать WSDL по ссылке на клиенте, а
АдресWSDL = "http://"+СокрЛП(ГИИС_ВызовСервера.ЗаполнитьСтруктуруПодключенияСервер(Объект.Организация).Адрес)+":"+СокрЛП(ГИИС_ВызовСервера.ЗаполнитьСтруктуруПодключенияСервер(Объект.Организация).Порт)+"/ws/v3/exchange3.wsdl"; ДД = ПолучитьWSDLКакДвоичныеДанные(АдресWSDL); ПрочитатьОтвет(Результат.ПолучитьТелоКакСтроку(),ПараметрыВыполнения, ДД); &НаСервере Процедура ПрочитатьОтвет(СтрокаОтвета,ПараметрыВыполнения, ДД) Экспорт //Осипов 2024-04-01 чтобы из файла wsdl получать //Определение = Новый WSОпределения("http://"+СокрЛП(ГИИС_Сервер.ЗаполнитьСтруктуруПодключенияСервер(Объект.Организация).Адрес)+":"+СокрЛП(ГИИС_Сервер.ЗаполнитьСтруктуруПодключенияСервер(Объект.Организация).Порт)+"/ws/v3/exchange3.wsdl"); ИмяВФ = ПолучитьИмяВременногоФайла("wsdl"); ДД.Записать(ИмяВФ); Определение = Новый WSОпределения(ИмяВФ); ЧтениеXML = Новый ЧтениеXML; ... КонецПроцедуры
При этом я нашел на форуме функцию чтения WSDL. Она корявая, но в целом рабочая.
При этом у меня была проблема создания WSОпределения из файла:
Оказалось, файл не считывался (возвращался пустой), а то я думал, что нужно указывать имя файла в формате с префиксом file:
Взятый с форума код по чтению файла у меня вышел такой после небольшой доработки напильником (Структуру URI можно было бы взять и из БСП, но делал второпях):
&НаКлиенте Функция СтруктураURI(Знач СтрокаURI) Экспорт СтрокаURI = СокрЛП(СтрокаURI); // схема Схема = ""; Позиция = Найти(СтрокаURI, "://"); Если Позиция > 0 Тогда Схема = НРег(Лев(СтрокаURI, Позиция - 1)); СтрокаURI = Сред(СтрокаURI, Позиция + 3); КонецЕсли; // строка соединения и путь на сервере СтрокаСоединения = СтрокаURI; ПутьНаСервере = ""; Позиция = Найти(СтрокаСоединения, "/"); Если Позиция > 0 Тогда ПутьНаСервере = Сред(СтрокаСоединения, Позиция + 1); СтрокаСоединения = Лев(СтрокаСоединения, Позиция - 1); КонецЕсли; // информация пользователя и имя сервера СтрокаАвторизации = ""; ИмяСервера = СтрокаСоединения; Позиция = Найти(СтрокаСоединения, "@"); Если Позиция > 0 Тогда СтрокаАвторизации = Лев(СтрокаСоединения, Позиция - 1); ИмяСервера = Сред(СтрокаСоединения, Позиция + 1); КонецЕсли; // логин и пароль Логин = СтрокаАвторизации; Пароль = ""; Позиция = Найти(СтрокаАвторизации, ":"); Если Позиция > 0 Тогда Логин = Лев(СтрокаАвторизации, Позиция - 1); Пароль = Сред(СтрокаАвторизации, Позиция + 1); КонецЕсли; // хост и порт Хост = ИмяСервера; Порт = ""; Позиция = Найти(ИмяСервера, ":"); Если Позиция > 0 Тогда Хост = Лев(ИмяСервера, Позиция - 1); Порт = Сред(ИмяСервера, Позиция + 1); КонецЕсли; Результат = Новый Структура; Результат.Вставить("Схема", Схема); Результат.Вставить("Логин", Логин); Результат.Вставить("Пароль", Пароль); Результат.Вставить("ИмяСервера", ИмяСервера); Результат.Вставить("Хост", Хост); Результат.Вставить("Порт", ?(Порт <> "", Число(Порт), Неопределено)); Результат.Вставить("ПутьНаСервере", ПутьНаСервере); Возврат Результат; КонецФункции &НаКлиенте Процедура ВыполнитьHTTPЗапрос(ПолныйАдресРесурса,имяВрФайла) //https://forum.mista.ru/topic/854995 //Осипов 2024-04-01 для чтения wsdl ссылки СтруктураURI = СтруктураURI(ПолныйАдресРесурса); HTTPСоединение = Новый HTTPСоединение(СтруктураURI.Хост, СтруктураURI.Порт); //на случай незащищенного соединения //HTTPСоединение = Новый HTTPСоединение(СтруктураURI.Хост,СтруктураURI.Порт,,,,,Новый ЗащищенноеСоединениеOpenSSL); HTTPЗапрос = Новый HTTPЗапрос(СтруктураURI.ПутьНаСервере); Попытка Результат = HTTPСоединение.Получить(HTTPЗапрос,имяВрФайла); Исключение // исключение здесь говорит о том, что запрос не дошел до HTTP-Сервера Сообщить("Произошла сетевая ошибка!"); ВызватьИсключение; КонецПопытки; // Анализируем фатальные ошибки // В большинстве случаев нужно остановить работу и показать пользователю сообщение об ошибке, // включив в него HTTP-статус // Ошибки 4XX говорят о неправильном запросе - в широком смысле // Может быть неправильный адрес, ошибка аутентификации, плохой формат запроса // Подробнее смотри http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4 Если Результат.КодСостояния >= 400 и Результат.КодСостояния < 500 Тогда Сообщить("Код статуса больше 4XX, ошибка запроса. Код статуса: " + Результат.КодСостояния); КонецЕсли; // Ошибки 5XX говорят о проблемах на сервере (возможно, прокси-сервер) // Это может быть программная ошибка, нехватка памяти, ошибка конфигурации и т.д. // Подробнее смотри http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5 Если Результат.КодСостояния >= 500 и Результат.КодСостояния < 600 Тогда Сообщить("Код статуса больше 5XX, ошибка сервера. Код статуса: " + Результат.КодСостояния); КонецЕсли; // Обрабатываем перенаправление Если Результат.КодСостояния >= 300 и Результат.КодСостояния < 400 Тогда Сообщить("Код статуса больше 3XX, Перенаправление. Код статуса: " + Результат.КодСостояния); Если Результат.КодСостояния = 302 Тогда Сообщить("Код статуса 302, Постоянное перенаправление."); АдресРесурса = Результат.Заголовки.Получить("Location"); Если АдресРесурса <> Неопределено Тогда Сообщить("Выполняю запрос по новому адресу " + АдресРесурса); ВыполнитьHTTPЗапрос(АдресРесурса,имяВрФайла); Иначе Сообщить("Сервер не сообщил адрес ресурса!"); КонецЕсли; КонецЕсли; КонецЕсли; // Статусы 1XX и 2XX считаем хорошими Если Результат.КодСостояния < 300 Тогда //Сообщить("Скорее всего все хорошо"); //Сообщить("Код статуса: " + Результат.КодСостояния); КонецЕсли; КонецПроцедуры &НаКлиенте Функция ПолучитьWSDLКакДвоичныеДанные(АдресWSDL) ИмяВФ = ПолучитьИмяВременногоФайла("wsdl"); ВыполнитьHTTPЗапрос(АдресWSDL, ИмяВФ); Возврат Новый ДвоичныеДанные(ИмяВФ); КонецФункции
Получается, что с SOAP работать на клиенте не особо получится, если архитектура такова, что туннель используется на клиенте. Придется делать XML запросы, чтобы обеспечить SOAP-функционал. Это недостаток 1С.
Свежие комментарии