FormLister: Использование капчи
- Дополнения
- FormLister
- Использование капчи
FormLister: Использование капчи
По умолчанию FormLister может использовать модицифированную капчу MODX и Google Recaptcha. Также в наличии SmsCaptcha - для отправки формы необходимо ввести код, полученный в смс-сообщении (отправку сообщения необходимо реализовывать отдельно).
Для подключения необходимо указать имя папки с файлами капчи (папки находятся в assets/snippets/FormLister/lib/captcha/) в параметре &captcha.
В параметре &captchaParams задаются в виде массива настройки капчи. Например:
&captchaParams=`{
"width":200,
"height":120
}`
Имя поля, в которое пользователь вводит значение капчи, задается параметром captchaField (по умолчанию - vericode). Правило валидации для этого поля создается автоматически.
Капча выводится в шаблоне формы с помощью плейсхолдера [+captcha+].
modxCaptcha
Модификация стандартной капчи MODX.
Настройки:
- width и height - ширина и высота картинки с капчей (значение по умолчанию - 100 и 60);
- inline - формат вывода. Если значение параметра равно 1, то в плейсхолдер [+captcha+] выводится картинка в base64-формате. Если 0, то выводится ссылка на файл connector.php, генерирующий картинку. Значение по умолчанию - 1;
- connectorDir - путь к папке с файлом connector.php, если параметр inline равен 0. Значение по умолчанию - assets/snippets/FormLister/lib/captcha/modxCaptcha/;
- errorEmptyCode - текст сообщения об ошибке, если поле со значением капчи не заполнено. Значение по умолчанию - "Введите проверочный код";
- errorCodeFailed - текст сообщения об ошибке, если введено неверное значение капчи. Значение по умолчанию - "Неверный проверочный код"
reCaptcha
Капча Google reCAPTCHA V2. На странице с формой должен быть подключен скрипт:
<script src='https://www.google.com/recaptcha/api.js'></script>
Значение параметра captchaField должно быть "g-recaptcha-response" (см. документацию).
Настройки:
- secretKey, siteKey - ключи для доступа к api reCAPTCHA;
- size, theme, badge, callback, expired_callback, tabIndex, type - см. документацию;
- errorCodeFailed - текст сообщения об ошибке, если пользователь не прошел проверку. Значение по умолчанию - "Вы не прошли проверку"
smsCaptcha
Настройки:
- codeLifeTime - срок действия введенного кода, секунд. Если пользователь попытается ввести код до истечения срока, то будет выведено сообщение errorCodeUsed. Значение по умолчанию - 86400 (сутки);
- errorEmptyCode - сообщение об ошибке, если пользователь получил, но не ввел код. Значение по умолчанию - "Введите код авторизации";
- errorCodeRequired - сообщение об ошибке, если пользователь не запросил код. Значение по умолчанию - "Получите код авторизации";
- errorCodeFailed - сообщение об ошибке, если пользователь ввел неверный код авторизации. Значение по умолчанию - "Неверный код авторизации";
- errorCodeExpired - сообщение об ошибке, если пользователь не ввел полученный код в течение заданного времени. Значение по умолчанию - "Код авторизации истек, получите новый";
- errorCodeUsed - сообщение об ошибке, если пользователь уже вводил код для текущей формы. Значение по умолчанию - "Код авторизации уже использовался".
Чтобы использовать эту капчу необходимо предварительно создать таблицу в базе данных:
<?php include_once(MODX_BASE_PATH.'assets/snippets/FormLister/lib/captcha/smsCaptcha/model.php'); $sms = new \SmsModel($modx); $sms->createTable();
Для отправки кода необходимо создать отдельную форму и указать в параметре prepareProcess сниппет:
<?php
//удаляем из номера телефона все, кроме цифр
$rawPhone = preg_replace('/[^\d]+/','',$data['phone']);
//задаем значение, по которому будет определяться для какой формы генерируется код
$formid = 'basic';
//в сессии будем хранить номер телефона, это нужно для проверки кода в основной форме, потом его можно использовать в каких-то целях, например убрать из основной формы поле для ввода телефона, а в письме использовать телефон из сессии
$session_key = $formid.'.smscaptcha';
if (empty($rawPhone)) {
$FormLister->setValid(false);
$FormLister->addError('phone','phone','Неверный номер телефона');
} else {
//загружаем класс для работы с таблицей
$sms = $FormLister->loadModel('SmsModel','assets/snippets/FormLister/lib/captcha/smsCaptcha/model.php');
$flag = false;
//проверяем, есть ли в таблице запись для заданного номера и идентификатора формы
$data = $sms->getData('+'.$rawPhone,$formid);
if ($data->getID()) {
//если есть и код не истек
if ($sms->get('expires') > time()) {
//смотрим, использован ли код
if ($sms->get('active')) {
$FormLister->addMessage('Вы уже использовали код.');
} else {
$FormLister->addMessage('Код уже был отправлен. Подождите несколько минут прежде чем запросить новый.');
}
//если код истек, то удаляем запись и разрешаем выдать новый
} else {
$sms->delete($sms->getID());
$flag = true;
}
} else {
$flag = true;
}
//если можно выдать новый код
if ($flag) {
$code = mt_rand(1000,9999);
//здесь отправляется смс и результат помещается в переменную $result
/**
*
*/
$result = array('status'=>true);
//проверяем отправлена ли смс
if (is_array($result) && $result['status']) {
//создаем запись в таблице, время жизни кода - 3 минуты
$result = $sms->create()->fromArray(array(
'phone'=>('+'.$rawPhone),
'formid'=>$formid,
'expires'=>(time() + 60*3),
'ip'=> \APIhelpers::getUserIP(),
'code'=>$code
))->save();
//если получилось записать, то сохраняем в сессию номер телефона
if ($result) {
$_SESSION[$session_key] = '+'.$rawPhone;
} else {
$FormLister->setValid(false);
$FormLister->addMessage('Не удалось отправить смс');
}
} else {
//если нельзя выдать код, то запрещаем дальнейшую обработку формы
$FormLister->setValid(false);
}
}
?>
Полностью вызов FormLister:
<div class="row"> <div class="col-md-8 col-md-offset-2"> <div class="well"> <form class="form-horizontal" method="post"> <input type="hidden" name="formid" value="code"> <div class="form-group[+phone.errorClass+][+phone.requiredClass+]"> <label for="phone" class="col-sm-2 control-label">* Телефон</label> <div class="col-sm-10"> <input type="text" class="form-control" placeholder="+375 29 123 45 67" name="phone" value="[+phone.value+]"> [+phone.error+] </div> </div> [+form.messages+] <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn btn-primary"><i class="glyphicon glyphicon-envelope"></i> Отправить</button> </div> </div> <img src="[+captcha+]"> <input name="vericode"> [+vericode.error+] </form> </div> </div> </div>