Автор статьи: Asmody
исходник: http://kb.mista.ru/article.php?id=473
Использование внешних web-сервисов в 1С:Предприятие 8
В статье дается пример использования внешних web-сервисов в 1С:Предприятие 8.1. В качестве примера показано, как с помощью web-сервиса компании «Аэрофлот» можно получить расписание рейсов самолетов в режиме реального времени.
Платформа «1С:Предприятие 8» постоянно развивается. В связи с чем, код, представленный в этой статье, в последних версиях платформы будет выдавать ошибку. Происходит это, в частности, из-за того, что изменился порядок вызова методов прокси-объекта web-сервиса: например, сложные объекты необходимо явно преобразовывать в ОбъектXDTO соответствующего типа, используя Фабрику соответствующего сервиса. Об этом вы можете почитать на нашем форуме или в книге «Технологии интеграции 1С:Предприятия» http://v8.1c.ru/metod/books/book.jsp?id=288
Вступление
Когда появляется новая версия какого-то программного продукта, то естественно, в первую очередь хочется понять, чего же такого в нем появилось нового. В случае с «1С:Предприятие 8.1» такой новой «фичей» для меня стали web-сервисы. Про web-сервисы написано и сказано много, поскольку существует эта технология по компьютерным меркам достаточно давно. По-этому я повторяться не буду, за справками отправляю всех к Яндексу. Скажу лишь, что с выходом новой редакции платформы «1С:Предприятие 8.1» у 1Сников появилась возможность создавать и использовать технологию web-сервисов, находясь, так сказать, в родной среде. В этой статье я хочу показать, как использовать внешние web-сервисы в своих разработках.
Для тех, кто совсем "не в теме": о web-сервисах "на пальцах"
ОК, специально для ТЕБЯ я чуть-чуть попытаюсь рассказать, что такое web-сервис, и почему именно это показалось мне таким «вкусным» новшеством платформы. Возможно ты знаешь про технологию COM или что-то слышал про OLE? С этой технологией рано или поздно сталкивается любой одинесник (особенно если надо быстро перекинуть какой-нибудь справочник «Сотрудники», а отдел кадров, предвидя необходимость снова вбивать всю 1500 сотрудников, готов повесить тебя на первом встречном подходящем гвозде).
Да, так вот, в основе технологии COM лежит идея о возможности вызова программного кода (и обращения к данным) одного приложения из другого приложения. Причем, возможности делать это не на уровне отдельных процедур и функций, но получая в распоряжение объекты другого приложения. При использовании OLE, мы в своем приложении создаем объект, являющийся «представителем» или, если хотите, «оберткой» некоторого объекта того приложения, с которым мы хотим наладить взаимодействие (т.н. «OLE-объект» или «COM-объект»). Через этот объект-«обертку» нам становятся доступны свойства и методы объекта другого приложения, причем только те из них, которыми разработчик того приложения разрешил нам пользоваться, опубликовав их в описании интерфейса. (Ну вот, не хотел лезть в дебри, но по-другому не получается…)
Теперь представим себе, что то-самое приложение находится на другом компьютере, и даже не в локальной сети (с такими случаями неплохо справляются DCOM, CORBA и прочие заумные аббревиатуры), а где-то далеко-далеко в Интернете. Вот тут-то и выходят на сцену web-сервисы (тоже в комплекте с заумными аббревиатурами: SOAP, WSDL и др.), которые позволяют проделывать аналогичный «фокус» и в этом случае: т.е. получать данные и манипулировать объектами приложения, выполняющегося на компьютере на другом краю Интернета.
Под «внешним» web-сервисом я буду понимать web-сервис, предоставляемый некоторым поставщиком сервиса (т.е. не нашим приложением.) Соответственно, под «внутренним» - web-сервис, который будем предоставлять мы из, или, точнее, на основе нашего приложения. При использовании внешних web-сервисов надо понимать, что хотя объект-«обертка» создается в нашем «локальном» приложении, «исполняющий код» этого объекта находится, может быть, на другой стороне Земного Шара. При этом обмен между нами и ними происходит на вездесущем ныне XML, с его известными «плюсами» (универсальностью и структурированностью) и «минусами» (раздутостью), а в качестве «линии передачи» используется старый добрый http.
Да, и не забудь про интернет-трафик! Причем, в случае с внешними web-сервисами большая часть его придется на входящую составляющую.
Все, остальное есть в Яндексе. Поехали дальше…
Откуда ноги, т.е. крылья растут
Порывшись в том же Яндексе, я нашел замечательный web-сервис от компании «Аэрофлот», который позволяет в режиме реального времени получать информацию о прилете и вылете самолетов, и решил сделать эдакое «Табло аэропорта» в «1С:Предприятие». Сам сервис живет тут Уже не живёт. Видимо, после переделки сайта «Аэрофлота», сервис был убит.
Он сказал: "Поехали!"
Для начала я создал пустую конфигурацию «1С:Предприятия 8.1» (на момент написания статьи в моем распоряжении была версия платформы 8.1.5.123). Затем я добавил в свою конфигурацию новый объект типа WS-ссылка. На предложенный запрос ввести URL импортируемого WSDL, я ввел ссылку на WSDL-файл, которая значится на странице сервиса: http://webservices.aeroflot.ru/flightstatus.wsdl (WSDL-файл является описанием web-сервиса. За подробностями - в Яндекс), и гордо назвал созданный объект «Аэрофлот». Щелкнув два раза на этом объекте, я получил дерево со структурой web-сервиса.
Это дерево представляет собой «портрет» web-сервиса, как его видит 1Ска. Самое интересное находится в ветке «Web-сервисы»: это имена и порты web-сервисов (на самом деле WSDL-файл может описывать не один, а несколько web-сервисов, тогда для каждого web-сервиса будет создана своя ветка), и перечислены методы web-сервиса. Это и есть те самые «ниточки», подергав за которые можно приоткрыть себе доступ к тем данным, которые предоставляет web-сервис. В ветке «Модель данных» содержится описание библиотек типов данных, которые используются web-сервисом.
Краткую справку об использовании web-сервиса обычно можно получить там же, где и ссылку на WSDL-файл. В случае с «Аэрофлотом», это страничка http://webservices.aeroflot.ru/flightstatus.asmx
"То взлет, то посадка..."
Для работы с web-сервисом я добавил в конфигурацию обработку «ТаблоВылетов», а в ней - одну форму, которую назначил основной. На форму я положил поле выбора «ВыборАэропорта», поле ввода «ДатаРейса», панель «ПанельТабло» с двумя страницами «Прилет» и «Вылет», при этом я снял флаг «Распределять по страницам» в свойствах панели, и табличное поле «ТаблицаТабло». Взаимодействие с web-сервисом происходит по принципу «запрос-ответ», при этом для web-сервиса создается специальный объект-посредник. Поэтому я добавил реквизит формы «СервисАэрофлот» произвольного типа. Если внимательно почитать описание сервиса, то можно увидеть, что web-сервис предоставляет данные о прилетах и вылетах через вызовы методов Arrival и Departure соответственно. При этом оба метода принимают в качестве параметров код аэропорта и нужную дату. Кроме того, web-сервис предоставляет возможность получить список аэропортов, по которым имеются данные в системе. Достаточно очевидным является следующий сценарий взаимодействия с web-сервисом: 1. Получить список аэропортов; 2. Выбрать нужный аэропорт и дату; 3. Получить данные о прилетах или вылетах; Но прежде чем обращаться к web-сервису, необходимо инициализировать объект-посредник (типа WSПрокси), что я и сделал в обработчике открытия формы:
СервисАэрофлот=WSСсылки.Аэрофлот.СоздатьWSПрокси("http://www.aeroflot.ru/", "FlightStatus", "FlightStatusSoap" );
Первым параметром передается URI пространства имен web-сервиса. Узнать его можно открыв свойства web-сервиса в дереве WS-ссылки. Вторым и третьим параметром параметрами передаются соответственно имя и порт web-сервиса. (не надо путать понятия «имя», «порт», «прокси» и т.п. в применении к web-сервисам с более привычными понятиями протокола TCP/IP. Соответствие между ними если и есть, то скорее смысловое. В общем случае нужно понимать, что, например порт web-сервиса и TCP-порт - это абсолютно разные вещи). Таким образом я проинициализировал объект СервисАэрофлот типа WSПрокси, который по-сути своей является «оберткой» web-сервиса. Через него я смогу обращаться к методам web-сервиса как к «родным» методам платформы. Первым делом я получил список аэропортов и заполнил список поля выбора «ВыборАэропорта»:
СписокВыбора=ЭлементыФормы.ВыборАэропорта.СписокВыбора; СписокВыбора.Очистить(); СписокАэропортов=СервисАэрофлот.AirportList().ПолучитьСписок("list"); ВсегоАэропортов=СписокАэропортов.Количество(); Для ии=0 по ВсегоАэропортов-1 Цикл Аэропорт=СписокАэропортов.Получить(ии); СписокВыбора.Добавить(Аэропорт.code, ""+Аэропорт.city+" : "+Аэропорт.name); КонецЦикла;
Тут нужен небольшой комментарий по конструкции
СписокАэропортов=СервисАэрофлот.AirportList().ПолучитьСписок("list");
Дело в том, что значения, возвращаемые методами web-сервисов, представляются в платформе объектами типа ОбъектXDTO. Поскольку тематика технологии XDTO выходит за рамки этой статьи, скажу лишь, что для превращения этого объекта в список (чем он и является), я вызвал его метод ПолучитьСписок(). Остальное в коде достаточно очевидно, включая названия полей структуры Аэропорт, которые я нашел на странице описания web-сервиса.
Теперь можно запустить конфигурацию и убедиться, что список поля выбора заполняется названиями аэропортов:
"День отлета, день прилета..."
Теперь у меня практически все готово для того, чтобы заставить мое табло функционировать. Осталось только его «выкрасить и выбросить» :) Чем и займусь:
Процедура ЗаполнитьТабло(Прилет=Истина) ТаблицаТабло.Колонки.Очистить(); ТаблицаТабло.Колонки.Добавить("КодРейса",, "Код рейса"); ТаблицаТабло.Колонки.Добавить("КодАвиакомпании",, "Авиакомпания"); ТаблицаТабло.Колонки.Добавить("НомерРейса",, "Номер"); ТаблицаТабло.Колонки.Добавить("АэропортТранзит",, "Аэропорт-транзит"); ТаблицаТабло.Колонки.Добавить("Аэропорт",, "Аэропорт "+?(Прилет,"вылета","прилета")); ТаблицаТабло.Колонки.Добавить("ВремяРасписание",, "По расписанию"); ТаблицаТабло.Колонки.Добавить("ВремяПланируемое",, "Планируемое"); ТаблицаТабло.Колонки.Добавить("ВремяФактическое",, "Фактическое"); ТаблицаТабло.Колонки.Добавить("ВремяРасчетное",, "Расчетное"); ТаблицаТабло.Колонки.Добавить("ВремяПосадки",, ?(Прилет,"Посадка","Взлет")); ТаблицаТабло.Колонки.Добавить("ОбъедРейс",, "Объед.рейс"); ТаблицаТабло.Колонки.Добавить("Статус",, "Статус"); Если Не Прилет Тогда ТаблицаТабло.Колонки.Добавить("Регистрация",, "Регистрация"); ТаблицаТабло.Колонки.Добавить("Посадка",, "Посадка"); КонецЕсли; ЭлементыФормы.ТаблицаТабло.СоздатьКолонки(); ЭлементыФормы.ТаблицаТабло.Колонки.КодРейса.Видимость=Ложь; Если Не Прилет Тогда ЭлементыФормы.ТаблицаТабло.Колонки.ВремяРасчетное.Видимость=Ложь; КонецЕсли; Если Прилет Тогда Данные=СервисАэрофлот.Arrival(ВыборАэропорта, ДатаРейса).ПолучитьСписок("list"); Иначе Данные=СервисАэрофлот.Departure(ВыборАэропорта, ДатаРейса).ПолучитьСписок("list"); КонецЕсли; ВсегоЗаписей=Данные.Количество(); Для ии=0 по ВсегоЗаписей-1 Цикл Запись=ДАнные.Получить(ии); НоваяСтрока=ТаблицаТабло.Добавить(); НоваяСтрока.КодАвиакомпании=Запись.company; НоваяСтрока.НомерРейса=Запись.flight_no; НоваяСтрока.АэропортТранзит=Запись.airport_inter; НоваяСтрока.Аэропорт=Запись.airport; НоваяСтрока.ВремяРасписание=Запись.sched; НоваяСтрока.ВремяПланируемое=Запись.plan; НоваяСтрока.ВремяФактическое=Запись.fact; НоваяСтрока.ВремяРасчетное=Запись.calc; НоваяСтрока.ВремяПосадки=Запись.real; НоваяСтрока.ОбъедРейс=Запись.union_flight_no; НоваяСтрока.Статус=Запись.status; Если Не Прилет Тогда НоваяСтрока.Регистрация=Запись.is_check; НоваяСтрока.Посадка=Запись.is_board; КонецЕсли; КонецЦикла; КонецПроцедуры
Для того, чтобы проверить как это все работает, я добавил на командную панель формы кнопку «Обновить» с соответствующей картинкой, а в ее обработчике написал такое:
Процедура КоманднаяПанель1Обновить(Кнопка) ЗаполнитьТабло(ЭлементыФормы.ПанельТабло.ТекущаяСтраница=ЭлементыФормы.ПанельТабло.Страницы.Прилет); КонецПроцедуры
Послесловие
Удивительное дело, но уже после того, как статья была написана и опубликована, выяснилось, что уважаемый ZAV уже опубликовал похожий пример на IT-Land'е: http://itland.ru/biblio/detail.php?ID=1060 Дабы избежать возможных обвинений в плагиате, настоятельно рекомендую ознакомиться и с этой статьей тоже и сравнить подходы авторов.