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С.

fixin

Программирую на 1С с 1999 года. В 1С просто Гений. В 2020 году ушел из офиса на вольные хлеба фриланса. Принимаю заказы.

Читайте также:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *