REST API в 1С-Битрикс: Управление сайтом (БУС)
Часто при разработке мобильных приложений или современных веб-интерфейсов для сайтов на «1С-Битрикс: Управление сайтом» (БУС) возникает необходимость получать и отправлять данные через REST API.
В отличие от Битрикс24, в БУС нет встроенного интерфейса для быстрой генерации ключей доступа к REST API. Для этого перейдите в административную панель Настройки > Настройки продукта > Модули, убедитесь что модуль rest установлен:
Настройка REST API
Официальная документация по REST API.
Поскольку в БУС нет штатного раздела для генерации вебхуков, создадим свою административную страницу для этой цели. Чтобы избежать конфликтов с URL-адресами самого REST API, разместим эту страницу в каталоге /local/rest/:
/local/rest/index.php<?php
// подключаем пролог административной части Битрикса
require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_admin.php');
// проверяем, что модуль REST установлен и активен
if (!\Bitrix\Main\Loader::includeModule('rest')) {
ShowError('Модуль REST не установлен');
require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/epilog_admin.php');
exit;
} ?>
<div class="adm-workarea">
<?php
// выводим компонент REST API, отображает список вебхуков и обрабатывает страницы их создания/редактирования
$APPLICATION->IncludeComponent(
'bitrix:rest.hook',
'.default',
[
'SEF_MODE' => 'Y',
// путь к нашей папке
'SEF_FOLDER' => '/local/rest/',
'COMPONENT_TEMPLATE' => '.default',
// шаблоны ЧПУ для компонента
'SEF_URL_TEMPLATES' => [
'list' => '',
'event_list' => 'event/',
'event_edit' => 'event/#id#/',
'ap_list' => 'ap/',
'ap_edit' => 'ap/#id#/',
],
],
false
); ?>
<br>
<a href="javascript:;" class="adm-btn adm-btn-green"
onclick="BX.PopupMenu.show('rest_hook_menu', this, [
{
// ссылка на создание исходящего вебхука
'href':'/local/rest/event/0/',
'text':'Исходящий вебхук'
},
{
// ссылка на создание входящего вебхука
'href':'/local/rest/ap/0/',
'text':'Входящий вебхук'
}
])">
Добавить вебхук
</a>
</div>
<?php
// подключаем эпилог
require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/epilog_admin.php');
Это критически важный шаг для того, чтобы и страница управления вебхуками и сами вызовы API работали корректно и не конфликтовали, необходимо иметь два отдельных правила:
- Правило для страницы управления вебхуками
/local/rest/, указывающее на компонент - Правило для API-вызовов
/rest/, указывающее на стандартный обработчик Битрикса
Откройте файл urlrewrite.php в корне сайта и убедитесь, что он содержит следующие два правила в последовательности как в примере:
urlrewrite.php// правило для страницы управления вебхуками (с компонентом)
100 =>
array (
// условие для нашего раздела управления
'CONDITION' => '#^/local/rest/#',
'RULE' => '',
// ID Компонента ОБЯЗАТЕЛЬНО
'ID' => 'bitrix:rest.hook',
// путь к файлу с компонентом
'PATH' => '/local/rest/index.php',
'SORT' => 100,
),
// правило для стандартной обработки вызовов REST API
150 =>
array (
// условие для вызовов API
'CONDITION' => '#^/rest/#',
'RULE' => '',
// ID может быть пустым
'ID' => '',
// путь к стандартному обработчику
'PATH' => '/bitrix/services/rest/index.php',
'SORT' => 200,
),
Не забывайте очищать кеш Битрикса после внесения изменений в файлы PHP и urlrewrite.php
Теперь, когда у нас есть страница управления, можно сгенерировать сам вебхук.
Перейдите по адресу https://site1.loc/local/rest/. Вы должны увидеть интерфейс для работы с вебхуками:
Нажмите зеленую кнопку Добавить вебхук и выберите Входящий вебхук:
Задайте имя вебхуку, в разделе Настройка прав доступа найдите и отметьте галочкой Информационные блоки (iblock). Также отметьте другие права, которые могут понадобиться вашему приложению, нажмите Сохранить:
Система сгенерирует URL для вызова REST API. Он будет выглядеть примерно так https://site1.loc/rest/ID_пользователя/уникальный_код/profile/, в действительности будет работать по адресу: https://site1.loc/rest/ID_пользователя/уникальный_код/:
Теперь можно попробовать получить данные элемента, используя метод iblock.Element.get.
URL вебхука:
https://site1.loc/rest/1/78103bqeped92b8c/
URL вебхука с параметрами:
https://site1.loc/rest/1/78103bqeped92b8c/iblock.Element.get?iblockId=37&elementId=555
По умолчанию метод iblock.Element.get возвращает очень ограниченный набор полей элемента:
IDNAMEIBLOCK_SECTION_ID
Расширение API с помощью своего контроллера
Чтобы обойти ограничения стандартного метода и получить доступ к полям вроде DETAIL_TEXT, необходимо создать собственный REST-контроллер для вашего инфоблока. Подробная документация об этом механизме доступна на сайте документации 1С-Битрикс своя реализация контроллера.
Мы реализуем контроллер, который наследует стандартный, но переопределяет список разрешенных полей.
API инфоблока/local/php_interface/lib/Rest/MyElementController.php<?php
namespace Local\Rest;
// пространство имен для логирования
// use Bitrix\Main\Diag\Debug;
// Убедитесь, что базовый класс доступен, проверка добавлена на случай проблем с загрузкой модуля
if (!class_exists('\Bitrix\Iblock\Controller\DefaultElement')) {
// лог для отладки
// Debug::writeToFile('Base DefaultElement class not found!', '', '__controller_error.log');
return;
}
class MyElementController extends \Bitrix\Iblock\Controller\DefaultElement
{
/**
* Конструктор. Обязательно вызываем родительский.
*/
public function __construct()
{
parent::__construct();
// лог для отладки
// Debug::writeToFile('MyElementController (full) instantiated!', '', '__controller_exec.log');
}
/**
* Переопределяем список разрешенных полей, добавляя нужные нам.
* Метод должен быть ПУБЛИЧНЫМ и СТАТИЧЕСКИМ (public static), как в родительском классе.
* @return array
*/
public static function getAllowedList()
{
// лог для отладки
// Debug::writeToFile('MyElementController: static getAllowedList() called.', '', '__controller_exec.log');
// вызов родительского статического метода для получения базового списка
$allowed = parent::getAllowedList();
// лог для отладки
// Debug::writeToFile(['Parent allowed list' => $allowed], '', '__controller_exec.log');
// Добавляем наши поля в список разрешенных, сюда можно добавить и другие нужные поля
$allowed[] = 'DETAIL_TEXT';
$allowed[] = 'PREVIEW_TEXT';
$allowed[] = 'DETAIL_PICTURE';
$allowed[] = 'PREVIEW_PICTURE';
$allowed[] = 'CODE';
// убираем дубликаты и возвращаем финальный список
$finalAllowed = array_unique($allowed);
// лог для отладки
// Debug::writeToFile(['Final allowed list' => $finalAllowed], '', '__controller_exec.log');
return $finalAllowed;
}
/**
* Опционально: можно переопределить getAction, если нужна особая логика
* Например, для дополнительной обработки данных перед возвратом.
*/
/*
public function getAction($iblockId, $elementId)
{
// лог для отладки
// Debug::writeToFile('MyElementController: getAction() called.', '', '__controller_exec.log');
$result = parent::getAction($iblockId, $elementId);
// ваша кастомная логика обработки $result
return $result;
}
*/
}
/local/php_interface/init.php<?php
use Bitrix\Main\Loader;
use Bitrix\Main\DI\ServiceLocator;
use Bitrix\Main\EventManager;
// пространство имен для логирования
// use Bitrix\Main\Diag\Debug;
// гарантируем, что модуль iblock загружен ПЕРЕД регистрацией, наш контроллер наследуется от класса из этого модуля
if (!Loader::includeModule('iblock')) {
// лог для отладки
// Debug::writeToFile('Failed to load iblock module in init.php!', '', '__init_error.log');
return;
} else {
// лог для отладки
// Debug::writeToFile('Iblock module loaded successfully in init.php.', '', '__init_log.log');
}
// регистрируем автозагрузку для нашего контроллера, сообщаем Битриксу, где искать наш класс Local\Rest\MyElementController
Loader::registerAutoLoadClasses(null, [
'\Local\Rest\MyElementController' => '/local/php_interface/lib/Rest/MyElementController.php',
]);
// регистрируем контроллер в Service Locator через событие OnPageStart
$eventManager = EventManager::getInstance();
$eventManager->addEventHandlerCompatible('main', 'OnPageStart', function() {
try {
// ВАЖНО замените 'my_iblock_1' на реальный API_CODE вашего инфоблока
$apiKey = 'my_iblock_1';
// формируем уникальный ключ для регистрации контроллера
$key = 'iblock.element.' . $apiKey . '.rest.controller';
// лог для отладки
// Debug::writeToFile('OnPageStart: Attempting registration for key: ' . $key, '', '__controller_reg.log');
// проверяем, что наш класс действительно доступен после автозагрузки
if (class_exists('\Local\Rest\MyElementController')) {
// создаем экземпляр локатора
$serviceLocator = ServiceLocator::getInstance();
// создаем экземпляр контроллера
$instance = new \Local\Rest\MyElementController();
// регистрируем локатор по ключу
$serviceLocator->addInstance($key, $instance);
// лог для отладки
// Debug::writeToFile('OnPageStart: Controller registered successfully for key: ' . $key, '', '__controller_reg.log');
} else {
// лог для отладки
// Debug::writeToFile('OnPageStart: Class \Local\Rest\MyElementController not found!', '', '__controller_reg_error.log');
// дополнительная проверка базового класса для диагностики
// if (!class_exists('\Bitrix\Iblock\Controller\DefaultElement')) {
// Debug::writeToFile('OnPageStart: Base \Bitrix\Iblock\Controller\DefaultElement STILL not found!', '', '__controller_reg_error.log');
// }
}
} catch (\Throwable $e) {
// ловим любые ошибки при регистрации
// Debug::writeToFile('OnPageStart: Error during registration: ' . $e->getMessage(), '', '__controller_reg_exception.log');
}
});
Не забудьте заменить my_iblock_1 на реальный API_CODE вашего инфоблока в этом файле!
После создания и регистрации контроллера вы можете использовать параметр select в запросе iblock.Element.get для получения полей, добавленных в getAllowedList.
Пример GET-запроса для получения ID, NAME и DETAIL_TEXT:
https://site1.loc/rest/1/78103bqeped92b8c/iblock.Element.get?iblockId=1&elementId=34&select[0]=ID&select[1]=NAME&select[2]=DETAIL_TEXT
Добавление своих методов в REST API
Объявляем свой класс RestTest который реализует два метода:
OnRestServiceBuildDescription()объявляет новыйscopeили логическую группу и список собственных методовtest()логика
/local/php_interface/init.php<?php
class RestTest
{
public static function OnRestServiceBuildDescription()
{
return array(
'hmarketing' => array(
'hmarketing.test' => array(
'callback' => array(__CLASS__, 'test'),
'options' => array(),
),
)
);
}
public static function test($query, $navStart, \CRestServer $server)
{
if ($query['error']) {
throw new \Bitrix\Rest\RestException(
'Message',
'ERROR_CODE',
\CRestServer::STATUS_PAYMENT_REQUIRED
);
}
return array(
'yourquery' => $query,
'myresponse' => 'Мой собственный ответ'
);
}
}
AddEventHandler(
'rest',
'OnRestServiceBuildDescription',
array(
'\RestTest',
'OnRestServiceBuildDescription'
)
);
В результате появится новый scope под именем hmarketing, у которого будет метод hmarketing.test с обработчиком test() из класса RestTest:
Запрос будет выглядить следующим образом:
https://site1.loc/rest/1/78103bqeped92b8c/hmarketing.test
В метод test() можно запихнуть обсалютно любую логику.
Пример запроса в Postman с параметром:







