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;
}Вуаля.
Комментарии: 11
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
2. а что, пардон, у меня слетит при обновлении?)
2. Если ничего, то я с удовольствием использую твой вариант, потому, что он очевидно круче.
P.s. Если тебе написали комментарий не содержащий похвалы и оваций, не стоит сразу камнями кидаться, не обязательно тебя хотели как-то задеть.
ничего не накроется. только плагин officeProfile надо будет заново деактивировать
Просто мне пишет пользователь не найден, хотя телефон в mobilephone есть…
Именно такое решение и искал.
Бескрайне благодарен вам — для начинающих разработчиков, вроде меня, подобные примеры и инструкции очень ценны.
Поставил на сайте, все отлично работает.