Книга знаний

1С:Предприятие / Приемы программирования / Интернет-технологии

Использование внешних web-сервисов в 1С:Предприятие 8

В статье дается пример использования внешних web-сервисов в 1С:Предприятие 8.1. В качестве примера показано, как с помощью web-сервиса компании "Аэрофлот" можно получить расписание рейсов самолетов в режиме реального времени.Автор статьи: Asmody | Редакторы: Волшебник
Последняя редакция №24 от 21.02.12 | История
URL: http://kb.mista.ru/article.php?id=473

Ключевые слова: web-сервис, веб-сервис, SOAP, WSDL, ws-ссылка


Дисклеймер и условия использования


Все случайно упомянутые в статье торговые марки принадлежат своим владельцам.
Статья опубликована под лицензией Creative Commons Attribution-Share Alike 3.0 Unported License. http://creativecommons.org/licenses/by-sa/3.0/

Ещё один дисклеймер (спустя многие времена)


Платформа "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С:Предприятие". Сам сервис живет тут: http://webservices.aeroflot.ru/desc_flightinfo.asp

Он сказал: "Поехали!"


Для начала я создал пустую конфигурацию "1С:Предприятия 8.1" (на момент написания статьи в моем распоряжении была версия платформы 8.1.5.123). Затем я добавил в свою конфигурацию новый объект типа WS-ссылка. На предложенный запрос ввести URL импортируемого WSDL, я ввел ссылку на WSDL-файл, которая значится на странице сервиса: http://webservices.aeroflot.aero/flightstatus.wsdl (WSDL-файл является описанием web-сервиса. За подробностями - в Яндекс), и гордо назвал созданный объект "Аэрофлот". Щелкнув два раза на этом объекте, я получил дерево со структурой web-сервиса.

Это дерево представляет собой "портрет" web-сервиса, как его видит 1Ска. Самое интересное находится в ветке "Web-сервисы": это имена и порты web-сервисов (на самом деле WSDL-файл может описывать не один, а несколько web-сервисов, тогда для каждого web-сервиса будет создана своя ветка), и перечислены методы web-сервиса. Это и есть те самые "ниточки", подергав за которые можно приоткрыть себе доступ к тем данным, которые предоставляет web-сервис. В ветке "Модель данных" содержится описание библиотек типов данных, которые используются web-сервисом.
Краткую справку об использовании web-сервиса обычно можно получить там же, где и ссылку на WSDL-файл. В случае с "Аэрофлотом", это страничка http://webservices.aeroflot.aero/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
Дабы избежать возможных обвинений в плагиате, настоятельно рекомендую ознакомиться и с этой статьей тоже и сравнить подходы авторов.

Описание | Рубрикатор | Поиск | ТелепатБот | Захваченные статьи | Установки | Форум
© Станислав Митичкин (Волшебник), 2005-2025 | Mista.ru

Яндекс.Метрика