[СДЕЛАЙ САМ] Авторизация и регистрация по SMS с помощью SendIt
Приветствую! Хочу рассказать вам как с помощью одного компонента и одной формы с минимумом усилий сделать регистрацию и авторизацию по SMS.
1. Устанавливаем SendIt и FormIt
2. Подготавливаем форму.
3. Добавляем необходимые пресеты.
4. Создаём сниппет генерации и отправки кода snippet.sendcode.php
5. Создаём сниппет проверки введённого кода CheckCode
6. Создаём сниппет установки полей пользователя SetUserFields
7. Добавляем JavaScript для обработки ответов вервера
Вся форма (data-si-form=«smsAuthForm») будет регистрировать нового пользователя, но сразу после загрузки страницы мы блокируем кнопку и скрываем поля кода и имени.
После вводе номера телефона он будет отправлен на сервер, где выполнится код из сниппета snippet.sendcode.php. В нём подключаем класс Identification, чтобы сгенерировать код, проверяем есть ли пользователь с таким телефоном, формируем сообщение для отправки пользователю, записываем данные в сессию для использования на следующих этапах. Код отправки сообщения вы пишите сами, так как я не хочу ограничивать вас в выборе сервиса СМС рассылок..
После отправки кода, если пользователь существует, с помощью JS меняем пресет с checkcode на sms_auth. Блокируем ввод номера на 30 секунд.Если пользователь не существует проверяем код, если он верный, устанавливаем его в качестве пароля, на клиенте показываем поле ввода имени и разблокируем кнопку. Если существует, также устанавливаем код в качестве пароля и переадресовываем в ЛК.
Если поле с вводом имени показано, пользователь должен его обязательно указать и только потом сможет отправить форму регистрации.
Можно ещё много всякого накрутить по юзабилити, но в целом это всё.
1. Устанавливаем SendIt и FormIt
2. Подготавливаем форму.
<form data-si-form="smsAuthForm" data-si-preset="sms_register">
<label>
<input type="tel" name="phone" data-si-event="change" data-si-preset="sendcode" placeholder="+7(">
<p data-si-error="phone"></p>
</label>
<label data-si-hide="code">
<input type="text" name="code" data-si-event="change" data-si-preset="checkcode" placeholder="0000">
<p data-si-error="code"></p>
</label>
<label data-si-hide="fullname">
<input type="text" name="fullname" placeholder="Полное имя">
<p class="color_error px-15 fs-16-12" data-si-error="fullname"></p>
</label>
<button type="submit">Отправить</button>
</form>
3. Добавляем необходимые пресеты.
'sendcode' => [
'hooks' => '',
'snippet' => '@FILE snippets/smsauth/snippet.sendcode.php',
'successMessage' => 'Код отправлен на номер {$phone}',
'validate' => 'phone:required',
'phone.vTextRequired' => 'Укажите телефон.'
],
'checkcode' => [
'hooks' => '',
'successMessage' => '',
'validate' => 'code:CheckCode',
'validationErrorMessage' => 'Неверный код.',
],
'sms_auth' => [
'extends' => 'checkcode',
'successMessage' => 'Вы успешно авторизованы.',
'hooks' => 'SetUserFields,Identification',
'method' => 'login',
'redirectTo' => 5,
'user_exist' => 1,
'redirectTimeout' => 3000,
'clearFieldsOnSuccess' => 1,
],
'sms_register' => [
'hooks' => 'SetUserFields,Identification',
'method' => 'register',
'successMessage' => 'Вы успешно зарегистрированы.',
'activation' => 0,
'autoLogin' => 1,
'redirectTo' => 5,
'redirectTimeout' => 3000,
'usergroups' => 2,
'validate' => 'fullname:required,phone:required,code:CheckCode',
'fullname.vTextRequired' => 'Укажите ваше имя.',
'clearFieldsOnSuccess' => 1,
],
4. Создаём сниппет генерации и отправки кода snippet.sendcode.php
require_once MODX_CORE_PATH . 'components/sendit/model/sendit/identification.class.php';
$phone = preg_replace('/[^0-9]/', '', $_POST['phone']);
$code = Identification::generateCode($modx, 'code', 4);
$userExist = $modx->getCount('modUser', ['username' => $phone]);
$site_url = $modx->getOption('site_url');
$msg = "Код подтверждения с сайта $site_url: $code";
$_SESSION['SMSAuth']['user_exist'] = $userExist;
$_SESSION['SMSAuth']['code'] = $code;
$_SESSION['SMSAuth']['phone'] = $phone;
$_SESSION['SMSAuth']['phone_orignal'] = $_POST['phone'];
// ОТПРАВКА КОДА В СЕРВИС РАССЫЛКИ СМС
//$modx->log(1, $code);
$successMessage = str_replace('{$phone}', $_POST['phone'], $successMessage);
return $SendIt->success($successMessage, ['user_exist' => $_SESSION['SMSAuth']['user_exist']]);
5. Создаём сниппет проверки введённого кода CheckCode
$inputCode = $_POST['code'];
if($inputCode !== $_SESSION['SMSAuth']['code']){
$validator->addError($key, $validationErrorMessage);
}else{
$code = $_SESSION['SMSAuth']['code'];
$phone = $_SESSION['SMSAuth']['phone'];
if($_SESSION['SMSAuth']['user_exist']){
$user = $modx->getObject('modUser', ['username' => $phone]);
$user->set('password', $code);
$user->save();
}
}
return true;
6. Создаём сниппет установки полей пользователя SetUserFields
$hook->setValue('username', $_SESSION['SMSAuth']['phone']);
$hook->setValue('password', $_SESSION['SMSAuth']['code']);
$hook->setValue('phone', $_SESSION['SMSAuth']['phone_orignal'] );
return true;
7. Добавляем JavaScript для обработки ответов вервера
const hiddenBlocks = document.querySelectorAll('[data-si-hide]');
const authFormBtn = document.querySelector('[data-si-form="smsAuthForm"] [type="submit"]');
authFormBtn && (authFormBtn.disabled = true); // блокируем кнопку
hiddenBlocks.length && hiddenBlocks.forEach(block => block.classList.add('v_hidden')); // скрываем поля с кодом и именем
document.addEventListener('si:send:after', (e) => {
const {target, result} = e.detail; // получаем данные из события
if(result.success){
if(target.dataset.siPreset === 'sendcode'){ // после отправки кода
const codeInput = document.querySelector('[data-si-form="smsAuthForm"] [name="code"]');
const phoneInput = document.querySelector('[data-si-form="smsAuthForm"] [name="phone"]');
const phoneError = document.querySelector('[data-si-form="smsAuthForm"] [data-si-error="phone"]');
const wrapCode = document.querySelector('[data-si-hide="code"]');
wrapCode.classList.remove('v_hidden'); // показываем поле ввода кода
if(result.data.user_exist){ // если пользователь существует
codeInput.dataset.siPreset = 'sms_auth'; // авторизуем
}else{
codeInput.dataset.siPreset = 'checkcode'; // проверяем код
}
phoneInput.disabled = true;
phoneError.textContent = 'Повторная отправка возможна через 30 сек.';
setTimeout(() => {
phoneInput.disabled = false;
phoneError.textContent = '';
}, 30000)
}
if(target.dataset.siPreset === 'checkcode'){ // поле проверки кода
const wrapName = document.querySelector('[data-si-form="smsAuthForm"] [data-si-hide="fullname"]');
wrapName.classList.remove('v_hidden'); // показываем поле ввода имени
authFormBtn.disabled = false; // разблокируем кнопку
}
}
})
Порядок работыВся форма (data-si-form=«smsAuthForm») будет регистрировать нового пользователя, но сразу после загрузки страницы мы блокируем кнопку и скрываем поля кода и имени.
После вводе номера телефона он будет отправлен на сервер, где выполнится код из сниппета snippet.sendcode.php. В нём подключаем класс Identification, чтобы сгенерировать код, проверяем есть ли пользователь с таким телефоном, формируем сообщение для отправки пользователю, записываем данные в сессию для использования на следующих этапах. Код отправки сообщения вы пишите сами, так как я не хочу ограничивать вас в выборе сервиса СМС рассылок..
После отправки кода, если пользователь существует, с помощью JS меняем пресет с checkcode на sms_auth. Блокируем ввод номера на 30 секунд.Если пользователь не существует проверяем код, если он верный, устанавливаем его в качестве пароля, на клиенте показываем поле ввода имени и разблокируем кнопку. Если существует, также устанавливаем код в качестве пароля и переадресовываем в ЛК.
Если поле с вводом имени показано, пользователь должен его обязательно указать и только потом сможет отправить форму регистрации.
Можно ещё много всякого накрутить по юзабилити, но в целом это всё.
Поблагодарить автора
Отправить деньги
Комментарии: 3
Получается весь механизм работы не подразумевает подключать в процесс сторонние сервисы по SMS рассылкам? Все делает php?
Нет. Автор немного схитрил и не указал в коде саму отправку SMS. Он просто оставил комментарий // ОТПРАВКА КОДА В СЕРВИС РАССЫЛКИ СМС
По факту там будет подключение к оператору и отправка SMS
По факту там будет подключение к оператору и отправка SMS
Сервис рассылки вы выбираете самостоятельно и отправку данных в него пишите самостоятельно.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.