Авторизация и регистрация по номеру телефона в Bitrix

Всем привет. У меня новый квест) За долгое время работы с битриксом приходилось реализовывать много чего, но вот с подключением MessageService по смс работать не приходилось.
На просторах интернета не много информации по этому вопросу, и та, что есть не работает как нужно, а часто вообще не работает.

Итак начнем!

Для подключения провайдера смс вам конечно же необходимо сначала протестировать api отправки смс на чистом php без битрикса, так я и сделал. Обычно это soap/curl или работа через сокеты и если ваш провайдер предоставляет библиотеку с которой нужно работать - это отлично. В основном предлагается библиотека QTSMS.class.php, при чем в разных источниках она совершенно разная, начиная от названий класса и методов и заканчивая самой логикой работы. Я скачал библиотеку которая по заверениям совместима с новым api для версий php 7.4, но я использовал старую версию api. Сама работа по отправке смс находится в файле Src/SmsClient.class.php (вся библиотека будет прикреплена к статье), и как мы видим на 222 строчке отправка выполняется через curl.

<?php private function connectSettings() { $protocol = !empty($this->protocol) ? $this->protocol.'://' : ''; $path = !empty($this->path) ? $this->path : ''; $url = $protocol . $this->hostname . $path; curl_setopt_array($this->ch, [ CURLOPT_URL => $url, CURLOPT_HEADER => FALSE, CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_HTTPHEADER => $this->buildHeaders(), CURLOPT_RETURNTRANSFER => TRUE, CURLOPT_FOLLOWLOCATION => FALSE, CURLOPT_USERAGENT => 'AISMS PHP class', ]); } ?>

Хотелось бы пояснить, что целью данной статьи не является разбор именно создания скрипта отправки смс под определенный сервис, а только подключение своего MessageService по отправке смс.
Итак, скачиваем архив с библиотекой и распаковываем в директорию /bitrix/php_interface/sms/ или /local/php_interface/sms/, я специально не стал называть директорию lib или vendor и т.д.,как принято в битриксе или для загрузки из composer, чтобы по названию было сразу понятно, что там лежит. Если же у вас уже существуют данные директории и в них много библиотек, то конечно же размещайте файлы архива так /bitrix/php_interface/lib/sms/ или /local/php_interface/lib/sms/
Далее в этой же директории sms создаем файл, например index.php и заполняем его кодом класса, который и будет нашим sms MessageService.
На данный момент это рабочий класс для работы с \Bitrix\Main\Sms\Event, в будущем конечно же возможны изменения в названиях методов да и в принципе построения логики sms MessageService.

<?php namespace MyProvider\MessageService; use Bitrix\Main\Application; use Bitrix\Main\Error; use Bitrix\Main\Result; use Bitrix\Main\Web\HttpClient; use Bitrix\Main\Web\Json; use Bitrix\Main\Loader; use Bitrix\MessageService\Sender\Result\MessageStatus; use Bitrix\MessageService\Sender\Result\SendMessage; use Bitrix\MessageService; // название класса может быть любым, только именно этот класс вам нужно будет подключить в обработчике собятия отправки в файле init.php class Smska extends \Bitrix\MessageService\Sender\Base { public $user='*****'; public $pass='*****'; public $host='*****'; public $servesename = '*****'; public static function isSupported() { return true; } public function getId() { return 'я писал здесь просто латинское слово без пробелов'; } public function getName() { return "полное название смс провайдера"; } public function getShortName() { return 'краткое название или адрес домена сервиса'; } public function isDemo() { return false; //есть ли демо период, оставляем так } public function canUse() { return true; //включен или выключен ваш сервис, ниже будет проверка (*) } //этот метод для парсинга атридутов xml объектов, так как мне на выход приходил именно xml объект, если вам он не нужен, можете смело удалять public function xmlAttribute($object, $attribute){ if(isset($object[$attribute])) return (string) $object[$attribute]; else return null; } //основной метод работы провайдера, отправляет смс public function sendMessage(array $messageFields) { //здесь проверяем свой же метод выше (*), если получаем false, то выводим сообщение о том, что сервис отключен if (!$this->canUse()) { $result = new SendMessage(); //это основной класс с методами проверки ответов и параметрами сохранения результатов $result->addError(new Error('Ошибка отправки. СМС-сервис отключен')); //передаем именно объект new Error, строковые значения этот метод не признает return $result; } //выполняем подключение нашего класса библиотеки и передаем в него наши свойства (логин,пароль и хост (хост обычно полный вместе с https:// с полным адресом для http запросов)) $sms = new \QTSMS($this->user, $this->pass, $this->host); $return = new SendMessage(); //подключаем здесь основной класс с методами проверки ответов и параметрами сохранения результатов $result = $sms->post_message($messageFields['MESSAGE_BODY'], $messageFields['MESSAGE_TO'], $this->servesename); //отправляем нашу смс //дальше что-то делаем с результатом для понимания дошла смс или нет, к этому этапу вы уже должны протестировать на "чистом php" обработку результата, что он вам дает при ошибке и при отправке ##### это все логика работы именно вашего сервиса, пишите свою или используйте эту, если она вам подойдет /* $xml = new \SimpleXMLElement($result);//у меня приходит xml поэтому я перевожу его в объект $status = $this->xmlAttribute($xml->result,'*****'); //здесь получаю атрибут $result_status = $sms->status_sms_group_id($status); //проверяю статус отправилось или нет $r_xml = new \SimpleXMLElement($result_status);//у меня приходит xml поэтому я опять перевожу его в объект $id = $this->xmlAttribute($r_xml->*****,'*****'); //получаю id записи */ //проверяем вашу переменную , которая скажет отправлено смс или нет, у меня это id записи при успешной отправке if(isset($id) && (int)$id>0){ $return->setExternalId($id); //пишем уникальный номер отправления, если у вас его нет можете писать любое большое рандомное число $return->setAccepted(); //говорим, что все ok sms отправлена } else{ $return->addError(new Error('Ошибка отправки')); //если что-то пошло не так записываем ошибку, она будет выведена пользователю } return $return; } //через этот метод мы работаем с нашим классом как с объектом (используется в init.php) public static function onGetSmsSenders() { $class = __CLASS__; return [new $class()]; } //имя отправителя, обязательно, если их будет несколько в административной панели вы сможете выбрать public function getFromList() { return [$this->servesename]; } } ?>

Далее открываем или создаем, если еще не создан файл /bitrix/php_interface/init.php или /local/php_interface/init.php
Добавляем в него обработчик события отправки смс и подключаем к нему наш класс
У меня после подключения вывалилась ошибка "класс \Bitrix\MessageService\Sender\Base не найден", возможно это связано с конфигурацией моего проекта и у вас все заработает, но если нет подключайте файл с двумя звездочками (**)

<? include_once($_SERVER['DOCUMENT_ROOT'].'/bitrix/modules/messageservice/lib/sender/base.php'); // файл с двумя звездочками (**) без него может ничего не заработать, видимо у битрикса проблема с автоподгрузкой классов в этом пространстве имен include_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/php_interface/sms/QTSMS.class.php'); //подключаем нашу библиотеку include_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/php_interface/sms/test_config.php'); // он понадобится нам в файле ajax авторизации (необходимо заполнить вашими доступами (логин, пароль, адрес)) include_once($_SERVER['DOCUMENT_ROOT'].'/bitrix/php_interface/sms/index.php'); // подключаем наш обработчик // вызов обработсика нашего события $eventManager = \Bitrix\Main\EventManager::getInstance(); $eventManager->addEventHandler( "messageservice", "onGetSmsSenders", array( MyProvider\MessageService\Smska::class, "onGetSmsSenders", ) ); ?>

Все сохраняем и переходим по ссылке вашсайт/bitrix/admin/settings.php?lang=ru&mid=main&mid_menu=1#authorize
Переходим на вкладку "Почта и СМС" и ставим нашу службу как "Служба отправки СМС по умолчанию", а также выбираем номер отправителя по умолчанию
Теперь переходим к самому главному: в битриксе нет авторизации по смс в стандартном виде, например в компоненте регистрации по адресу вашсайт/bitrix/admin/fileman_file_edit.php?path=%2Fbitrix%2Fcomponents%2Fbitrix%2Fmain.register%2Fcomponent.php&full_src=Y&site=s1&lang=ru&&filter=Y&set_filter=Y
на 220 строчке вы найдете подключение провайдера смс.

<? $sms = new \Bitrix\Main\Sms\Event( "SMS_USER_CONFIRM_NUMBER", [ "USER_PHONE" => $phoneNumber, "CODE" => $code, ] ); ?>

А в компонентах вашсайт/bitrix/admin/fileman_file_edit.php?path=%2Fbitrix%2Fcomponents%2Fbitrix%2Fsystem.auth.form%2Fcomponent.php&full_src=Y&site=s1&lang=ru&&filter=Y&set_filter=Y или вашсайт/bitrix/admin/fileman_admin.php?PAGEN_1=1&SIZEN_1=20&lang=ru&site=s1&path=%2Fbitrix%2Fcomponents%2Fbitrix%2Fmain.auth.form%2F&del_filter=Y&find_name=auth нет, возможно в битриксе есть какие-то специальные компоненты для этого, но я их не нашел, да и выводить в публичной части необходимо в рамках шаблона компонента формы авторизации, так что в любом случае придется переписывать.
Нам понадобится файл кастомного шаблона авторизации вашсайт/bitrix/admin/fileman_file_edit.php?path=%2Fbitrix%2Ftemplates%2F(ваш_шаблон_сайта)%2Fcomponents%2Fbitrix%2Fsystem.auth.form%2Fmain%2Ftemplate.php&full_src=Y&site=s1&lang=ru&&filter=Y&set_filter=Y у вас может быть другой.
У меня на строчке 110 после

<div class="form_footer"> <div class="filter block">

Добавляю

<div class="auth_sms"> <label for="auth_sms" title="Войти по номеру телефона" tabindex="5">Войти по номеру телефона</label> </div>

Также на строчке 39 после

<input type="hidden" name="AUTH_FORM" value="Y" /> <input type="hidden" name="TYPE" value="AUTH" /> <input type="hidden" name="POPUP_AUTH" value="<?=$arParams['POPUP_AUTH']?>" />

Добавляю

<div class="form_sms"> <label>Введите номер телефона</label> <input type="tel" class="phone_sms" name="sms_phone" autocomplete="tel"> <input type="button" class="send_sms" value="Получить СМС"> </div> <div class="form_sms2"> <label>Введите код из смс</label> <input type="tel" class="sms_code" name="sms_code" autocomplete="tel"> <input type="button" class="auth_sms" value="Войти"> </div>

Открываем кастомный файл js скриптов вашсайт/bitrix/admin/fileman_file_edit.php?path=%2Fbitrix%2Ftemplates%2F(ваш_шаблон_сайта)%2Fjs%2Fcustom.js&site=s1&lang=ru&&filter=Y&set_filter=Y#authorize
и добавляем jquery код

$(document).on('click','[for="auth_sms"]',function(){ $('.form_sms').show(500); $('.form_body').hide(300); $(".phone_sms").inputmask({"mask": "+7 (999) 999-99-99"}); $(this).html('Войти с помощью логина'); $(this).attr('for',"auth_login"); $('.form_footer .buttons.clearfix').hide(); }); $(document).on('click','[for="auth_login"]',function(){ $('.form_sms').hide(300); $('.form_sms2').hide(300); $('.form_body').show(500); $(this).html('Войти по номеру телефона'); $(this).attr('for',"auth_sms"); $('.form_footer .buttons.clearfix').show(); }); $(document).on('click','.send_sms',function(){ $('.form_footer .buttons.clearfix').hide(); var tel_auth = $('.phone_sms').val(); if(tel_auth!=''){ $.ajax({ type: "POST", url: "/ajax/script/sms.php", data: {number_login:tel_auth}, success: function(data){ if(data=='yes'){ $('.form_sms').hide(300); $('.form_sms2').show(500); } else if(data=='no-user'){ $('.form_sms label').html('Введите номер телефона <span class="red-not">Пользователь с таким номером не найден</span>'); } else{ $('.form_sms label').html('Введите номер телефона <span class="red-not">Ошибка отправки СМС</span>'); } } }); } else{ $('.form_sms label').html('Введите номер телефона <span class="red-not">Пустое поле телефона</span>'); } $(this).html('Войти по номеру телефона'); $(this).attr('for',"auth_sms"); }); $(document).on('click','.auth_sms',function(){ $('.form_footer .buttons.clearfix').hide(); var code = $('.sms_code').val(); if(code!=''){ $.ajax({ type: "POST", url: "/ajax/script/auth_sms.php", data: {code:code}, success: function(data){ if(data=='yes'){ document.location.href = '/personal/'; } else if(data=='no-code'){ $('.form_sms2 label').html('Введите код из смс <span class="red-not">Пустое поле</span>'); } else{ $('.form_sms2 label').html('Введите код из смс <span class="red-not">Неверный код</span>'); } } }); } else{ $('.form_sms2 label').html('Введите код из смс <span class="red-not">Пустое поле</span>'); } });

не забудьте подключить библиотеку для маски телефона и указать в ready

$(document).ready(function(){ $(".phone_sms").inputmask({"mask": "+7 (999) 999-99-99"}); });

Открываем кастомный файл стилей вашсайт/bitrix/admin/fileman_file_edit.php?path=%2Fbitrix%2Ftemplates%2F(ваш_шаблон_сайта)%2Fcss%2Fcustom.css&site=s1&lang=ru&&filter=Y&set_filter=Y
И добавляем наши стили, у вас могут быть свои

/*auth form sms*/ .auth_sms label { color: #198ac8 !important; cursor: pointer; } .form_sms label,.form_sms2 label{ color: #888888; display: block; } .form_sms,.form_sms2 { margin: 0; padding: 29px 60px 8px; display:none; } input.phone_sms,input.sms_code { padding: 8px 13px 7px; width: 100%; height: 48px; } input.send_sms,input.auth_sms { background-color: #1d9de3; border-color: #1d9de3;font-size: 0.7333em; font-weight: normal; text-transform: uppercase; text-decoration: none; margin: 0px; border: 0px solid; letter-spacing: 0.8px; border-radius: 3px; padding: 12px 21px 11px; overflow: hidden; transition: background-color 0.3s ease; -moz-transition: background-color 0.3s ease; -ms-transition: background-color 0.3s ease; -o-transition: background-color 0.3s ease; -webkit-transition: background-color 0.3s ease;color: #fff;margin-top: 20px; } span.red-not { color: red; display: block; border-bottom: 1px dashed; width: max-content; margin-top: -5px; margin-bottom: 5px; } /*--*/

Теперь создаем наши php файлы для авторизации в директории /ajax/script/ (у вас может быть своя, для установки своей директории внесите изменения в кастомный файл js):
Файл sms.php:

<?php session_start(); ini_set('max_execution_time', 20000); require_once($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_before.php"); /*ini_set('error_reporting', E_ALL); //можете раскомментировать для тестирования ошибок в консоли браузера на вкладке network->Fetch/XHR ini_set('display_errors', 1); ini_set('display_startup_errors', 1);*/ function xmlAttribute($object, $attribute){ if(isset($object[$attribute])) return (string) $object[$attribute]; else return null; } $sms = new QTSMS($cfg['login'], $cfg['password'], $cfg['host']); $rand = mt_rand(0,9).mt_rand(0,9).mt_rand(0,9).mt_rand(0,9).mt_rand(0,9); //создаем рандомный код для смс $_SESSION['rand_sms'] = $rand; //сохраняем его в сессию $sender_name = 'имя отправителя'; //проверяем передали ли нам номер телефона (меняется в кастомном файле js) if(isset($_POST['number_login'])){ $phoneNumber = $_POST['number_login']; // проверяем есть ли пользователь с таким телефоном $filter = Array("PERSONAL_PHONE"=>$phoneNumber); $rsUsers = CUser::GetList(($by="personal_country"), ($order="desc"), $filter); while($arUser = $rsUsers->Fetch()){ $user_id = $arUser['ID']; } if(isset($user_id)){ // если найден записываем его id в сессию по коду из смс $_SESSION['USER_ID_AUTH'][$_SESSION['rand_sms']] = $user_id; //чистим номер от лишних символов, чтобы отправить смс $phoneNumber = str_replace('+7','8',$phoneNumber); $phoneNumber = preg_replace('#([^0-9]+)#','',$phoneNumber); // отправляем смс $result = $sms->post_message($rand, $phoneNumber, $sender_name); /* $xml = new SimpleXMLElement($result);//у меня приходит xml поэтому я перевожу его в объект $status = $this->xmlAttribute($xml->result,'*****'); //здесь получаю атрибут $result_status = $sms->status_sms_group_id($status); //проверяю статус отправилось или нет $r_xml = new SimpleXMLElement($result_status);//у меня приходит xml поэтому я опять перевожу его в объект $id = $this->xmlAttribute($r_xml->*****,'*****'); //получаю id записи */ if((int)$id>0){ echo 'yes'; } else{ echo 'no'; } } else{ echo 'no-user'; } } else{ echo 'no'; }

Файл auth_sms.php:

<?php session_start(); ini_set('max_execution_time', 20000); require_once($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_before.php"); if(isset($_POST['code'])){ if(isset($_SESSION['USER_ID_AUTH'][$_POST['code']])){ global $USER; $USER->Authorize($_SESSION['USER_ID_AUTH'][$_POST['code']]); echo 'yes'; } else{ echo 'no'; } } else{ echo 'no-code'; }

Вот и все!!! Желаю вам успехов в разработке)

11
Начать дискуссию