Office - авторизация и регистрация через sms c одной формы
Кейс:
Клиент очень хотел, чтобы у него на странице входа, как у служб доставки, было одно поле — номер телефона. И всё. То есть, если ты новый — ты регистрируешься, если уже юзер — входишь.
Если с авторизацией через email такое можно заставить работать из коробки, то с телефоном пришлось помудрить. Далее — пошаговое описание решения.
1. Контроллер
В папке core/components/office/controllers/ создаём свой класс-роутер authext.class.php. Он расширяет дефолтный Auth, и его задача определить, новый ты юзер или нет, и исходя из этого отправить тебя либо на авторизацию, либо на регистрацию. При чем, он должен учитывать, что если ты новый юзер, но уже передаешь код активации из sms — все равно должен быть отправлен на регистрацию, хотя объект пользователя уже создан. Это я проверяю через параметр active:
2. Вызов сниппета и чанк формы
В вызове сниппета указываем свой контроллер, свой чанк входа, редирект на лк вместо чанка выхода, свой чанк сообщения о регистрации:
В чанке формы оставляем два поля: mobilephone и скрытый phone_code, а также указываем свой контроллер и его метод в поле action:
В чанке sms о регистрации убираем информацию о пароле:
3. Правка в JS
Теперь делаем так, чтобы при в воде номера на кнопке была надпись «Выслать код», а при вводе кода — «Войти». В настройку office_auth_frontend_js прописываем свой файл: [[++assets_url]]components/office/js/auth/custom.js. В него копируем код из default.js и слегка его модифицируем, строка (на данный момент) 54:
Профит.
Теперь пользователь в любом случае попадает на сайт, имея только номер телефона и одну sms, независимо от того, регистрировался он до этого или нет. Отличие только в тексте получаемой смски.
В моем случае еще требовалось, чтобы при регистрации в лк не были заполнены поля email и fullname (office их по умолчанию забивает фейковыми данными), пока пользователь сам туда что-то не впишет. Это решается редактированием настройки office_profile_required_fields (убираем оттуда всё, оставляем mobilephone) и плагина officeProfile (лучше его скопировать и работать с копией, а оригинал отключить) — в этом плагине комментируем примерно с 16 строки:
Вуаля.
Клиент очень хотел, чтобы у него на странице входа, как у служб доставки, было одно поле — номер телефона. И всё. То есть, если ты новый — ты регистрируешься, если уже юзер — входишь.
Если с авторизацией через email такое можно заставить работать из коробки, то с телефоном пришлось помудрить. Далее — пошаговое описание решения.
1. Контроллер
В папке core/components/office/controllers/ создаём свой класс-роутер authext.class.php. Он расширяет дефолтный Auth, и его задача определить, новый ты юзер или нет, и исходя из этого отправить тебя либо на авторизацию, либо на регистрацию. При чем, он должен учитывать, что если ты новый юзер, но уже передаешь код активации из sms — все равно должен быть отправлен на регистрацию, хотя объект пользователя уже создан. Это я проверяю через параметр active:
<?php
if (!class_exists('officeAuthController')) {
include 'auth.class.php';
}
/**
* Class officeAuthExtController
*/
class officeAuthExtController extends officeAuthController
{
public function formLoginOrRegister (array $data)
{
if (
!$profile = $this->checkLogin($data) or !($profile instanceof modUserProfile) // нет такого профиля
or (!$profile->User->active and !empty($data['phone_code'])) // профиль неактивен, а в запросе есть код из sms
) {
$data['username'] = $this->office->checkPhone(@$data['mobilephone']);
return $this->formRegister($data);
} else {
return $this->formLogin($data);
}
}
}
return 'officeAuthExtController';
2. Вызов сниппета и чанк формы
В вызове сниппета указываем свой контроллер, свой чанк входа, редирект на лк вместо чанка выхода, свой чанк сообщения о регистрации:
{'!office'|snippet:[
'action' => 'authext',
'groups' => 'Customer',
'HybridAuth' => false,
'tplLogin' => 'login',
'tplLogout' => '@INLINE {$_modx->sendRedirect("office_profile_page_id"|option|url)}',
'tplRegister' => 'register_sms'
]}
В чанке формы оставляем два поля: mobilephone и скрытый phone_code, а также указываем свой контроллер и его метод в поле action:
<div id="office-auth-form">
<form action="{$_modx->resource.id|url}" method="post">
<div class="form-group">
<label style="display: block;">
<input type="text" name="mobilephone" class="form-control" placeholder="Ваш телефон">
</label>
</div>
<div class="form-group hidden">
<label style="display: block;">
<input type="text" name="phone_code" class="form-control" placeholder="Введите код" readonly>
</label>
</div>
<div class="form-group">
<input type="hidden" name="action" value="authExt/formLoginOrRegister">
<input type="hidden" name="return" value="">
<button type="submit" class="btn btn-primary">Выслать код</button>
</div>
</form>
</div>
В чанке sms о регистрации убираем информацию о пароле:
{var $lang = $_modx->config.cultureKey}
{if $code?}
{if $lang == 'en'}
You registered on {'site_name'|option}. Your activation code: {$code}.
{else}
Вы зарегистрировались на {'site_name'|option}. Ваш код активации: {$code}.
{/if}
{/if}
3. Правка в JS
Теперь делаем так, чтобы при в воде номера на кнопке была надпись «Выслать код», а при вводе кода — «Войти». В настройку office_auth_frontend_js прописываем свой файл: [[++assets_url]]components/office/js/auth/custom.js. В него копируем код из default.js и слегка его модифицируем, строка (на данный момент) 54:
if (response.data['sms'] != undefined) {
if (response.data['sms'] == 1) {
$form.find('input').attr('readonly', true);
$form.find('[name="phone_code"]').attr('readonly', false)
.parents('.hidden').removeClass('hidden').addClass('not-hidden');
$form.find('[type="submit"]').text('Войти');
} else {
$form.find('input').attr('readonly', false);
$form.find('[name="phone_code"]').attr('readonly', true)
.parents('.not-hidden').removeClass('not-hidden').addClass('hidden');
$form.find('[type="submit"]').text('Выслать код');
}
}
Профит.
Теперь пользователь в любом случае попадает на сайт, имея только номер телефона и одну sms, независимо от того, регистрировался он до этого или нет. Отличие только в тексте получаемой смски.
В моем случае еще требовалось, чтобы при регистрации в лк не были заполнены поля email и fullname (office их по умолчанию забивает фейковыми данными), пока пользователь сам туда что-то не впишет. Это решается редактированием настройки office_profile_required_fields (убираем оттуда всё, оставляем mobilephone) и плагина officeProfile (лучше его скопировать и работать с копией, а оригинал отключить) — в этом плагине комментируем примерно с 16 строки:
// if (!in_array('email', $required)) {
// $required[] = 'email';
// }
Помимо этого, создаем свой плагин на событие OnUserBeforeSave, обманывающий родной процессор modx, который не разрешает юзеру не иметь email:<?php
switch ($modx->event->name) {
case 'OnUserBeforeSave':
if ($mode == 'new') {
$user->Profile->set('email', '');
$user->Profile->set('fullname', '');
}
break;
}
Вуаля.
Комментарии: 9
Я как-то по проще сделал, в коде не менял ничего. Вход и регистрация по коду из смс. Один минус – две вкладки, зато при обновлении офиса ничего не слетит.
примеры кода в студию
1. статья имеет в названии условие «С ОДНОЙ ФОРМЫ», а не с двух вкладок. разница принципиальна. то что ты сделал и делать-то особо не надо — лишние поля вырезать из чанков только.
2. а что, пардон, у меня слетит при обновлении?)
2. а что, пардон, у меня слетит при обновлении?)
1.
2.
P.s. Если тебе написали комментарий не содержащий похвалы и оваций, не стоит сразу камнями кидаться, не обязательно тебя хотели как-то задеть.
лишние поля вырезать из чанков только.Именно так я и сделал. И да, у меня два поля, и это минус.
2.
а что, пардон, у меня слетит при обновлении?)Если ничего, то я с удовольствием использую твой вариант, потому, что он очевидно круче.
P.s. Если тебе написали комментарий не содержащий похвалы и оваций, не стоит сразу камнями кидаться, не обязательно тебя хотели как-то задеть.
это не камни, это глухая оборона, ибо обесценивается проделанный труд. извини за резкость, тоже не хотет ругаться.
ничего не накроется. только плагин officeProfile надо будет заново деактивировать
ничего не накроется. только плагин officeProfile надо будет заново деактивировать
Что-то у меня не выходит. С формой в модальном окне не будет работать?
будет, но форма должна быть внутри div#office-auth-form
у office вместо логина или email можно войти и с телефоном?
Просто мне пишет пользователь не найден, хотя телефон в mobilephone есть…
Просто мне пишет пользователь не найден, хотя телефон в mobilephone есть…
Очень крутой кейс. Спасибо.
Именно такое решение и искал.
Бескрайне благодарен вам — для начинающих разработчиков, вроде меня, подобные примеры и инструкции очень ценны.
Поставил на сайте, все отлично работает.
Именно такое решение и искал.
Бескрайне благодарен вам — для начинающих разработчиков, вроде меня, подобные примеры и инструкции очень ценны.
Поставил на сайте, все отлично работает.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.