Авторизация и регистрация по номеру телефона в Bitrix
Всем привет. У меня новый квест) За долгое время работы с битриксом приходилось реализовывать много чего, но вот с подключением MessageService по смс работать не приходилось. На просторах интернета не много информации по этому вопросу, и та, что есть не работает как нужно, а часто вообще не работает.
2110просмотров
Итак начнем!
Для подключения провайдера смс вам конечно же необходимо сначала протестировать api отправки смс на чистом php без битрикса, так я и сделал. Обычно это soap/curl или работа через сокеты и если ваш провайдер предоставляет библиотеку с которой нужно работать - это отлично. В основном предлагается библиотека QTSMS.class.php, при чем в разных источниках она совершенно разная, начиная от названий класса и методов и заканчивая самой логикой работы. Я скачал библиотеку которая по заверениям совместима с новым api для версий php 7.4, но я использовал старую версию api. Сама работа по отправке смс находится в файле Src/SmsClient.class.php (вся библиотека будет прикреплена к статье), и как мы видим на 222 строчке отправка выполняется через curl.
Хотелось бы пояснить, что целью данной статьи не является разбор именно создания скрипта отправки смс под определенный сервис, а только подключение своего 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 строчке вы найдете подключение провайдера смс.
А в компонентах вашсайт/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 после
Открываем кастомный файл 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
Открываем кастомный файл стилей вашсайт/bitrix/admin/fileman_file_edit.php?path=%2Fbitrix%2Ftemplates%2F(ваш_шаблон_сайта)%2Fcss%2Fcustom.css&site=s1&lang=ru&&filter=Y&set_filter=Y И добавляем наши стили, у вас могут быть свои
Теперь создаем наши 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';
}