Использование капчи

    Использование капчи

    По умолчанию 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:

    [!FormLister?
    &formid=`code`
    &submitLimit=`0`
    &protectSubmit=`0`
    &rules=`{
    "phone":{
        "required":"Обязательно введите номер телефона",
        "phone":"Введите номер правильно"
    }
    }`
    &prepareProcess=`setSmsCaptcha`
    &captcha=`modxCaptcha`
    &formTpl=`@CODE:
    <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>`
    &successTpl=`@CODE:Код авторизации отправлен на номер [+phone.value+]. Срок действия кода - 3 минуты.`
    !]