Организация API + REST

Примеры

Здесь приведены примеры обработчиков запросов и самиз запросов с клиентской стороны (в браузере пользователя). В примерах приведены примеры для варианта размещения обарботика модуля в директории относительно корня сайта - /api/

Обновление captcha

Создаем файл /api/user/get_captcha.php со следующим содержимым

<?if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) {
   die();
}

$sid = $APPLICATION->CaptchaGetCode();

$this->setResult(array(
    'sid' => $sid,
    'src' => '/bitrix/tools/captcha.php?captcha_sid=' . $sid
));

Для клиентской стороны добалвять скрипт делающий запрос к api (урезали логику до запроса) и получения данных дял замены капчи без перезагрузки страницы. При этом в самой форме нужно подменить не только саму картинку но и заменить в скрытом полей идентификаторо капчи чтобы при отправке данных капча была верной

//... 
$.ajax({    url: '/api/',
    type: 'POST',
    dataType: 'json',
    data: {
        sessid: BX.bitrix_sessid(),
        method: 'user.getCaptcha'
    },
    error: function (r) {
        
    },
    success: function (r) {
        
        if (!!r.response) {
            
             alert(r.response.sid);
            
        }
        else if (!!r.error) {
            console.log('error', r.error.error_msg);           
        }
    }
});

Подписать пользователя на рассылку

Если у вас есть модуль подписки и рассылки и вам необходимо сделать подписку пользваотеля на AJAX без перезагрузки страницы, то с помощью модуля это сделать можно следующим образом. Саму форму описывать не будем, важно отметить что должно присутствовать поле email и идентификатор рассылки (рубрики - id)

С клиентской стороны

// фактически данные надо будет взять из формы
var rubricId = 1; //
var email = 'test@mail.ru';

// можем сразу провести валидацию
if (!!email.match(/^[\w\d_\.\-]+@[\w\d\-]+\.[a-z]{2,4}$/i) == false) { 
  alert('Вы не верно указали адрес электронной почты');
    return false;
}

$.ajax({    url: '/api/',
    type: 'POST',
    dataType: 'json',
    data: {
        sessid: BX.bitrix_sessid(),
        method: 'subscribe.sign',
       email: email,
       id: rubricId
    },
    error: function (r) {
        
    },
    success: function (r) {
        
        if (!!r.response) {
            
             alert(r.response.msg);
            
        }
        else if (!!r.error) {
            alert(r.error.msg);         
        }
    }
});

Обработчик запроса для серверной стороны в файле - /api/subscribe/sign.php с содержимым

<? if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) {
    die();
}

  global $APPLICATION;

// Подписка на рассылку

/**
* @var $this \Bxmaker\Api\Handler
*/

if (!CModule::IncludeModule('subscribe')) {
    $this->setError('Не установлен модуль подписки, рассылки', 4, array());
    return false;
}

if (!$this->get('id') || intval($this->get('id')) <= 0) {
    $this->setError('Не получен дентификатор рассылки', 4, array());
    return false;
}

if (!$this->get('email') || !preg_match('/^[\d\w\-\.]+@[\w\d\-\.]+\.[a-z]{2,4}$/i', $this->get('email'), $match)) {
    $this->setError('E-mail указан не верно', '2');
    return false;
}


$id = intval($this->get('id'));
$email = $this->get('email');

$dbrRubric = CRubric::GetList(array("SORT" => "ASC", "NAME" => "ASC"), array(
    "ACTIVE" => "Y",
    "LID" => LANG,
    "ID" => intval($this->get('id')),
    "VISIBLE" => 'Y'
));
if (!$arRubric = $dbrRubric->Fetch()) {
    $this->setError('Рассылка не найдена', 4, array());
    return false;
}

//get current user subscription from cookies
$arRubrics = array();
$oSubscribtion = new CSubscription;
$arSubscribe = $oSubscribtion->GetUserSubscription();
if (!!$arSubscribe['ID'] && $arSubscribe['EMAIL'] == strtolower($email)) {
    //повторная отправка
    if ($arSubscribe['CONFIRMED'] != 'Y') {
       $oSubscribtion->ConfirmEvent($arSubscribe['ID'], SITE_ID);
    }

    $arRubrics = $oSubscribtion->GetRubricArray($arSubscribe['ID']);

    if (!in_array($id, $arRubrics)) {
        // добавляем
        $arRubrics[] = $id;

        $oSubscribtion->Update($arSubscribe['ID'], array(
             "RUB_ID" => $arRubrics
        ));
    }

    $this->setResult(array(
        'msg' => 'Вы успешно подписаны!',
        'email' => $email,
        'rubric_id' => $id
    ));

    return true;
}


// добавляем подписку
$arFields = Array(
    "USER_ID" => ($USER->IsAuthorized() ? $USER->GetID() : false),
    "FORMAT" => "html",
    "EMAIL" => $email,
    "ACTIVE" => "Y",
    "RUB_ID" => array($id),
    "CONFIRMED" => "N",
    "SEND_CONFIRM" => "Y",
);

//can add without authorization
$ID = $oSubscribtion->Add($arFields);
if ($ID > 0) {
    $oSubscribtion->Authorize($ID);


    $this->setResult(array(
        'msg' => 'Вы успешно подписаны!',
        'email' => $email,
        'rubric_id' => $id
    ));
}
else {
    $this->setError($oSubscribtion->LAST_ERROR, '2');
    return false;
}

Отключение проверки sessid для метода

Бывают случаи когда не требуется проверка сессионных данных, для таких случаев существует соответствующий метод - setSkipMethodSessidControl, в который передается массив методов. Как полные пути, так и группы. В примере ниже исключения добавлены для следующих методов.

Правило: data.mix - проверка sessid не будет производиться для запроса, в котором method=data.mix, но будет производиться для запросов в которых method=data.mix.add, method=data.mix.update, method=data.mix.get и тд

Правило: data.mix.* - проверка sessid не будет производиться для запросов в которых method=data.mix.add, method=data.mix.update, method=data.mix.get и тд

Файл /api/index.php

<? require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php');

if (\Bitrix\Main\Loader::includeModule('bxmaker.api')) {
   
   $oApi = new \Bxmaker\Api\Handler(array('DIR' => dirname(__FILE__)));
    $oApi->setParam(array(
         'IBLOCK_ID_OTZIV' => 1,
         'IBLOCK_ID_IDEA' => 4,
         'IBLOCK_ID_MIX' => 7,
         'IBLOCK_ID_BRON' => 5,
         'IBLOCK_ID_STORAGE' => 9
    ));

    $oApi->setSkipMethodSessidControl(array(
         'data.idea.*',
         'data.mix'
    ));

    $oApi->init();

    $oApi->showResult();

} 
else {
    echo json_encode(array( 'error' => array(
        'msg' => 'Модуль обработки запросов не установлен',
        'code' => 0,
        'more' => array()
    )));
}

Авторизация

В данном случае рассмотрим вариант, когда необходимо сделать атворизацию польвзовтаеля в Битркисе через ajax. Этот вараинт совсем примитивный, не учитывающий необходимость запросить captcha.

Для простой реализации авторизации с учетом необходимости запроса кода с картинки или подтверждения номера телефона кодом из смс, стоит исопльзвоать модуль Авторизации по номеру телефона, в котором реализованы методы для этих задач, и написать обработчики для ajax будет проще простого.

На клиентской стороне запрос будет выглядеть так

$.ajax({    url: '/api/',
    type: 'POST',
    dataType: 'json',
    data: {
        sessid: BX.bitrix_sessid(),
        method: 'user.auth',
       login : $('input[name="login"]').val(),
       password : $('input[name="password"]').val()
    },
    error: function (r) {
        
    },
    success: function (r) {
        
        if (!!r.response) {
            
               location.reload();
            
        }
        else if (!!r.error) {
            alert( r.error.error_msg);           
        }
    }
});

Для серверной стороны добавляем файл /api/user/auth.php

<?if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) {
   die();
}

if (!$this->get('login') || strlen(trim($this->get('login'))) < 1) {
    return $this->setError('Укажите логин или email!', '1');
}

if (!$this->get('password') || strlen(trim($this->get('password'))) < 1) {
    return $this->setError('Укажите пароль!', '1');
}


$arAuthResult = $USER->Login($this->get('login'), $this->get('password'), "Y");
if(isset($arAuthResult['TYPE']) && $arAuthResult['TYPE'] == 'ERROR')
{
    $this->setError($arAuthResult['MESSAGE'], 3);
}
else
{
    $this->setResult(array(
        'msg' => 'Вы успешно авторизованы!'
    ));
}