Обмен с помощью Web - Сервисов. Новый (С примерами)

Артур 115 3 1 3

Продолжим цикл статей про обмены с помощью встроенных механизмов 1С -Web-Сервисы.

Рассмотрим простой пример самописного обмена с мобильным приложением.
Для начала создаем Web-Сервис (С наименованием "ObmenMobil").
-URl пространство имен - вводим ip адресс для удобства (пример: 127.1.1.1)
-Пакеты XDTO , до сих пор до конца не разобрался )), поэтому выбираю стандартный (http://v8.1c.ru/8.1/data/core).
-Имя файла публикации - Любое значение с форматом *.1cws(Пример: ObmenMobil.1cws)
111.jpg

Далее, добавляем новую "Операцию" в наш Web-Сервис. (Наименование: "ПолучитьСписокНоменклатуры").
Тип возвращаемого значения укажем: ValueStorage (http://v8.1c.ru/8.1/data/core).
(PS. Выбранный тип содержится в Пакете XDTO (http://v8.1c.ru/8.1/data/core), указанной ранее в Web-сервисе).
(PS. ValueStorage - Это "Хранилище значений", удобен тем что его можно сжать, если объем данных будет большим, но так же можно использовать строковый тип (Например стандартный тип: "string (http://www.w3.org/2001/XMLSchema)")).

И добавим ему параметры. (В данном примере я добавлю только 1 универсальный параметр).
Наименование: "Параметры" - Тип значения: "string (http://www.w3.org/2001/XMLSchema)"
2.jpg

Процедура модуля:

///Параметры - Тип: "строка"
Функция ПолучитьСписокНоменклатуры(Параметры)
	
	///Параметры - Это будет Структура, сериализованная в строку XML.
	///поэтому конвертируем его обратно в структуру.
	
	ЧтениеXMLДанных = Новый ЧтениеXML;
	ЧтениеXMLДанных.УстановитьСтроку(Параметры);
	СтруктураПараметров = СериализаторXDTO.ПрочитатьXML(ЧтениеXMLДанных);
	ЧтениеXMLДанных.Закрыть();  

	
	/// Основная процедура вынесена в общие модуле, так как Синтаксис ошибкок в этом модуле не работает
	Возврат ОбменДанными.ПолучитьСписокНоменклатурыXML(СтруктураПараметров);

КонецФункции


//// Общий модуль: ОбменДанными
Функция ПолучитьСписокНоменклатурыXML(СтруктураПараметров) Экспорт

	ДобавлятьШтрихКод 	= Ложь;
	
	/// если в параметрах указано свойство "Штрихкод" - используем его значение 
	СтруктураПараметров.Свойство("ШтрихКод",ДобавлятьШтрихКод);
	
	

	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ
		|	Номенклатура.Код КАК Код,
		|	Номенклатура.Наименование КАК Наименование,
		|	Номенклатура.ЕдиницаДляОтчетов.Наименование КАК ЕдиницаДляОтчетовНаименование,
		|	Номенклатура.ЕдиницаДляОтчетов.Вес КАК ЕдиницаДляОтчетовВес,
		|	Номенклатура.ЕдиницаДляОтчетов.Объем КАК ЕдиницаДляОтчетовОбъем,
		|	Номенклатура.ЕдиницаДляОтчетов.Коэффициент КАК ЕдиницаДляОтчетовКоэффициент,
		|	Номенклатура.ЭтоГруппа КАК ЭтоГруппа,
		|	Номенклатура.ПометкаУдаления КАК ПометкаУдаления,
		|	Номенклатура.Ссылка КАК Ссылка,
		|	Номенклатура.ЕдиницаДляОтчетов.Ссылка КАК ЕдиницаДляОтчетовСсылка
		|ИЗ
		|	Справочник.Номенклатура КАК Номенклатура
		|ГДЕ
		|	Номенклатура.Ссылка В ИЕРАРХИИ(&Родитель)
		|	И Номенклатура.ПометкаУдаления = ЛОЖЬ";
	
	Запрос.УстановитьПараметр("Родитель", Родитель);
	
	РезультатЗапроса = Запрос.Выполнить();
	
	Выборка = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
	
	//Весь список номенклатуры буден помещен в массив
	ОбъектСписок = новый Массив;

	Пока Выборка.Следующий() Цикл
		
		//Каждую номенклатуру помещаем в струткуру
		ДанныеНоменклатуры = новый Структура("Код, Наименование, Ссылка, ЭтоГруппа, Родитель, ЕдиницаИзмерения, ШтрихКоды",
		 						Выборка.Код, Выборка.Наименование,XMLСтрока(Выборка.Ссылка),Выборка.Ссылка.ЭтоГруппа,,,); 
								
		//Если есть родитель, то создаем рекурсивно родителя
		Если НЕ Выборка.Ссылка.Родитель.Пустая() Тогда
			ДанныеНоменклатуры.Родитель =  ДобавитьРодителей(Выборка.Ссылка.Родитель);
		КонецЕсли;
		
		//Создаем Единицу измерения в виде структуры
		Если НЕ Выборка.Ссылка.ЭтоГруппа Тогда

			Если НЕ Выборка.Ссылка.ЕдиницаДляОтчетов.Пустая() Тогда
	            ДанныеЕдиницыИзмерения = новый Структура("Код, Наименование, Ссылка, Вес, Объем, Коэффициент",  
			 				Выборка.ЕдиницаДляОтчетовСсылка.Код,Выборка.ЕдиницаДляОтчетовСсылка.Наименование,XMLСтрока(Выборка.ЕдиницаДляОтчетовСсылка),
							Выборка.ЕдиницаДляОтчетовСсылка.Вес,Выборка.ЕдиницаДляОтчетовСсылка.Объем,Выборка.ЕдиницаДляОтчетовСсылка.Коэффициент);
				
				ДанныеНоменклатуры.ЕдиницаИзмерения = ДанныеЕдиницыИзмерения;
			КонецЕсли;
			
			Если ДобавлятьШтрихКод Тогда
				///Штрихкодов может быть несколько, поэтому отдельно рисуем запрос на получения и добавляем в массив
				ДанныеНоменклатуры.ШтрихКоды = ПолучитьШтрихКоды(Выборка.Ссылка);
			КонецЕсли;	
		КонецЕсли;	
		
		ОбъектСписок.Добавить(ДанныеНоменклатуры);
	
	КонецЦикла;
	
	Запись = Новый ЗаписьXML;
	Запись.УстановитьСтроку(); 
	
	//Преобразуем массив в объект XDTO
	МассивВОбъектеXDTO = СериализаторXDTO.ЗаписатьXDTO(ОбъектСписок);
	
	//Записываем объект XDTO в XML строку
	ФабрикаXDTO.ЗаписатьXML(Запись, МассивВОбъектеXDTO); 
	
	ДанныеXML = Запись.Закрыть(); // документ готов!
	
	///Поместим данные в хранилище значений в сжатом виде
	ХранилищеЗнч = новый ХранилищеЗначения(ДанныеXML,новый СжатиеДанных(9))
	
	Возврат ХранилищеЗнч;
	
КонецФункции

Функция ДобавитьРодителей(Родитель)
	
	ДанныеРодителя = новый Структура("Код, Наименование, Ссылка, ЭтоГруппа, Родитель",
		 						Родитель.Код, Родитель.Наименование,XMLСтрока(Родитель.Ссылка),Родитель.ЭтоГруппа,);

	Если НЕ Родитель.Родитель.Пустая() Тогда
		ДанныеРодителя.Родитель = ДобавитьРодителей(Родитель.Родитель);
	КонецЕсли;
	
	Возврат ДанныеРодителя;
КонецФункции


Функция ПолучитьШтрихКоды(Владелец)

	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ
		|	Штрихкоды.Штрихкод КАК Штрихкод,
		|	Штрихкоды.Владелец КАК Владелец
		|ИЗ
		|	РегистрСведений.Штрихкоды КАК Штрихкоды
		|ГДЕ
		|	Штрихкоды.Владелец = &Владелец";
	
	Запрос.УстановитьПараметр("Владелец", Владелец);
	ТЧ = Запрос.Выполнить().Выгрузить();
	Если ТЧ.Количество() = 0 Тогда
		возврат новый Массив;
	КонецЕсли;
	
	Возврат ТЧ.ВыгрузитьКолонку("Штрихкод");
		
КонецФункции

Всё. Публикуем базу и можно подключаться)

БАЗА 2. Подключение и загрузка данных:

Процедура ЗагрузитьНоменклатуру()  экспорт	
	///----------данный кусок перенесен в справочник "ПодключениеКWS", чтобы не держать данные в модуле---<
	ВСОпределение = Новый WSОпределения("127.1.1.1/Obmen/ws/Obmen.1cws?wsdl", "admin", "pass"); 
	//127.1.1.1 - ВашИПАдресГдеОпубликованWebСервис 
	//admin - пользователь информационной базы с полными правами и пароль -pass
	ВСПрокси = Новый WSПрокси(ВСОпределение, "127.1.1.1", "Obmen", "ObmenSoap");
	//127.1.1.1 - URl пространство имен Веб сервиса первой базы, Obmen -наименование 
	// расширения ,
	//ObmenSoap тоже самое Но добавляем Soap к названии ))
	
	Склад= Элементы.Склад.Значение; //Элемент формы, выбранное поле - склад
	Время=ТекущаяДата();
	
	ВСПрокси.Пользователь = "admin";
	ВСПрокси.Пароль = "pass";
	
	
	/// Добавим параметр: Штрихкод	
	ПараметрЗапроса = новый Структура;
	ПараметрЗапроса.Вставить("Штрихкод",Истина);
	
	/// Сериализуем структуру в строку.
	ДокументВОбъектеXDTO = СериализаторXDTO.ЗаписатьXDTO(ПараметрЗапроса);
	МойXML = Новый ЗаписьXML;
	МойXML.УстановитьСтроку();
	ФабрикаXDTO.ЗаписатьXML(МойXML, ДокументВОбъектеXDTO);
	
	
	ПараметрЗапроса = МойXML.Закрыть();  	
	
	ХранилищеЗначений = ВСПрокси.ПолучитьСписокНоменклатуры(ПараметрЗапроса);  // подключаемся и получаем данные xml 	
////--------------------------------------->	 
/// ! для удобства добавил справочник "ПодключениеКWS" для заполнения настроек Веб сервисов, и получаю данные оттуда (Процедура ниже)
	    //Подключение = ПодключениеКWS();
		//ХранилищеЗначений = Подключение.ПолучитьСписокНоменклатуры(ПараметрЗапроса); 
		
	
	ТекстXML = ХранилищеЗначений.Получить();   
	
	ЧтениеXML = новый ЧтениеXML;
	ЧтениеXML.УстановитьСтроку(ТекстXML);
	
	/// Отключимся от БАЗЫ 1, так как данные уже получены. 
	//Подключение = Неопределено;  
	ВСПрокси = Неопределено;
	
	МассивНоменклатуры = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
	
	Для каждого Стр из МассивНоменклатуры Цикл
		
		Номенклатура = СоздатьНоменклатуру(Стр);

	КонецЦикла;  
	

КонецПроцедуры   


/// ОбъектНастроек = Справочник объект "ПодключениеКWS", используется для тетирования нового подключения до записи.  
Функция ПодключениеКWS(ОбъектНастроек = Неопределено) Экспорт 
	
	Настройки = Константы.НастройкиПодключения.Получить(); 		
        
	
	Если ОбъектНастроек = Неопределено И Настройки.Пустая() Тогда
		ВызватьИсключение("Не заполнены настройки подключения к веб сервисам!");
	КонецЕсли;
	
	Если ОбъектНастроек <> Неопределено Тогда  ///Для тестов
		Настройки = ОбъектНастроек;	
	КонецЕсли;
	
	МестоположениеWSDL 			= Настройки.IPАдрес +"/"+ Настройки.МестоположениеWSDL;		
	ИмяПользователя 			= Настройки.ИмяПользователя;
	Пароль						= Настройки.Пароль;            		
	URIПространстваИменСервиса 	= Настройки.URIПространстваИмен; 	
	ИмяСервиса					= Настройки.ИмяСервиса;					
		
	ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL;            
	
	ВСОпределение = Новый WSОпределения(МестоположениеWSDL, ИмяПользователя, Пароль,,,ЗащищенноеСоединение);        	
	ВСПрокси = Новый WSПрокси(ВСОпределение,URIПространстваИменСервиса , ИмяСервиса,ИмяСервиса+"Soap" );     
	
	ВСПрокси.Пользователь = ИмяПользователя;
	ВСПрокси.Пароль = Пароль;
		
	Возврат ВСПрокси;

КонецФункции


Функция СоздатьНоменклатуру(ДанныеНоменклатуры)   
	
	///Проверка на существование ссылки. Если ссылка найдена, пропускаем.
	СсылкаНоменклатуры = XMLЗначение(Тип("СправочникСсылка.Номенклатура"),ДанныеНоменклатуры.Ссылка);  
	
	///Ссылка будет отображаться как битая, проверяем по реквизиту "ВерсияДанных"
	Если НЕ ЗначениеЗаполнено(СсылкаНоменклатуры.ВерсияДанных) Тогда   
		
		Если ДанныеНоменклатуры.ЭтоГруппа Тогда
			СПР = Справочники.Номенклатура.СоздатьГруппу();
		Иначе
			СПР = Справочники.Номенклатура.СоздатьЭлемент();    
		КонецЕсли;  
		СПР.УстановитьСсылкуНового(СсылкаНоменклатуры);
	Иначе		
		СПР 				= СсылкаНоменклатуры.ПолучитьОбъект(); 
	КонецЕсли;

	СПР.Код 			= ДанныеНоменклатуры.Код;     
	СПР.Наименование 	= ДанныеНоменклатуры.Наименование; 
		
	///Если есть родитель, сначала нужно создать родителя, и так до самого корня начала
	Если ДанныеНоменклатуры.Родитель <> Неопределено Тогда
		СПР.Родитель 		= СоздатьНоменклатуру(ДанныеНоменклатуры.Родитель);	
	КонецЕсли;
					
	СПР.Записать();
			
	Если НЕ СПР.ЭтоГруппа Тогда 
			
		Если ДанныеНоменклатуры.ЕдиницаИзмерения <> Неопределено Тогда
			НоваяЕД = СоздатьЕдиницуИзмерения(ДанныеНоменклатуры.ЕдиницаИзмерения,СПР.Ссылка);					
			СПР.БазоваяЕдиницаИзмерения = НоваяЕД.Наименование;
			СПР.ЕдиницаИзмерения 		= НоваяЕД.Ссылка;
					
			СПР.Записать();
		КонецЕсли; 
			
		Для каждого ст из ДанныеНоменклатуры.ШтрихКоды цикл
			ЗаписатьШтрихКод(СПР.Ссылка,ст);
		КонецЦикла;  
		
	КонецЕсли;
		
	Возврат СПР.Ссылка;
  		
КонецФункции  

Процедура ЗаписатьШтрихКод(Владелец,ШтрихКод)
	МенеджерЗаписи = РегистрыСведений.Штрихкоды.СоздатьМенеджерЗаписи();
	
	МенеджерЗаписи.Владелец = Владелец;
	МенеджерЗаписи.ШтрихКод = ШтрихКод;

	МенеджерЗаписи.Записать();
КонецПроцедуры

Функция СоздатьЕдиницуИзмерения(СтрокаДанных,Владелец) 
	
	СсылкаЕД = XMLЗначение(Тип("СправочникСсылка.ЕдиницаИзмерения"),СтрокаДанных.Ссылка); 	
	Если НЕ ЗначениеЗаполнено(СсылкаЕД.ВерсияДанных) Тогда
		НоваяЕД = Справочники.ЕдиницаИзмерения.СоздатьЭлемент();
		НоваяЕД.УстановитьСсылкуНового(СсылкаЕД);
	Иначе	
		НоваяЕД = СсылкаЕД.ПолучитьОбъект();
	КонецЕсли; 	
	
	НоваяЕД.Код 			= СтрокаДанных.Код;
	НоваяЕД.Наименование   	= СтрокаДанных.Наименование; 
	НоваяЕД.Вес             = СтрокаДанных.Вес;
	НоваяЕД.Объем           = СтрокаДанных.Объем;
	НоваяЕД.Коэффициент     = СтрокаДанных.Коэффициент;
				
	НоваяЕД.Владелец 		= Владелец;  
	НоваяЕД.Записать(); 

	Возврат НоваяЕД.Ссылка;

КонецФункции   

1

Комментарии

МВЮ
#1, 31 января 2023 19:32

что за ужасный код выложили...


Обсуждение в Telegram

См. также

Обмен через ВЕБ Сервисы 2 часть

Обмен через ВЕБ Сервисы 1 часть

ИнициализироватьПараметрыWebСервиса (БСП)

ОбработатьИнформациюОбОшибкеWebСервиса (БСП)

Обмен данными XDTO (пример)

ПолучитьОписаниеОшибкиWebСервиса (БСП)

Склонение слов

СобытиеЖурналаРегистрацииУстановкаПодключенияКWebСервису (БСП)

ПолучитьПроксиМенеджераСервиса (БСП)

Модератору