Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Несмотря на то, что “в коробке” с Битриксом уже идут модули как для SOAP (модуль “Веб сервисы” в редакции “Бизнес” и старше), так и для REST (модуль “Rest API” во всех редакциях, начиная с версии 16.6.0), примеров по работе с ними до сих пор недостаточно. Постараемся развеять “туман войны”
Постановка задачи
Допустим, у нас есть клиент Виталий. Виталий ведет активный бизнес в интернете: владеет собственным интернет-магазином (shop.ru), поддерживает текстовый блог, зарабатывая с контекстной рекламы, ведет канал на YouTube не пренебрегая рекламной интеграцией и др. Также у Виталия есть личный dashboard-сайт (dashboard.ru), на котором он анализирует свои доходы от разных источников, автоматизирует некоторые операции и т.п. YouTube канал уже интегрирован с dashboard, блог — тоже. И вот дошло дело и до интернет-магазина. Виталий приходит к нам и говорит: “Хочу видеть информацию по продажам интернет-магазина на своем dashboard”. Задача — организовать взаимодействие между двумя системами — двумя сайтам — shop.ru и dashboard.ru. Перед нами типичная задача интеграции. Среди списка информации, которую Виталий хочет получать с сайта, остановимся на следующем требовании: “Информация об ожидаемой прибыли”.
SOAP. Модуль “Веб сервисы”
Для реализации SOAP веб-сервисов у Битрикс есть модуль “Веб-сервисы”. Документирован он в стиле Битрикс — плохо. Однако, кое-какую информацию найти все же можно. Здесь находится описание некоторых (не всех) встроенных компонентов. А здесь можно найти пример реализации soap сервера с использованием встроенного компонента.
Неотъемлемый навык любого Битрикс-разработчика — умение разбираться в исходном коде. Что ж, применим его. Модуль “Веб-сервисы” под капотом не использует php модуль soap. В некоторых случаях (хостер не включил php-soap) именно этот факт может склонить вас использовать модуль Битрикс для реализации SOAP веб-сервиса. Модуль позволяет реализовать как soap сервер, так и soap клиент. Для soap сервера у Битрикс есть класс CSOAPServer, для клиента — CSOAPClient. Если с первым напрямую работать скорее всего не придется, т.к. есть компонент, то для реализации клиента потребуется использовать API напрямую. Также в модуле есть классы для soap запроса, ответа, ошибки и др. Узнать, как работать с модулем можно взглянув на реализацию встроенных компонентов, а также откопав в модуле файл с тестами. Да, да, вы не ослышались, файл с тестами в формате phpt.
А теперь попробуем воспользоваться возможностями модуля для реализации задачи Виталия.
Так как интернет-магазин shop.ru является источником информации, логично предположить, что на нем необходимо развернуть soap сервер. Модуль Битрикс действительно облегчает работу по созданию soap сервера, взяв на себя работу по генерации wsdl файла. Хочется отметить, что soap модуль php такого не умеет. Для того, чтобы реализовать наш сервер, нам потребуется класс всего с 3 методами:
-
Метод проверки авторизации: проверяем права пользователя на доступ к модулю sale. Если прав нет, инициируем http-авторизацию.
-
Метод получения информации об ожидаемой прибыли. Обусловимся, что ожидаемая прибыль — это сумма стоимостей не отмененных ('CANCELED' => 'N') заказов в статусе “Принят, ожидается оплата” (STATUS_ID' => 'N').
-
Метод описания сервера — самое интересное. Именно на основе данных, возвращенных этим методом и генерируется wsdl файл. В методе необходимо создать объект класса CWebServiceDesc и сконфигурировать его:
-
название веб-сервиса (wsname);
-
класс веб-сервиса (wsclassname);
-
служебная информация (wsdlauto, wsendpoint, wstargetns);
-
комплексные типы данных (classTypes, structTypes);
-
методы.
Название нашего веб-сервиса — intervolga.webservice.shop. Имя класса — ShopWebService — текущий класс.
Наш метод получения ожидаемой прибыли не принимает никаких аргументов, а информацию возвращает в виде строки. Поэтому, комплексных типов данных не объявляем — оставляем массивы пустыми.
Обратите внимание на описание поля classes. В нем мы описываем класс-обработчик для веб-сервиса и его методы. Название класса-обработчика необходимо указывать вместе с пространством имен. Это позволит нам расположить классы-обработчики отдельно от самих компонентов soap сервера. Описание метода достаточно прозрачно: название, входные и выходные параметры и служебная информация — доступность метода, необходимость авторизации.
Сам класс должен наследоваться от битриксового IWebService. Также не забываем подключить все необходимые модули. Класс-обработчик для веб-сервера мы создали. Теперь необходимо разместить на одной из публичных страниц компонент soap сервера — bitrix:webservice.server и настроить его на использование нашего класса-обработчика:
Теперь, перейдя на страницу с компонентом мы увидим простенький UI с описанием веб-сервиса, возможностью протестировать методы сервера или просмотреть сгенерированный wsdl файл.
Для тестирования и отладки компонента недостаточно: нет возможности посмотреть сырые данные запроса и ответа (soap конверты), к тому же в некоторых моментах компонент не так строго следует стандартам. Например, если указать тип возвращаемого значения нашего метода — integer, то компонент в ответе будет отображать вещественное число. Поэтому, лучше использовать сторонний SOAP клиент, например, SoapUI . Кстати, он в данном случае корректно вернет целое число, отбросив дробную часть. C помощью клиента SoapUI мы можем посмотреть soap конверт запроса:
И soap конверт ответа:
На этом базовая реализация soap сервера завершена. Наш сервер принимает запросы и возвращает необходимую информацию.
Перейдем к клиенту. Напомню, что наш клиент — сайт dashboard.ru. Для простоты предположим, что этот сайт также на Битрикс. Для получения и отображения информации об ожидаемом доходе воспользуемся инструментом “Гаджеты”. Опустим детали разработки гаджетов Битрикс и сфокусируемся на основном коде гаджета. Здесь нам нужно обратиться к веб-сервису, получить информацию и отобразить ее в красивом виде.
За реализацию soap клиента в Битрикс отвечает класс CSOAPClient. В качестве аргументов конструктора ему нужно передать адрес сайта, на котором развернут soap сервер и относительный путь до страницы с компонентов сервера. Также, т.к. мы настроили на сервере проверку прав доступа, необходимо добавить клиенту логин и пароль одного из пользователей сайта (с доступом к модулю sale). Для выполнения запроса нужно создать экземпляр класса CSOAPRequest, указав название метода. Добавить параметры запроса (в нашем случае не требуется) и отправить запрос, сохранив результат. Последний шаг — обработать полученный результат и вывести его. Итоговый код гаджета получился следующим:
Стоит отметить, что если для реализации soap сервера мы не задумываясь остановились на предлагаемом решении модуля Битрикс, т.к. он действительно упрощал работу, возлагая на себя ответственность по генерации wsdl файла, то с soap клиентом Битрикс не все так однозначно. Чтобы пояснить, о чем я говорю, приведу пример реализации этого же гаджета, но с использованием php модуля soap:
Как видите, код получился короче и элегантнее. Мы не создаем промежуточных объектов. На конфигурацию объекта клиента потребуется одно выражение, вместо трех. На отправку запроса — одно, вместо двух. К тому же, не стоит забывать о том, что в случае возникновения каких либо сложностей, разобраться и найти помощь с модулем php будет легче. Также, по отзывам, php модуль soap обладает достаточно хорошей производительностью. Так что, решать, пользоваться ли модулем Битрикс или модулем php — вам. Я лишь скажу, что на нескольких боевых проектах у нас давно и стабильно используется soap клиент, реализованный именно на основе модуля php.
А теперь взглянем на получившийся гаджет:
Готово! Мы удовлетворили потребность Виталия, реализовав запрошенный функционал. Мы успешно интегрировали две системы настроив SOAP веб-сервис с использованием модуля “Веб-сервисы” от Битрикс.
Rest. Модуль “Rest API”
Еще один вариант реализации веб-сервиса, реализованный в Битрикс — Rest API. Совсем недавно, начиная с 18 версии, модуль для работы с Rest API перенесли из Б24 в БУС. Документация для этого модуля в БУС полностью отсутствует (на момент написания статьи). Но есть документация Rest API для Б24. Возможности модулей схожи, поэтому можно ознакомиться с документацией для Битрикс24. Мы же, как и полагается, воспользуемся исходным кодом модуля. Веб-сервис также будет состоять из сервера и клиента. Для сервера в модуле есть компонент bitrix:rest.server, для клиента — обычный HttpClient битрикс. Начнем с сервера.
Интересный факт: после установки модуля Rest API, создается ЧПУ “/rest/”. Об этом можно узнать из urlrewrite. На странице размещен компонент сервера с некоторыми сервисными методами.
Для нашей задачи воспользуемся стандартным ЧПУ. Если такой адрес вас не устраивает, можно разместить компонент bitrix:rest.server в любой удобной для вас директории.
Для реализации методов Rest API нам потребуется класс-обработчик. Данный класс (ShopWebService в нашем случае) необходимо наследовать от битриксового IRestService. В классе нам потребует константа с названием scope для нашего веб-сервиса. В модуле Rest API scope используется для разграничения прав на наборы операций. Установив собственный scope мы разграничим методы нашего веб-сервиса от других. Также, можно использовать scope для имитации версионирования методов API, т.к. встроенной возможности версионирования в модуле нет.В дальнейшем мы еще вернемся к этому.
В классе нам также потребуется 3 метода:
-
Метод получения информации об ожидаемой прибыли. Здесь все аналогично soap, только без проверки авторизации. К моменту вызова метода, аутентификация уже будет произведена.
-
Метод конфигурации сервера. В этом методе мы должны вернуть массив с описанием доступных методов веб-сервиса. Описание метода содержит название метода для обращения к нему извне — ключ массива. Значение этого массива — класс и название метода в коде. Обратите внимание мы используем наш scope как ключ внешнего массива. На этом уровне массива мы также можем указать другие scope и их методы. Также мы добавляем scope как префикс для каждого метода.
-
Обработчик события OnRestServiceBuildDescription. По сути, здесь мы также возвращаем массив конфигурации веб-сервиса, но немного в другом виде. Данный метод потребуется нам в дальнейшем для выбранного механизма авторизации. Не забываем также подключить обработчик события. Именно он будет использоваться для оповещения модуля Rest API о новом наборе методов.
Теперь перейдем к авторизации. Ее принцип здесь существенно отличается. Мы не будем использовать HTTP-авторизацию. Битриксовый модуль предлагает несколько вариантов реализации авторизации:
-
oauth (широко известный открытый протокол авторизации);
-
apauth (авторизация на основе вебхуков);
-
sessionauth (авторизация на основе сессий и кук).
Также есть возможность расширить список за счет события OnRestCheckAuth, реализовав собственный вариант авторизации. Мы воспользуемся методом apauth. Этот метод авторизации предполагает использование вебхуков и работает только с https. Необходимо создать вебхук для нашего веб-сервиса. Для этого в модуле есть компонент bitrix:rest.hook. Разместим его в служебном разделе (например, в папке /web_service/rest/hook) и перейдем по адресу shop.ru/web_service/rest/hook/ap/0/. Заполним форму следующим образом:
Обратите внимание на поле “Права доступа”. Здесь мы выбираем наш scope. Обработчик OnRestServiceBuildDescription используется для добавления новых scope в этот список.
Интересный момент: если вы вернетесь к обработчику, то заметите, что мы нигде не указывали строковое название scope — “Rest API для dashboard.ru”. Опытным путем было выяснено, что битрикс сам подхватывает это название из языковой переменной шаблона “REST_SCOPE_<scope>”. Для этого также не забываем загрузить файл языковых переменных на странице с обработчиком.
Нажимаем на кнопку “Сохранить”, вебхук будет создан. Сохраните токен вебхука. Он нам потребуется для построения запросов к rest серверу. На этом наш rest сервер готов. Перейдем к написанию клиента.
Клиентом по прежнему будет являться гаджет на сайте dashboard.ru. Отдельного класса rest клиента нет. С его задачей отлично справляется обычный HttpClient битрикс. Схема та же: конфигурируем клиент, конфигурируем и отправляем запрос, получаем и выводим результат.
Остановимся подробнее на пути запроса:
https:://<server_name>/<path_to_rest_server>/<user_login>/<user_webhook_token>/<full_webservice_method_name>/, где:
-
<server_name> — название сайта (shop.ru);
-
<path_to_rest_server> — путь от корня сайта до папки размещения компонент bitrix:rest.server (/web_service/rest);
-
<user_login> — логин пользователя, для которого генерировался вебхук;
-
<user_webhook_token> — сгенерированный ранее токен вебхука;
-
<full_webservice_method_name> — название метода веб-сервиса (вместе с scope). Это название мы задавали в методе getDescription() в качестве ключей массива (dashboard_site.expected_income)
Для нашего случая запрос будет выглядеть следующим образом:
https://shop.ru/web_service/rest/admin/n5t9bkzjj3wxemlo/dashboard_site.expected_income/
Готово. Теперь мы реализовали веб-сервис с использованием Rest API модуля Битрикс. А вам остается лишь выбрать один из способов применительно к вашим условиям и задачам.