Мобильное приложение на ember для Битрикса

Начну с предыстории, зачем мне понадобились такие сложности. У нас был готовый портал с личным кабинетом пользователя. Как уже можно догадаться, сайт сделан на Битриксе, со своей структурой инфоблоков, авторизацией через внешний сервис и получением данных по API с других серверов. Было решено создать мобильное приложение для личного кабинета. В функционал приложения должно входить:

  • просмотр и редактирование профиля
  • просмотр информации, хранящейся в инфоблоках

В общих чертах приложение должно работать следующим образом:

  1. На стороне приложения формируем запрос, принимаем ответ и рендерим его;
  2. На стороне Битрикса мы принимаем GET запрос, отдаем json в ответе;

Начнем работу с Битрикса. Сначала необходимо создать структуру файлов. У меня получилось примерно так:

/API/profile.php
/API/projects/index.php

В файле profile.php размещается функционал просмотра/редактирования профиля. Внутри располагается обычная страница, вида:


<?require($_SERVER["DOCUMENT_ROOT"]." /bitrix/header.php");?>
	текст страницы
<?require($_SERVER["DOCUMENT_ROOT"]." /bitrix/footer.php");?>

В тексте страницы размещен компонент отображения профиля. В моем случае не коробочный компонент, но это не важно. Для примера разместим штатный компонент Битрикса:

 

Способом, описанным ниже, можно будет преобразовать любой компонент для использования в мобильном приложении.

В /projects/index.php разместим комплексный компонент «новости». В настройках компонента очень важно настроить ЧПУ, для генерации страниц, вида /projects/123, где 123 — id материала. В статье я не буду на этом останавливаться т.к. на сайте Битрикса есть исчерпывающая документация.

После создания структуры, нам надо настроить отображение страниц, т. к. сейчас они отображаются с шаблоном сайта, нам же нужен контент в формате json. Первым шагом создаем новый шаблон. Назовем его API. В начале файла header.php определим заголовки ответа:


header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST');
header('Access-Control-Allow-Headers:accept, api_key, api_id');

В первой строки говорим что в ответе будет json. Во второй разрешаем присылать запросы с другого домена, в третьей разрешаем методы. Четвертая строчка необходима для авторизации.

На процессе авторизации хочу остановиться немного подробнее. У портала, для которого разрабатывалось приложение, есть внешняя авторизация, а встроенная в Битрикс по факту не используется. Другими словами пользователь даже не знает пароль от своего личного кабинета, он всегда авторизуется через внешний сервис. Для реализации механизмов авторизации и синхронизации написан отдельный модуль. Сам модуль нам не интересен, от него нам надо знать только то, что у пользователя есть 2 дополнительных поля: UF_API_ID и UF_API_KEY. Оба данных параметра пользователь может посмотреть на своей странице в личном кабинете. Исходя из этого наша стратегия авторизации будет примерно следующей:

  • читаем полученные заголовки
  • в соответствии с заголовками, ищем пользователя
  • если поле с ключом соответствует заголовку, авторизуем

Вот рабочий код всего выше сказанного:


function getUser($runetId){
	$filter = array("UF_API_ID" => $APIId,);
	$rsUsers = CUser::GetList(($by="LAST_NAME"), ($order="asc"), $filter, ["SELECT"=>['UF_*']]);
	$user = $rsUsers->fetch();
	return [$user['ID'], $user['UF_API_KEY']];
}

global $USER;
if (!$USER->IsAuthorized()){
	$headers = getallheaders();
	$user = getUser($headers['API_ID']);
	if ($user['API_KEY'] && $user['API_KEY'] == $headers['API_KEY']){
		$USER->Authorize($user['ID']);
	}
}

Разместим его в шаблоне, сразу после заголовков, а после него проверку и вывод ошибки:


if (!$USER->IsAuthorized()){
	echo '{"page":{"id":1, "title":"error", "content":"Wrong api key or id"}}';
	die;
}

Небольшое отступление. Я привел код прототипа авторизации, который корректно работает. В реальности код другой и силь