Сервис управления списком баз wcib (WebCommonInfoBases) посредством JSON

24.06.22

Интеграция - WEB-интеграция

Пример реализации http-сервиса управления списками баз без использования SOAP

Скачать файлы

Наименование Файл Версия Размер
Пример сервиса wcib JSON:
.cf 79,70Kb
16
.cf 79,70Kb 16 Скачать

Предыстория:

Не так давно мне понадобилось буквально по кусочкам собирать информацию в совершенно различных источниках о том, как же все-таки реализовать сервис управления списками баз для лаунчера 1сestart через JSON. Некоторые нюансы выявлял самостоятельно. В процессе исследований обнаружил, что часть пользователей вообще не подозревает о таком варианте. Поэтому решил собрать и изложить свой опыт тут.
 

4 запроса:

Лаунчер 1cestart для варианта JSON посылает 4 запроса:

1- HEAD запрос на эндпоинт "WebCommonInfoBases". Название зашито в лаунчере, он добавляет его сам к указанному в настройках URl. На этот запрос необходимо отправить ответ с кодом 200, только в таком случае мы получим ожидаемый запрос на проверку обновления списка в нужном формате. В противном случае мы получим SOAP запрос.
2- GET запрос на эндпоинт "WebCommonInfoBases". Тут мы должны указать необходимость обновления списка баз и адрес сервиса, возвращающего этот список в формате v8i:

Пример тела ответа:

{
  "root":
  {
    "InfoBasesChanged": true,
    "URL": "http:\\СервисПолученияСписка_v8i"
  }
}

 

3- HEAD запрос на указанный ранее сервис. Принцип все тот же, отвечаем с кодом 200

4- GET запрос на указанный ранее сервис. Возвращаем тело в формате JSON

 

Пример тела ответа:

{
  "root":
  {
    "ClientID": "none",
    "InfoBasesCheckCode": "none",
    "InfoBases":"Описание в формате v8i"
  }
}

 

Настройка лаунчера


В настройках диалога запуска необходимо прописать путь к публикации первого эндпоинта по которому будет происходить проверка необходимости обновления и получение URL второго эндпоинта

 

Реализация


Создаем 2 эндпоинта:


Корневой URL у первого эндпоинта должен быть именно таким: "WebCommonInfoBases"

  

Пример тела модуля первого эндпоинта:


#Область ПрограммныйИнтерфейс

Функция CheckInfoBases_GET(Запрос)
	
	Попытка
	
		ClientID 					= Строка(Запрос.ПараметрыЗапроса["ClientID"]);
		
		// Может быть пустым
		InfoBasesCheckCode			= Строка(Запрос.ПараметрыЗапроса["InfoBasesCheckCode"]);
		
		// Может передать веб-сервер
		ЛогинПользователя			= Запрос.ПараметрыЗапроса.Получить("UserID");
		
		ИдентификаторПользователя 	= Запрос.ПараметрыURL.Получить("user_guid");
		
		Если ПустаяСтрока(ClientID) Тогда
			Ответ = Новый HTTPСервисОтвет(404);
			Возврат Ответ;
		КонецЕсли;
		
		Если Не ЗначениеЗаполнено(ИдентификаторПользователя) 
			И Не ЗначениеЗаполнено(ЛогинПользователя) Тогда
			
			Ответ = Новый HTTPСервисОтвет(404);
			Возврат Ответ;
			
		КонецЕсли;	
		
		InfoBasesChanged = Ложь;
		URL = "";
		
		СтруктураОтвета = CheckInfoBases(ClientID, InfoBasesCheckCode, InfoBasesChanged, URL
										, Запрос.БазовыйURL, ЛогинПользователя, ИдентификаторПользователя);
		
		Тело = СтроковыеФункцииКлиентСервер.КонвертироватьВJson(СтруктураОтвета);
		Ответ = Новый HTTPСервисОтвет(200);
		Ответ.УстановитьТелоИзСтроки(Тело);
		
		Ответ.Заголовки["Content-Type"]  = "application/json;charset=utf-8";
		Ответ.Заголовки["Cache-Control"] = "no-cache";
		
		Возврат Ответ;
		
	Исключение
		
		ЗаписьЖурналаРегистрации("CheckInfoBases.JSON", УровеньЖурналаРегистрации.Ошибка,
								,,СлужебныйКлиентСервер.ПодробныйТекстОшибки(ИнформацияОбОшибке()));
		ВызватьИсключение;
		
	КонецПопытки
		
КонецФункции

#КонецОбласти

#Область СлужебныеПроцедуры

Функция ПустойИдентификатор()
	Возврат "00000000-0000-0000-0000-000000000000";
КонецФункции

Функция CheckInfoBases(ClientID, InfoBaseCheckCode, InfoBasesChanged, URL, БазовыйURL, ЛогинПользователя, ИдентификаторПользователя)
	
    InfoBasesChanged = Ложь;	
	
	// TODO: Тип доступа опряделяет список для пользователя (для типа web и rdp разные списки)
	// Должен определяться по эндпоинту. Нужны разные эндпоинты для разных типов доступа
	ТипДоступа = "rdp";
	
	УстановитьПривилегированныйРежим(Истина);
	
	АдресЗащищенногоВС = Константы.URLПолученияСпискаБаз.Получить();
	
	Если ЗначениеЗаполнено(ИдентификаторПользователя) Тогда
		АдресЗащищенногоВС = АдресЗащищенногоВС + ИдентификаторПользователя+"/";	
	КонецЕсли;
	
	Если ClientID = ПустойИдентификатор()
		И InfoBaseCheckCode = ПустойИдентификатор() Тогда
		// это первое обращение клиента
		InfoBasesChanged = Истина;
		URL = АдресЗащищенногоВС;
		СтруктураОтвета = СтруктурыДанныхСервер.СтруктураОтветаПроверкаОбновления(InfoBasesChanged, URL);
		
	КонецЕсли;
	
	СтруктураОтвета = ФункцииУправленияСервер.ПроверитьПотребностьОбновления(ЛогинПользователя, ИдентификаторПользователя
																			, InfoBaseCheckCode, ТипДоступа); 
	
	Возврат СтруктураОтвета;	
	
КонецФункции

Функция RootHEAD(Запрос)
	Ответ = Новый HTTPСервисОтвет(200);
	//Ответ.Заголовки["Content-Type"]	 = "application/json;charset=utf-8";
	//Ответ.Заголовки["Cache-Control"] = "no-cache";
	Возврат Ответ;
КонецФункции

#КонецОбласти

 

Пример тела модуля второго эндпоинта:



Функция GetInfoBasesGetInfoBases_GET(Запрос)
	
	// Пропускаем запросы HEAD
	// Заглушка, необходимая 1С стартеру для отправки JSON
	Если Запрос.HTTPМетод = "" Тогда
		
		Ответ = Новый HTTPСервисОтвет(200);
		// Работает даже без заголовков
		//Ответ.Заголовки["Content-Type"]	 = "application/json;charset=utf-8";
		//Ответ.Заголовки["Cache-Control"] = "no-cache";
		Возврат Ответ;
		
	ИначеЕсли Запрос.HTTPМетод = "GET" Тогда
		
		Попытка
			
			ClientID 			= Запрос.ПараметрыЗапроса["ClientID"];
			InfoBasesCheckCode	= Запрос.ПараметрыЗапроса["InfoBasesCheckCode"];
			
			// Может передать веб-сервер
			ЛогинПользователя	= Запрос.ПараметрыЗапроса.Получить("UserID");
			
			ИдентификаторПользователя 	= Запрос.ПараметрыURL.Получить("user_guid");
			
			InfoBases 			= "";
			
			GetInfoBases(ClientID, InfoBasesCheckCode, InfoBases, Запрос.БазовыйURL, ЛогинПользователя, ИдентификаторПользователя);
			
			ДанныеОтвета = Новый Структура("root", Новый Структура("ClientID,InfoBasesCheckCode,InfoBases"
																	, ClientID, InfoBasesCheckCode, InfoBases));
			
			Тело = СтроковыеФункцииКлиентСервер.КонвертироватьВJson(ДанныеОтвета);
			
			Ответ = Новый HTTPСервисОтвет(200);
			Ответ.УстановитьТелоИзСтроки(Тело);
			
			Ответ.Заголовки["Content-Type"]	 = "application/json;charset=utf-8";
			Ответ.Заголовки["Cache-Control"] = "no-cache";
			
			Возврат Ответ;
			
		Исключение
			
			ЗаписьЖурналаРегистрации("GetInfoBases.JSON", УровеньЖурналаРегистрации.Ошибка,,
									,СлужебныйКлиентСервер.ПодробныйТекстОшибки(ИнформацияОбОшибке()));
			ВызватьИсключение;
			
		КонецПопытки
		
	Иначе
		
		Ответ = Новый HTTPСервисОтвет(405);	
		Возврат Ответ;
		
	КонецЕсли;
	
КонецФункции



#Область СлужебныеПроцедуры

Процедура GetInfoBases(ClientID, InfoBaseCheckCode, InfoBases, БазовыйURL, ЛогинПользователя, ИдентификаторПользователя)
	
	УстановитьПривилегированныйРежим(ИСТИНА);
		
	ТипДоступа = "rdp";
	
	ВспомогательныеФункцииСервер.ИнициализироватьВнешнийИсточник(Константы.АдресСервера.Получить());
	
	Если ЛогинПользователя <> Неопределено Тогда 
		РезультатJSON = ВнешниеИсточникиДанных.wcib_db.public_get_v8i_list_uid(ЛогинПользователя, ТипДоступа);
	Иначе
		РезультатJSON = ВнешниеИсточникиДанных.wcib_db.public_get_v8i_list_guid(ИдентификаторПользователя, ТипДоступа);
	КонецЕсли;
	
	СтруктураОтвета = СтроковыеФункцииКлиентСервер.КонвертироватьJsonВСтруктуру(РезультатJSON);
	
	InfoBaseCheckCode = СтруктураОтвета.version;
	
	Если ClientID = ПустойИдентификатор() Тогда
		ClientID = Строка(Новый УникальныйИдентификатор());
	КонецЕсли;
	
	InfoBases = ПолучитьСписокИБ(СтруктураОтвета.infobases);
	
КонецПроцедуры

Функция ПолучитьСписокИБ(ДанныеСписка) Экспорт
	
	Если ДанныеСписка = Неопределено Тогда
		ДанныеСписка = Новый Массив;	
	КонецЕсли;
	
	ЧислоИБ = ДанныеСписка.Количество(); 
	
	УстановитьПривилегированныйРежим(Истина); 
		
	//собираем в дерево
	
	//соответствие(Группа): массив(Список ИБ): структура(Элемент ИБ)

	Результат = "";	

	ИспользоватьФайл = ЧислоИБ > 1000;
	
	Если ИспользоватьФайл Тогда
		ИмяВременногоФайла = ПолучитьИмяВременногоФайла("v8i");
		ЗТ = Новый ЗаписьТекста(ИмяВременногоФайла, КодировкаТекста.UTF8);
	КонецЕсли;
	
	Для Каждого JSONСтруктураБазы Из ДанныеСписка Цикл
		
		JSONСтруктураБазы = СтрЗаменить(JSONСтруктураБазы, "\", "\\");
		
		СтруктураБазы = СтроковыеФункцииКлиентСервер.КонвертироватьJsonВСтруктуру(JSONСтруктураБазы);
		
		Группа = Новый Массив();
	
		ОписаниеИБ = Новый Структура("Наименование,Строки", СтруктураБазы.name, Новый Массив());
		СтрокиИБ = ОписаниеИБ.Строки;
	
		ConnectString = ВспомогательныеФункцииСервер.СформироватьСтрокуПодключения(СтруктураБазы);
	
		СтрокиИБ.Добавить(ConnectString);
		СтрокиИБ.Добавить("ID=" + СтруктураБазы.base_id);
		 
		СтрокиИБ.Добавить("OrderInList=" + СтруктураБазы.order_in_list);
		
		Если СтруктураБазы.app_arch <> Неопределено Тогда
			СтрокиИБ.Добавить("AppArch=" + СтруктураБазы.app_arch);
		КонецЕсли;
		
		СтрокаДополнительныхПараметров = "";
		
		Если СтруктураБазы.use_ib_autorization = Истина Тогда
			
			ИмяПользователя = СтруктураБазы.iblogin;
			Пароль = ?(ЗначениеЗаполнено(СтруктураБазы.ibpwd), СтруктураБазы.ibpwd, "");
			
			СтрокаДополнительныхПараметров = СтрокаДополнительныхПараметров + "/N " + ИмяПользователя + " ";
			СтрокаДополнительныхПараметров = СтрокаДополнительныхПараметров + "/P " + Пароль + " "; 
						
		КонецЕсли;
		
		// Авторизация на веб-сервере (для получения списка баз)
		Если  СтруктураБазы.wslogin <> Неопределено Тогда
			СтрокаДополнительныхПараметров = СтрокаДополнительныхПараметров + "/WSN " + СтруктураБазы.wslogin + " ";
			СтрокаДополнительныхПараметров = СтрокаДополнительныхПараметров + "/WSP " + СтруктураБазы.wspwd + " ";
		КонецЕсли;
		
		// Если используется прокси для WS
		Если СтруктураБазы.use_proxy = 2 Тогда
			СтрокаДополнительныхПараметров = СтрокаДополнительныхПараметров + "/Proxy ";
			СтрокаДополнительныхПараметров = СтрокаДополнительныхПараметров + "-PSrv " + СтруктураБазы.psrv + " ";
			СтрокаДополнительныхПараметров = СтрокаДополнительныхПараметров + "-PPort " + Формат(СтруктураБазы.pport, "ЧГ=") + " ";
			Если СтруктураБазы.puser <> Неопределено Тогда
				СтрокаДополнительныхПараметров = СтрокаДополнительныхПараметров + "-PUser " + СтруктураБазы.puser + " ";	
			КонецЕсли;
			Если СтруктураБазы.ppwd <> Неопределено Тогда
				СтрокаДополнительныхПараметров = СтрокаДополнительныхПараметров + "-PPwd " + СтруктураБазы.ppwd + " ";	
			КонецЕсли;
		КонецЕсли;
		
		Если СтруктураБазы.technical_specialist_mode = Истина Тогда
			СтрокаДополнительныхПараметров = СтрокаДополнительныхПараметров + "/TechnicalSpecialistMode ";	
		КонецЕсли;
		
		Если СтруктураБазы.main_window_mode <> Неопределено Тогда
			СтрокаДополнительныхПараметров = СтрокаДополнительныхПараметров + "/MainWindowMode " + СтруктураБазы.main_window_mode + " ";	
		КонецЕсли;
		
		Если СтруктураБазы.clear_cache = Истина Тогда
			СтрокаДополнительныхПараметров = СтрокаДополнительныхПараметров + "/ClearCache ";	
		КонецЕсли;

		Если СтруктураБазы.update_ib = Истина Тогда
			СтрокаДополнительныхПараметров = СтрокаДополнительныхПараметров + "/C ЗапуститьОбновлениеИнформационнойБазы";
		КонецЕсли;
		
		Если Не ПустаяСтрока(СтрокаДополнительныхПараметров) Тогда
			СтрокиИБ.Добавить("AdditionalParameters=" + СтрокаДополнительныхПараметров);
		КонецЕсли;
		
		Группа.Добавить(ОписаниеИБ);
	
		//рендерим дерево в v8i
		//если дерево больше 1000, используем файл как буфер, потому что конкатенация длинных строк в платформе работает медленно
	
		Для Каждого ОписаниеИБ из Группа Цикл
			Если ИспользоватьФайл Тогда
				ЗТ.ЗаписатьСтроку("[" + ОписаниеИБ.Наименование + "]");
			Иначе
				Результат = Результат + "[" + ОписаниеИБ.Наименование + "]" + Символы.ПС;
			КонецЕсли;
			Для Каждого СтрокаИБ из ОписаниеИБ.Строки Цикл
				Если ИспользоватьФайл Тогда
					ЗТ.ЗаписатьСтроку(СтрокаИБ);
				Иначе
					Результат = Результат + СтрокаИБ + Символы.ПС;
				КонецЕсли;
			КонецЦикла;
		КонецЦикла;
	КонецЦикла;
	
	Если ИспользоватьФайл Тогда
		ЗТ.Закрыть();
		ЧТ = новый ЧтениеТекста(ИмяВременногоФайла, КодировкаТекста.UTF8);
		Результат = ЧТ.Прочитать();
		ЧТ.Закрыть();
		УдалитьФайлы(ИмяВременногоФайла);
	КонецЕсли;
		
	Возврат Результат;
	
КонецФункции

Функция ПустойИдентификатор()
	Возврат "00000000-0000-0000-0000-000000000000";
КонецФункции

#КонецОбласти

 

wcib json 1cestart http InternetService

См. также

SALE! 20%

Infostart Toolkit: Инструменты разработчика 1С 8.3 на управляемых формах

Инструментарий разработчика Роли и права Запросы СКД Платформа 1С v8.3 Управляемые формы Запросы Система компоновки данных Конфигурации 1cv8 Платные (руб)

Набор инструментов программиста и специалиста 1С для всех конфигураций на управляемых формах. В состав входят инструменты: Консоль запросов, Консоль СКД, Консоль кода, Редактор объекта, Анализ прав доступа, Метаданные, Поиск ссылок, Сравнение объектов, Все функции, Подписки на события и др. Редактор запросов и кода с раскраской и контекстной подсказкой. Доработанный конструктор запросов тонкого клиента. Продукт хорошо оптимизирован и обладает самым широким функционалом среди всех инструментов, представленных на рынке.

13000 10400 руб.

02.09.2020    121608    670    389    

711

SALE! 25%

Infostart PrintWizard

Пакетная печать Печатные формы Инструментарий разработчика Платформа 1С v8.3 Запросы 1С:Зарплата и кадры бюджетного учреждения 1С:Конвертация данных 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 Платные (руб)

Инструмент, позволяющий абсолютно по-новому взглянуть на процесс разработки печатных форм. Благодаря конструктору можно значительно снизить затраты времени на разработку печатных форм, повысить качество и "прозрачность" разработки, а также навести порядок в многообразии корпоративных печатных форм.

18000 15300 руб.

06.10.2023    7262    21    6    

39

Интеграция Альфа Авто 5 / Альфа Авто 6 и AUTOCRM / Инфотек

Сайты и интернет-магазины WEB-интеграция Платформа 1С v8.3 Конфигурации 1cv8 1С:Управление торговлей 11 Автомобили, автосервисы Россия Управленческий учет Платные (руб)

Интеграционный модуль обмена между конфигурацией Альфа Авто 5 и Альфа Авто 6 и порталом AUTOCRM. Данный модуль универсален. Позволяет работать с несколькими обменами AUTOCRM разных брендов в одной информационной базе в ручном и автоматическом режиме. Без существенных изменений типовой конфигурации. Проверено с брендами: Интеграция 1С и GEELY Интеграция 1С и HAVAL Интеграция 1С и KIA Интеграция 1С и FORD Интеграция 1С и LADA ГАРАНТИЯ 100% ВНЕДРЕНИЯ!

36000 руб.

03.08.2020    15729    10    17    

11

SALE! 20%

Infostart УДиФ: Управление данными и формами

Инструменты администратора БД Инструментарий разработчика Роли и права Платформа 1С v8.3 Конфигурации 1cv8 Россия Платные (руб)

Расширение позволяет без изменения кода конфигурации выполнять проверки при вводе данных, скрывать от пользователя недоступные ему данные, выполнять код в обработчиках. Не изменяет данные конфигурации, легко устанавливается практически на любую конфигурацию на управляемых формах.

10000 8000 руб.

10.11.2023    3506    11    1    

33

SALE! 30%

PowerTools

Инструментарий разработчика Инструменты администратора БД Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Россия Платные (руб)

Универсальный инструмент программиста для администрирования конфигураций. Сборник наиболее часто используемых обработок под единым интерфейсом.

3600 2520 руб.

14.01.2013    177726    1073    0    

849
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. Vhett 23.05.23 11:58 Сейчас в теме
Такой вопрос: если авторизация по ОС, то сможем ли через http получить имя учётки клиента, откуда запускается запрос?
P.S. Пробовал через web сделать, но вместо учётки клиента, возвращал мне учётку сервера.
P.S.S Так же заметил что у одного и того же компьютера, может меняться идентификатор. Потому программа дублирует постоянно одного и того же пользователя. С такой ситуацией не сталкивались?
2. areafiftyone 15.09.23 17:37 Сейчас в теме
Непонятно, что это за внешние источники? Откуда берутся базы данных?
3. ogursoft 07.03.24 14:32 Сейчас в теме
А как выглядит готовый json со списком баз?
Оставьте свое сообщение