Чтение данных из SharePoint в 1С

03.08.22

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

Рассмотрим задачу по одностороннему обмену между 1С и MS SharePoint. Суть задачи - забирать данные из определенных таблиц в MS SharePoint и загрузить их в 1С. В данной статье будет продемонстрирована загрузка из таблицы AssignmentTimephasedDataSet.

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование По подписке [?] Купить один файл
Чтение данных из SharePoint в 1С
.epf 11,59Kb
15
15 Скачать (1 SM) Купить за 1 850 руб.

- Предисловие

          - Авторизация

                      1. Токен от Майкрософт

                      2. Куки от сервера SP

                      3. Токен от сервера SP

          - Чтение данных

          - Дополнительно

 

Предисловие

   Рассмотрим задачу по одностороннему обмену между 1С и MS SharePoint. Суть задачи - забирать данные из определенных таблиц в MS SharePoint и загрузить их в 1С.  В данной статье будет продемонстрирована загрузка из таблицы AssignmentTimephasedDataSet.  

   В результате долгих поисков были найдены 3 способа прочитать данные из MS SharePoint. Для 2 из 3 найденных способов требовались определенные настройки на стороне MS SharePoint (Далее SP). Не буду углубляться в подробности, скажу лишь, что технических специалистов на стороне SP не было, чтобы выполнить настройку, пришлось работать с тем, что есть. Речь в статье пойдет про 3 способ, который позволяет получить информацию из любой таблицы с указанием конкретных отборов, через GET запросы.

 Авторизация

   Итак, чтобы прочитать информацию из SP, мы должны сначала авторизоваться. Здесь есть нюанс, у вас должны быть права на программную работу с SP. Например, я мог просматривать данные в SP через браузер, но при попытке программного вызова сваливалась ошибка с сообщением о несанкционированном доступе. После того как права мне расширили, начинается самое интересное - процесс авторизации. Пришлось штудировать Stack Overflow и десятки других сайтов и проецировать решения, предложенные там, сначала в Postman, а затем и в 1С. Алгоритм, представленный в сети, конкретно в моем случае не работал, и мне пришлось внести в него корректировки. Готовый алгоритм авторизации представлен ниже.

 

        1. Итак, самое первое, что нам необходимо сделать - это авторизоваться в Майкрософт, выполнив POST запрос:

&НаСервере
Функция ТокенМайкрсофота()
	
	ТексЗапроса = РеквизитФормыВЗначение("Объект").ПолучитьМакет("ЗапросДляТокена").ПолучитьТекст();	
	
	ТексЗапроса = СтрЗаменить(ТексЗапроса, "[Логин]", 	Логин);
	ТексЗапроса = СтрЗаменить(ТексЗапроса, "[Пароль]", 	Пароль);
	ТексЗапроса = СтрЗаменить(ТексЗапроса, "[Домен]", 	Домен);
	
	ЗаголовкиHTTPЗапрос = Новый Соответствие;
	ЗаголовкиHTTPЗапрос.Вставить("Accept", "application/json; odata=verbose"); 
 
	HTTPЗапрос = Новый HTTPЗапрос("/extSTS.srf", ЗаголовкиHTTPЗапрос);  	   
	HTTPЗапрос.УстановитьТелоИзСтроки(ТексЗапроса, "UTF-8", ИспользованиеByteOrderMark.НеИспользовать); 
	
	HTTPСоединение 		= Новый HTTPСоединение("login.microsoftonline.com",,,,,, Новый ЗащищенноеСоединениеOpenSSL); 	
	HTTPОтвет 		= HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
	
	ДанныеОтветаСтрокой = HTTPОтвет.ПолучитьТелоКакСтроку();
	
	ТекстНачало ="xmlns:wsse=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"">";  
	
	НачалоТекста = Найти(ДанныеОтветаСтрокой, ТекстНачало);
	Если НачалоТекста = 0 Тогда 
		Возврат "";
	КонецЕсли;    
	
	НачалоТекста = НачалоТекста + СтрДлина(ТекстНачало);
	ТекстКонец = "</wsse:BinarySecurityToken>";
	КонецТекста = Найти(ДанныеОтветаСтрокой, ТекстКонец);
	Если КонецТекста = 0 Тогда 
		Возврат "";
	КонецЕсли;     
	
	Возврат Сред(ДанныеОтветаСтрокой, НачалоТекста, КонецТекста - НачалоТекста);
	
КонецФункции

               В результате мы получим токен доступа нашей учетной записи в Майкрософт. 

 

 

         2.Далее с этим токеном доступа мы стучимся на сайт SP.     

&НаСервере
Функция КукиСервераSP()
	
	ЗаголовкиHTTPЗапрос = Новый Соответствие();                 
	ЗаголовкиHTTPЗапрос.Вставить("Content-Type", 	"text/plain");	
	ЗаголовкиHTTPЗапрос.Вставить("Cookie", 		BinarySecurityToken);
	
	HTTPЗапрос = Новый HTTPЗапрос("/_forms/default.aspx?wa=wsignin1.0", ЗаголовкиHTTPЗапрос);  	   
	HTTPЗапрос.УстановитьТелоИзСтроки(BinarySecurityToken, "UTF-8", ИспользованиеByteOrderMark.НеИспользовать);
	
	HTTPСоединение 	= Новый HTTPСоединение(СерверSP(),,,,,, Новый ЗащищенноеСоединениеOpenSSL); 	
	HTTPОтвет 	= HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
	
	КукиЗаголовка = HTTPОтвет.Заголовки.Получить("Set-Cookie");
	
	НачалоСтроки 	= ", SIMI=";	
	КонецСтроки 	= "domain=sharepoint.com; path=/; SameSite=None; secure, ";  
	
	Подстрока 	= ВыбратьПодСтроку(КукиЗаголовка, НачалоСтроки, КонецСтроки);  
	
	СтрокаДляУдаления = СтрШаблон("%1%2%3", НачалоСтроки, Подстрока, КонецСтроки); 
	
	Возврат СтрЗаменить(КукиЗаголовка, СтрокаДляУдаления, ";");
	
КонецФункции  

    

               В результате мы получаем Cookie от сервера SP, который нам потребуется для дальнейшей работы с таблицами.

 

 

      3. Далее с этим куки мы стучимся еще по одному URL на сайте SP.

&НаСервере
Функция ТокенСервераSP()   
		
	Заголовки = Новый Соответствие();        
	Заголовки.Вставить("Content-Type", 					"text/xml; charset=utf-8");      
	Заголовки.Вставить("Cookie", 						Cookie);
	
	HTTpЗапрос = Новый HTTPЗапрос("/sites/pwa/_api/contextinfo", Заголовки);
	Соединение = Новый HTTPСоединение(СерверSP(),,,,,, Новый ЗащищенноеСоединениеOpenSSL);		
	HTTPОтвет  = Соединение.ОтправитьДляОбработки(HTTpЗапрос);     
	
	ДанныеОтветаСтрокой = HTTPОтвет.ПолучитьТелоКакСтроку(); 
	
	ТекстНачало = "<d:FormDigestValue>";  
	
	НачалоТекста = Найти(ДанныеОтветаСтрокой, ТекстНачало);
	Если НачалоТекста = 0 Тогда 
		Возврат "";
	КонецЕсли; 
	
	НачалоТекста = НачалоТекста + СтрДлина(ТекстНачало);
	ТекстКонец = "</d:FormDigestValue>";
	КонецТекста = Найти(ДанныеОтветаСтрокой, ТекстКонец);
	Если КонецТекста = 0 Тогда 
		Сообщить("В HTTPОтвет не удалось найти конец FormDigestValue");
		Возврат "";
	КонецЕсли; 
	
	Возврат Сред(ДанныеОтветаСтрокой, НачалоТекста, КонецТекста - НачалоТекста);

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

               Здесь мы получаем токен от сервера SP, который обрамлён в теги FormDigestValue

 

 

               В итоге у нас имеются куки и токен (FormDigestValue) для программной авторизации на сайте SP. Эти данные живут некоторое время, если вдруг данных из таблиц перестали считываться, вероятнее всего, нужно обновить параметры авторизации.

 

Чтение данных

   Переходим к чтению данных. При считывании из таблиц существует ограничение на количество возвращаемых строк. Оно может быть любым в зависимости от настроек конкретно в вашей организации. В моем случае ограничение на таблице AssignmentTimephasedDataSet составило 2000 строк. В таблице Projects ограничение составило 500 строк.

   Нам изначально требуется узнать общее количество строк в таблице. Это делается при помощи $count?. Например, количество записей за выбранный период составило 10000. Итого мы сможем за 5 обращений к таблице прочитать всю информацию.

   На каждом витке цикла мы пропускаем указанное количество строк и начинаем загрузку со следующей строки. Пропустить ненужные строки можно при помощи $skip.

&НаСервере
Процедура ВыполнитьЧтениеДанных()
	
	ТаблицаДанных.Очистить();      
	
	//Логика аналогичная запросу "С - ПО"
	ОтборПоПериоду = СтрШаблон("&$filter=TimeByDay ge datetime'%1' and TimeByDay lt datetime'%2'",
								Формат(Период.ДатаНачала, "ДФ=yyyy-MM-ddT00:00:00"),  Формат(Период.ДатаОкончания, "ДФ=yyyy-MM-ddT23:59:59")); 
								
	//$count? -  используется чтобы получить общее количество строк в таблице по указанному отбору	
	СервисКоличестваЗаписейВтаблице	= СтрШаблон("/sites/pwa/_api/ProjectData/[en-us]/AssignmentTimephasedDataSet()/$count?%1", ОтборПоПериоду);
	КоличествоЗаписейВтаблице 	= КоличествоСтрокВТаблице(СервисКоличестваЗаписейВтаблице);    
	КоличествоПрочитанныхСтрок	= 0;
	КоличествоИтераций 		= КоличествоЗаписейВтаблице/2000;         
	НомерСтроки 			= 1;
	
	Заголовки = Новый Соответствие();        
	Заголовки.Вставить("Content-Type", 	"text/xml; charset=utf-8");      
	Заголовки.Вставить("Cookie", 		Cookie);												
	Заголовки.Вставить("X-RequestDigest", 	FormDigestValue);                                       
	
	Соединение = Новый HTTPСоединение(СерверSP(),,,,,, Новый ЗащищенноеСоединениеOpenSSL); 
	
	ЧитаемыеКолонки	= "AssignmentId,TimeByDay,TaskName";   
	
	Пока КоличествоИтераций > 0 Цикл 

		//$skip - используется чтобы пропустить указанное количество строк в таблице
		Фильтр			= ?(КоличествоПрочитанныхСтрок = 0, "", СтрШаблон("&$skip=%1", Формат(КоличествоПрочитанныхСтрок, "ЧГ=0")));		
		СервисПолученияДанных 	= СтрШаблон("/sites/pwa/_api/ProjectData/[en-us]/AssignmentTimephasedDataSet?$select=%1%2%3", ЧитаемыеКолонки, ОтборПоПериоду, Фильтр);	
		
		HTTpЗапрос 			= Новый HTTPЗапрос(СервисПолученияДанных, Заголовки);	
		HTTPОтветПозадачам 		= Соединение.Получить(HTTpЗапрос);
		
		ПрочитатьОтветПоЗадачам(HTTPОтветПозадачам.ПолучитьТелоКакСтроку(), НомерСтроки); 
		
		КоличествоИтераций 		= КоличествоИтераций - 1;  		
		КоличествоПрочитанныхСтрок 	= КоличествоПрочитанныхСтрок + 2000;
		
	КонецЦикла;	     
		
КонецПроцедуры

      При считывании мы получаем данные в XML формате. Парсим и загружаем в 1С

 

Дополнительно

 

     Текст запроса из макета "ЗапросДляТокена":

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
      xmlns:a="http://www.w3.org/2005/08/addressing"
      xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
  <s:Header>
    <a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action>
    <a:ReplyTo>
      <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
    </a:ReplyTo>
    <a:To s:mustUnderstand="1">https://login.microsoftonline.com/extSTS.srf</a:To>
    <o:Security s:mustUnderstand="1"
       xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <o:UsernameToken>
        <o:Username>[Логин]</o:Username>
        <o:Password>[Пароль]</o:Password>
      </o:UsernameToken>
    </o:Security>
  </s:Header>
  <s:Body>
    <t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
      <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
        <a:EndpointReference>
          <a:Address>https://[Домен].sharepoint.com/</a:Address>
        </a:EndpointReference>
      </wsp:AppliesTo>
      <t:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</t:KeyType>
      <t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
      <t:TokenType>urn:oasis:names:tc:SAML:1.0:assertion</t:TokenType>
    </t:RequestSecurityToken>
  </s:Body>
</s:Envelope>

P.s.  

 -  Повторяющийся код по вызову http методов, созданию запросов и т.д. специально не стал делать универсальными для большей наглядности.

1сИSharePoint api ЗагрузкаИзSharepoint авторизацияВSharePoint apisharepoint ПрочитатьТаблицыИзSharePoint РаботаСSharePoint httpЗапросКSharePoint Интеграция1С вебапиSharePoint вебапиСшарапоинт 1сишарапоинт прочитатьтаблицыизшарапоинт интеграция1сишарапоинт программнаяавторизациявшарапоинт Интеграция1СИSharePoint Интеграция1сишарапоинт

См. также

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

Интеграционный модуль обмена между конфигурацией Альфа Авто 5 и Альфа Авто 6 и порталом AUTOCRM. Данный модуль универсален. Позволяет работать с несколькими обменами AUTOCRM разных брендов в одной информационной базе в ручном и автоматическом режиме.

36000 руб.

03.08.2020    17783    19    22    

16

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

Интеграция 1С и Битрикс 24. Разработка имеет двухстороннюю синхронизацию 1С и Bitrix24 задачами. Решение позволяет создавать пользователя в 1С из Битрикс24 и наоборот. Данная разработка технически подходит под все основные конфигурации линейки продуктов 1С:Предприятие 8.3 (платформа начиная с 8.3.23). При приобретении предоставляется 1 месяц бесплатных обновлений разработки. Доступна демо-версия продукта с подключением Вашего Битрикс24

5040 руб.

04.05.2021    19849    13    17    

16

WEB-интеграция 8.3.8 Конфигурации 1cv8 Автомобили, автосервисы Беларусь Украина Россия Казахстан Управленческий учет Платные (руб)

Расширение предназначено для конфигурации "1С:Предприятие 8. Управление Автотранспортом. ПРОФ". Функционал модуля: 1. Заполнение регистров сведений по подсистеме "Мониторинг", а именно: события по мониторингу, координаты по мониторингу, пробег и расход по мониторингу, текущее местоположение ТС по мониторингу 2. Заполнение путевого листа: пробег по мониторингу, время выезда/заезда, табличная часть ГСМ, места стоянок по геозонам. 3. Отчеты по данным загруженным в регистры сведений. 4. Предусмотрена автоматическая загрузка данных в фоновом режиме (условия работы данной загрузке читайте в описании товара) Модуль работает без включенной константы по настройкам мониторинга. Модуль формы предоставляется с открытым кодом, общий модуль защищен. Любой заинтересованный пользователь, имеет возможность скачать демо-версию расширения.

22656 руб.

25.05.2021    14424    42    8    

18

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

Расширение значительно упрощает написание API на 1С. Веб программисты получают простой и понятный доступ к 1С. Описание API создаётся автоматически и представляется в виде удобном как для человека, так и для программной обработки.

24000 руб.

27.09.2024    1172    1    0    

3
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Max89 21.06.23 07:34 Сейчас в теме
Приобрел вашу обработку, но она не получает FormDigestValue. В ответ на запрос приходит ошибка 404
2. avaddon1988 06.10.23 01:08 Сейчас в теме
(1) Доброго дня.
Обработку не скачивал, недостающие запросы искал сам и писал по этой статье - FormDigestValue получает, только необходимо заменить строку "/sites/pwa/_api/contextinfo" на "/_api/contextinfo".
Прикрепленные файлы:
3. user1718284 17.01.24 11:53 Сейчас в теме
Чтобы выгрузить файл чуть поменял ваш код:
&НаСервере
Функция ТокенСервераSP()   
		
	Заголовки = Новый Соответствие();        
	Заголовки.Вставить("Content-Type", 					"text/xml; charset=utf-8");      
	Заголовки.Вставить("Cookie", 						Cookie);
	
	//HTTpЗапрос = Новый HTTPЗапрос(СокрЛП(DirectoryName)+"/_api/contextinfo", Заголовки);
	HTTpЗапрос = Новый HTTPЗапрос("_api/contextinfo", Заголовки);
	Соединение = Новый HTTPСоединение(СерверSP(),,,,,, Новый ЗащищенноеСоединениеOpenSSL);		
	HTTPОтвет  = Соединение.ОтправитьДляОбработки(HTTpЗапрос);     
	
	ДанныеОтветаСтрокой = HTTPОтвет.ПолучитьТелоКакСтроку(); 
	
	ТекстНачало = "<d:FormDigestValue>";  
	
	НачалоТекста = Найти(ДанныеОтветаСтрокой, ТекстНачало);
	Если НачалоТекста = 0 Тогда 
		Возврат "";
	КонецЕсли; 
	
	НачалоТекста = НачалоТекста + СтрДлина(ТекстНачало);
	ТекстКонец = "</d:FormDigestValue>";
	КонецТекста = Найти(ДанныеОтветаСтрокой, ТекстКонец);
	Если КонецТекста = 0 Тогда 
		Сообщить("В HTTPОтвет не удалось найти конец FormDigestValue");
		Возврат "";
	КонецЕсли; 
	
	Возврат Сред(ДанныеОтветаСтрокой, НачалоТекста, КонецТекста - НачалоТекста);

КонецФункции
Показать


Сработала такая конструкция:

&НаСервере
Процедура ВыполнитьЧтениеДанных(СтруктураРеквизитовФормы)
	     	
	Заголовки = Новый Соответствие();        
	Заголовки.Вставить("Cookie", 			Cookie);

	Сервис = СокрЛП(DirectoryName)+"/_api/web/GetFileByServerRelativeUrl('"+СокрЛП(DirectoryName)+СокрЛП(FolderName)+"/"+Files+"')/$value";
	Соединение 			= Новый HTTPСоединение(СерверSP(),,,,,, Новый ЗащищенноеСоединениеOpenSSL);  	
	HTTpЗапрос 			= Новый HTTPЗапрос(Сервис, Заголовки);		
	HTTPОтвет 	= Соединение.Получить(HTTpЗапрос);
	
	Ответ = HTTPОтвет.ПолучитьТелоКакСтроку();	 
Показать
4. user1718284 17.01.24 11:57 Сейчас в теме
5. user1718284 04.07.24 12:27 Сейчас в теме
При отправке файла нужен X-RequestDigest toker на директорию

&НаСервере
Функция ТокенСервераSP()   
		
	Заголовки = Новый Соответствие();        
	Заголовки.Вставить("Content-Type", 					"text/xml; charset=utf-8");      
	Заголовки.Вставить("Cookie", 						Cookie);
	
	HTTpЗапрос = Новый HTTPЗапрос(СокрЛП(DirectoryName)+"/_api/contextinfo", Заголовки);
	//HTTpЗапрос = Новый HTTPЗапрос("_api/contextinfo", Заголовки);
	Соединение = Новый HTTPСоединение(СерверSP(),,,,,, Новый ЗащищенноеСоединениеOpenSSL);		
	HTTPОтвет  = Соединение.ОтправитьДляОбработки(HTTpЗапрос);     
	
	ДанныеОтветаСтрокой = HTTPОтвет.ПолучитьТелоКакСтроку(); 
	
	ТекстНачало = "<d:FormDigestValue>";  
	
	НачалоТекста = Найти(ДанныеОтветаСтрокой, ТекстНачало);
	Если НачалоТекста = 0 Тогда 
		Возврат "";
	КонецЕсли; 
	
	НачалоТекста = НачалоТекста + СтрДлина(ТекстНачало);
	ТекстКонец = "</d:FormDigestValue>";
	КонецТекста = Найти(ДанныеОтветаСтрокой, ТекстКонец);
	Если КонецТекста = 0 Тогда 
		Сообщить("В HTTPОтвет не удалось найти конец FormDigestValue");
		Возврат "";
	КонецЕсли; 
	
	Возврат Сред(ДанныеОтветаСтрокой, НачалоТекста, КонецТекста - НачалоТекста);

КонецФункции
Показать



Пример отправки файла:

	ФайлЗапроса = ПолучитьИмяВременногоФайла("txt");
	ТекстовыйФайл = Новый ТекстовыйДокумент;
	ТекстовыйФайл.УстановитьТекст("777");          
	ТекстовыйФайл.Записать(ФайлЗапроса, КодировкаТекста.ANSI); 
	
	ФайлОтправки = Новый Файл(ФайлЗапроса);
	РазмерФайлаОтправки = XMLСтрока(ФайлОтправки.Размер());
	
	ИмяФайла1 = "test.txt";          
	
	Заголовки = Новый Соответствие();        
	Заголовки.Вставить("Cookie", 			Cookie);
	Заголовки.Вставить("Content-Length", РазмерФайлаОтправки);
	Заголовки.Вставить("X-RequestDigest", FormDigestValue);
	//Заголовки.Вставить("Content-Type", "text/plain;charset=UTF-8");
	
	Сервис = СокрЛП(DirectoryName)+"/_api/web/GetFolderByServerRelativeUrl('"+СокрЛП(DirectoryName)+СокрЛП(FolderName)+"')/Files/Add(url='"+ИмяФайла1+"',overwrite=true)";
	Соединение 			= Новый HTTPСоединение(СерверSP(),,,,,, Новый ЗащищенноеСоединениеOpenSSL);  	 	
	HTTpЗапрос 			= Новый HTTPЗапрос(Сервис, Заголовки);		
	
	HTTPЗапрос.УстановитьИмяФайлаТела(ФайлЗапроса);	
	
	ИмяФайлаОтвета = ПолучитьИмяВременногоФайла();
	
	ОтветHTTP = Соединение.ОтправитьДляОбработки(HTTpЗапрос, ИмяФайлаОтвета);      
	Код = ОтветHTTP.КодСостояния;
	
	Сообщить(Код);
	
	УдалитьВременныйФайл(ИмяФайлаОтвета);
	УдалитьВременныйФайл(ФайлЗапроса);
Показать
Оставьте свое сообщение