Содержание
Disclaimer: Статей на эту тему написано очень много и, как вы, конечно, догадались, это очередная. Возможно, вы узнаете из неё что-то новое, но ничего сверхсекретного, что нельзя было бы нагуглить самостоятельно, здесь не описано. Только заметки из личного опыта.
Вступление
Рассматривать будем только ситуацию, когда есть сторонний web-сервис и стоит задача наладить обмен данными.
Строение сервиса описывается в файле WSDL (англ. Web Services Description Language)
Файл чаще всего доступен по ссылке, где находится точка входа в сам web-сервис. Я написал «чаще всего», так как бывают исключения. Например, Web-сервис на базе SAP не публикует wsdl и его можно получить только выгрузив из самого приложения.
И так, у нас есть описание web-сервиса, логин, пароль. Давайте подключимся.
// Определяем настройки URLПространстваИменСервиса = «http://Somesite.ru»; ИмяПользователя = «TestUser»; Пароль = «q1w2e3»; МестоположениеWSDL = «https://Somesite.ru/WebService/Some?wsdl»; ИмяСервиса = «SomeServiceName»; ИмяТочкиПодключения = «SomeService_Port»; // Создаем подключение SSL = Новый ЗащищенноеСоединениеOpenSSL(); WSОпределение = Новый WSОпределения(МестоположениеWSDL,,,,,SSL); WSПрокси = Новый WSПрокси(WSОпределение, URLПространстваИменСервиса, ИмяСервиса, ИмяТочкиПодключения,,,SSL); WSПрокси.Пользователь = ИмяПользователя; WSПрокси.Пароль = Пароль;
Отлично! Мы подключились к web-сервису! По идее это основа любого варианта обмена, так как позволяет создавать объект структуры данных на основании wsdl, а работать с таким объектом одно удовольствие.
Рассмотрим XML который нам выдает SoapUI
<soapenv:Envelope xmlns:soapenv=»http://schemas.xmlsoap.org/soap/envelope/» xmlns:som=»http://Somesite.ru»> <soapenv:Header/> <soapenv:Body> <som:SUBMISSION> <som:ID>357</som:ID> <som:CUSTOMER> <som:CLIENT_ID>121212</som:CLIENT_ID> <som:SEX>M</som:SEX> <som:CLIENT_BIRTHDAY>19900111</som:CLIENT_BIRTHDAY> <som:CARS> <som:CLASS>Mercedes</som:CLASS> <som:MODEL>GLS</som:MODEL> </som:CARS> <som:CARS> <som:CLASS>Audi</som:CLASS> <som:MODEL>TT</som:MODEL> </som:CARS> </som:CUSTOMER> </som:SUBMISSION> </soapenv:Body> </soapenv:Envelope>
Теперь опишем его программно
// Создаем объект и наполняем его данными СвояФабрикаXDTO = WSОпределение.ФабрикаXDTO; КорневойТип = СвояФабрикаXDTO.Тип(URLПространстваИменСервиса, «SUBMISSION»); КорневойОбъект = СвояФабрикаXDTO.Создать(КорневойТип); КорневойОбъект.ID = «4356»; КлиентТип = СвояФабрикаXDTO.Тип(URLПространстваИменСервиса, «CUSTOMER»); КлиентОбъект = СвояФабрикаXDTO.Создать(КлиентТип); КлиентОбъект.CLIENT_ID = «121212»; КлиентОбъект.SEX = «M»; // F — женский, M — мужской КлиентОбъект.CLIENT_BIRTHDAY = «19900111»; // Автомобили клиента АвтоТип = СвояФабрикаXDTO.Тип(URLПространстваИменСервиса, «CARS»); АвтоОбъект = СвояФабрикаXDTO.Создать(АвтоТип); АвтоОбъект.CLASS = «Mercedes»; АвтоОбъект.MODEL = «GLS»; КлиентОбъект.CARS.Добавить(АвтоОбъект); АвтоОбъект = СвояФабрикаXDTO.Создать(АвтоТип); АвтоОбъект.CLASS = «Audi»; АвтоОбъект.MODEL = «TT»; КлиентОбъект.CARS.Добавить(АвтоОбъект); КорневойОбъект.CUSTOMER.Добавить(КлиентОбъект);
Данные успешно заполнены. Теперь нужно их отправить.
В этот самый момент и возникает множество нюансов. Попробуем рассмотреть каждый.
Рецепт 1. Отправляем XDTO-объект целиком
Результат = WSПрокси.AddCustomers(КорневойОбъект);
Остается лишь обработать результат, который нам вернул сервис и на этом всё. Согласитесь, что это очень удобно!
Но на практике не всегда бывает так. Например 1с не ладит с префиксацией определенных тэгов внутри xml, когда пространство имен корнеового тэга отличается от пространства дочерних. В таких случаях приходится собирать soap вручную. Так же приходилось сталкиваться с web-сервисами, которые в качестве параметра ждут xml в чистом виде. Маразм, но все же делается это не слишком сложно.
Рецепт 2. Отправляем чистый xml в качестве параметра
ПараметрыЗаписиXML = Новый ПараметрыЗаписиXML(«UTF-8», «1.0», Истина); МойXML = Новый ЗаписьXML; МойXML.УстановитьСтроку(ПараметрыЗаписиXML); МойXML.ЗаписатьОбъявлениеXML(); СвояФабрикаXDTO.ЗаписатьXML(МойXML, КорневойОбъект); СтрокаXML = МойXML.Закрыть(); Если УдалитьОписаниеПространстваИмен Тогда Попытка ПервыйТэгВСтроке = СтрПолучитьСтроку(СтрокаXML,2); ИмяКорневогоТэга = КорневойОбъект.Тип().Имя; СтрокаXML = СтрЗаменить(СтрокаXML, ПервыйТэгВСтроке, «<«+ИмяКорневогоТэга+»>»); Исключение //ОписаниеОшибки() КонецПопытки; КонецЕсли; Результат = WSПрокси.AddCustomers(СтрокаXML);
Если не удалять пространство имен, которое 1с добавляет по умолчанию, то стало больше всего на 5 строк кода. Чаще всего я заворачиваю преобразование xml в функцию, так как обычно вызываем более одного метода.
Рецепт 3. Отправляем через нативный HTTPЗапрос.
СтрокаSOAP = «<soapenv:Envelope xmlns:soapenv=»»http://schemas.xmlsoap.org/soap/envelope/»» xmlns=»»http://Somesite.ru»»> | <soapenv:Header/> | <soapenv:Body> |» +СтрокаXML+ » | </soapenv:Body> |</soapenv:Envelope>»; // Описываем заголовки HTTP-запроса Заголовки = Новый Соответствие; Заголовки.Вставить(«Content-Type», «text/xml;charset=UTF-8»); Заголовки.Вставить(«SOAPAction», «http://sap.com/xi/WebService/soap1.1»); Заголовки.Вставить(«Authorization», «Basic «+ПолучитьBase64ЗаголовокАвторизации(ИмяПользователя, Пароль)); // ВНИМАНИЕ!!! // Нельзя заполнять программно следующие заголовки, так как это приводит к ошибке // Платформа сама правильно их заполнит //Заголовки.Вставить(«Accept-Encoding», «gzip,deflate»); //Заголовки.Вставить(«Content-Length», Формат(СтрДлина(СтрокаSOAP),»ЧГ=»)); // длина сообщения //Заголовки.Вставить(«Host», «Somesite.ru:8001»); //Заголовки.Вставить(«Connection», «Keep-Alive»); //Заголовки.Вставить(«User-Agent», «Apache-HttpClient/4.1.1 (java 1.5)»); // Подключаемся к сайту. Соединение = Новый HTTPСоединение(«Somesite.ru/WebService/Some»,,ИмяПользователя, Пароль,,,SSL, Ложь); // Адрес должен быть без https:// // Получаем текст корневой страницы через POST-запрос. HTTPЗапрос = Новый HTTPЗапрос(«/GetCustomer», Заголовки); HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаSOAP); Результат = Соединение.ВызватьHTTPМетод(«POST», HTTPЗапрос);
В этом варианте нам придется собрать soap вручную. По сути мы просто оборачиваем xml из рецепта 2 в оболочку soap, где в зависимости от требований web-сервиса мы можем менять наш soap как душе угодно.
Далее описываем заголовки согласно документации. Некоторые сервисы спокойно прожуют наш запрос и без заголовков, тут надо смотреть конкретный случай. Если вы не знаете какие заголовки прописывать, то самый простой способ это подглядеть запрос в SoapUI переключившись во вкладку RAW.
Функция получения Base64 строки выглядит так (подсмотрел ):
Функция ПолучитьBase64ЗаголовокАвторизации(ИмяПользователя, Пароль) КодировкаФайла = КодировкаТекста.UTF8; ВременныйФайл = ПолучитьИмяВременногоФайла(); Запись = Новый ЗаписьТекста(ВременныйФайл, КодировкаФайла); Запись.Записать(ИмяПользователя+»:»+Пароль); Запись.Закрыть(); ДвДанные = Новый ДвоичныеДанные(ВременныйФайл); Результат = Base64Строка(ДвДанные); УдалитьФайлы(ВременныйФайл); Результат = Сред(Результат,5); Возврат Результат; КонецФункции
Есть важный момент. При работе с HTTPСоединение указывайте адрес без указания протоколов «http://» и «https://», иначе рискуете потратить время на поиск не очевидной ошибки.
Рецепт 4. Отправляем через WinHttpRequest
WinHttp = Новый COMОбъект(«WinHttp.WinHttpRequest.5.1″); WinHttp.Option(2,»UTF-8»); WinHttp.Option(4, 13056); //intSslErrorIgnoreFlag WinHttp.Option(6, true); //blnEnableRedirects WinHttp.Option(12, true); //blnEnableHttpsToHttpRedirects WinHttp.Open(«POST», «https://Somesite.ru/WebService/Some/GetCustomer», 0); WinHttp.SetRequestHeader(«Content-type», «text/xml»); WinHttp.SetCredentials(ИмяПользователя, Пароль, 0); WinHttp.Send(СтрокаSOAP); WinHttp.WaitForResponse(15); XMLОтвет = WinHttp.ResponseText();
Здесь по сути тоже самое, что и в предыдущем варианте, но работаем с COMОбъектом. Строку соединения указываем полностью, вместе с протоколом. Особое внимание следует уделить только флагам игнорирования ошибок SSL-сертификатов. Они нужны, если мы работаем по SSL, но без определенного сертификата, так как создать новое защищенное соединение в таком варианте не предоставляется возможным (или я не умею как). В остальном механизм схож с предыдущим.
На данный момент это все рецепты, что у меня есть. Если столкнусь с новыми, то обязательно дополню статью.
Обработка результата
В рецепте 1 мы чаще всего получаем готовый XDTO-объект и работаем с ним как со структурой. Во всех остальных случаях можно преобразовывать xml-ответ в XDTO
Если Результат.КодСостояния = 200 Тогда ЧтениеXML = Новый ЧтениеXML; ЧтениеXML.УстановитьСтроку(Результат.ПолучитьТелоКакСтроку()); ОбъектОтвет = СвояФабрикаXDTO.ПрочитатьXML(ЧтениеXML); Сообщить(ОбъектОтвет.Body.Response.RESPONSE_ID); Сообщить(ОбъектОтвет.Body.Response.RESPONSE_TEXT); КонецЕсли;
Тут все просто.
Вместо заключения
1. Начинайте работу с web-сервисами с программы SoapUI. Она предназначена для таких работ и позволит быстрее понять как работает тот или иной сервис. Для освоения есть статья про SoapUI.
2. Если вы обмениваете с сервисом по незащищенному каналу http и возникает вопрос в том что именно отправляет 1с в своих сообщениях, то можно воспользоваться снифферами трафика такими как Wireshark, Fiddler, и другие. Проблема возникнет только если используете ssl-соединение.
3. Если все же web-сервис общается по https, то ставим на удаленной машине (любой, главное не на своей) сервер Nginx, к которому мы и будем обращаться, а он в свою очередь запакует все в https и перешлет куда нужно (reverse proxy) и в стандартный конфиг добавляем:
server { listen 0.0.0.0:8080; server_name MyServer; location ~ .* { proxy_pass https://Somesite.ru:8001; proxy_set_header Host $host; proxy_set_header Authorization «Basic <base64 ваш пароль:логин>»; proxy_pass_header Authorization; } }
4. Если вас пугает XDTO, то рекомендую ознакомится с циклом статей злого бобра Андрея XDTO — это просто.
5. Если аутентификация предполагает использование Cookie, то нашлась следующая статья.
справка:
WSОпределения (WSDefinitions)
Из WSDL файла
Синтаксис:
Новый WSОпределения(<МестоположениеWSDL>, <ИмяПользователя>, <Пароль>, <ИнтернетПрокси>, <Таймаут>, <ЗащищенноеСоединение>, <ИспользоватьАутентификациюОС>)
Параметры:
<МестоположениеWSDL> (обязательный)
Тип: Строка.
Местоположение WSDL файла, откуда будет получено определение веб-сервисов.
<ИмяПользователя> (необязательный)
Тип: Строка.
Имя пользователя, которое будет использоваться для аутентификации при получении определений веб-сервисов.
<Пароль> (необязательный)
Тип: Строка.
Пароль пользователя, который будет использоваться для аутентификации при получении определений веб-сервисов.
<ИнтернетПрокси> (необязательный)
Тип: ИнтернетПрокси.
Содержит объект ИнтернетПрокси, используемый для загрузки WSDL документа по протоколу HTTP.
Если не указан, то используются настройки прокси по умолчанию.
Значение по умолчанию: Неопределено.
<Таймаут> (необязательный)
Тип: Число.
Таймаут соединения, осуществляемого для загрузки WSDL описания веб-сервиса, в секундах. 0 — не устанавливать таймаут.
Значение по умолчанию: 0.
<ЗащищенноеСоединение> (необязательный)
Тип: ЗащищенноеСоединениеOpenSSL; Неопределено.
Объект защищенного соединения для осуществления HTTPS соединения для загрузки WSDL описания веб-сервиса.
Значение по умолчанию: Неопределено.
<ИспользоватьАутентификациюОС> (необязательный)
Тип: Булево.
Включает использование аутентификации NTLM или Negotiate на сервере.
Значение по умолчанию: Ложь.
Описание:
Создает определение веб-сервисов из WSDL-файла.
Если используемый WSDL-файл некорректен, будет вызвано исключение.
пишу так:
ОпределениеWS = Новый WSОпределения(«http://api.xxx.ru/schema/service.wsdl");
создается объект с типом WSОпределения, но так как всё тянется с интернета, проходит время, хочу ускорить
сохраняю wsdl на диск, добавляю макет, с типом двоичные данные и называю его service_wsdl, пишу следующее:
ФайлWSDL = ПолучитьИмяВременногоФайла(«wsdl»);
ПолученныйМакет = ПолучитьМакет(«service_wsdl»);
ПолученныйМакет.Записать(ФайлWSDL);
ОпределениеWS = Новый WSОпределения(ФайлWSDL);
УдалитьФайлы(ФайлWSDL);
конструктор не срабатывает, в ошибке написано следующее:
Ошибка при вызове конструктора (WSОпределения): При вызове веб-сервиса произошла ошибка. При создании описания сервиса произошла ошибка. : Файл не обнаружен ‘C:\Users\user\AppData\Local\Temp\Service.wsdl’
при этом переменная ФайлWSDL имеет следующее значение: ‘C:\Users\user\AppData\Local\Temp\v8_BF2A_2bb.wsdl’, и по указанному пути хранится в точности такой же файл, какой был скачан с интернета
помогите разобраться, что не так, ведь в конструктор в первый параметр передается строка, как и указано в справке
- Платформа parts-soft.ru /
- Возможности системы /
- Подключение веб-сервисов
Для подключения веб-сервиса необходимо зарегистрироваться на сайте поставщика, после чего запросить доступ у Вашего клиентского менеджера.
Фото 1. Пример письма для открытия доступа
Для активации веб-сервиса в системе Parts-Soft.ru выполните шаги, описанные ниже.
ШАГ 1. Перейдите в меню Служебные → Справочники → Веб-сервисы. В открывшемся списке веб-сервисов нажмите на кнопку «Подключить».
Фото 2. Список веб-сервисов
РЕЗУЛЬТАТ: откроется окно Подключение веб-сервиса.
ШАГ 2. В открывшемся окне выберите нужный веб-сервис из выпадающего списка Доступные веб-сервисы и нажмите на кнопку «Запросить подключение».
Рассмотрим на примере подключение API parts-soft.ru (это Важно), просьба обратить внимание.
Фото 3. Запросить подключение
РЕЗУЛЬТАТ: появится блок Данные для подключения.
ШАГ 3. В появившемся поле Логин введите данные для подключения (ключ API доступа, полученный у Вашего поставщика) и нажмите на кнопку «Подключить».
Обратите внимание, что подключение каждого отдельного веб-сервиса может отличаться, то есть при подключении может понадобиться ключ API, а может логин и пароль.
Фото 4. Данные для подключения
РЕЗУЛЬТАТ: новый веб-сервис появится в списке веб-сервисов (см. фото 2).
ШАГ 4. Для настройки параметров веб-сервиса нажмите на ссылку Настройки.
Фото 5. Переход к настройкам веб-сервиса
РЕЗУЛЬТАТ: откроется страница настроек веб-сервиса.
ШАГ 5. На странице настроек веб-сервиса в поле URL укажите адрес сайта поставщика без слеша на конце (например, https://ваш-поставщик.ru).
Описание некоторых важных параметров представлено в Таблице. Нажмите на кнопку «Сохранить» (8), чтобы выполненные настройки вступили в силу.
Фото 6. Настройки веб-сервиса
№ |
Название настройки |
Описание |
---|---|---|
Логин |
Логин на сайте поставщика или ключ api доступа. |
|
Логин 2 |
Для некоторых поставщиков необходимо указывать номер договора. |
|
Пароль |
Пароль на сайте поставщика (если в качестве логина был указан логин на сайте поставщика). |
|
Префикс поставщика |
Информация доступна в справочном разделе Склады веб-сервиса. |
|
Таймаут соединения |
Максимальное время, в течении которого система ожидает ответа от веб-сервиса, далее соединение сбрасывается. |
|
Адрес сайта поставщика (без слеша на конце). |
||
Настройка фильтра результатов |
Позволяет фильтровать выдачу от данного поставщика по одному из трех алгоритмов на выбор. Для каждого артикула — n с лучшей ценой, n с лучшей ценой + n с лучшим сроком, n с лучшей ценой + n с лучшим сроком + n с лучшей статистикой. |
ШАГ 6. У многих веб-сервисов есть дополнительные поля оформления заказа. Проверьте в настройках подключенного веб-сервиса наличие таких полей. Если они есть — установите их значения и обязательно нажмите на кнопку «Сохранить».
Фото 6. Поля оформления заказа
Тестирование веб-сервиса
После настройки веб-сервиса можно проверить подключение.
Для этого перейдите к списку веб-сервисов и в нужной строке нажмите на ссылку «Тест». В нижнем поле отобразится информация о найденном предложении либо о проблемах с подключением.
Обратите внимание, что в списке веб-сервисов доступны и другие ссылки и на дополнительные настройки веб-сервиса. Подробнее в соответствующих справочных разделах:
- Поставщики;
- Статусы;
- Подмена номеров.
Фото 8. Тестирование веб-сервиса
Привязка веб-сервиса к прайс-листу
Для того чтобы данные с веб-сервиса появились в поиске, необходимо привязать его к прайс-листу. После привязки данные веб-сервиса появятся в поиске аналогично данным с загруженных прайс-листов.
ВАЖНО! При создании связанного прайс-листа потребуется указать поставщика. Убедитесь, что поставщик уже есть в системе либо создайте его (подробнее в справочном разделе Создание поставщика).
Для привязки веб-сервиса выполните следующие шаги.
ШАГ 1. Перейдите в меню Служебные → Справочники → Веб-сервисы. Рядом с названием подключенного ранее веб-сервиса нажмите на ссылку для создания связанного прайс-листа.
Фото 9. Ссылка на создание связанного прайс-листа
ШАГ 2. В открывшейся форме создания нового прайс-листа автоматически указываются тип прайс-листа и веб-сервис. Измените название прайс-листа на нужное Вам и выберите заранее созданного поставщика из выпадающего списка.
Нажмите на кнопку «Создать» в нижней части формы.
Фото 10. Новый прайс-лист
ШАГ 3. Нажмите на кнопку «Редактировать» для перехода к опциям прайс-листа. На странице опций отметьте галочкой пункт Активен, чтобы прайс-лист начал принимать участие в проценке.
Вы можете указать сроки доставки для данного прайс-листа. Также существует возможность настроить график отправки и время доставки, что влияет на окончательный срок доставки деталей (подробнее в справочных разделах График отправки заказов и Расчет времени доставки с учетом дополнительных сроков).
В блоке Связать с веб-сервисом можно убедиться, что в выпадающем списке выбран нужный веб-сервис. Информация для настройки наценок доступна в соответствующем справочном разделе Настройка наценок на прайс-лист.
По окончании настройки прайс-листа нажмите на кнопку «Сохранить».
Фото 11. Связать с веб-сервисом
РЕЗУЛЬТАТ: веб-сервис подключен и привязан к прайс-листу.
ВАЖНО! При подключении веб-сервиса ОБЯЗАТЕЛЬНО проверяйте, что у Вас открыт доступ к сервису со стороны поставщика. Доступ к личному кабинету на сайте поставщика не является доступом к веб-сервису. Для некоторых сервисов (например, Emex, Berg) необходимо запрашивать дополнительный доступ. Если доступ не будет получен, то у Вас не будет работать проценка.