Множетственная ReCaptcha2 на 1 стр + Ajaxform

Добрый день! Вдохновленный заметкой и комментарием Андрея в ней, я решил немного по подробнее расписать про особенности подключения Google ReCaptcha 2 для использования в MODX Revolution c дополнением AjaxForm и FormIt.


Под катом пример с картинками.

Итак, стояла задача установить Google ReCaptcha2 в трех формах на одной странице (Лэндинг). Две из которых запрос прайса на почту и одна с просьбой перезвонить.

Работает все изначально через AjaxForm в связке с FormIt. Для этого ставим компонент recaptchav2, в настройках через системные параметры MODX задаем sitekey и secretkey, предварительно получив их тут.

Первый шаг: тут логинимся в google и задаем имя набора параметров и домен сайта где будет каптча:

Второй шаг: тут получаем заветные ключи и копируем себе, их мы и будем указывать в параметрах MODX:

Третий шаг: полученные ключи мы прописываем в соответствующих настройках MODX как показано на скриншоте.

Четвертый шаг: Необходимо поработать с кодом шаблона ресурса, на котором предполагается использовать несколько вызовов ReCaptcha2. Следующим образом. В подвал добавляем вызов апи Google и небольшой javascript который будет отвечать за рендер каптчи, т.к. штатные вызовы компонента recaptchav2 в данной ситуации не подходят, ниже код:
<script src="https://www.google.com/recaptcha/api.js?onload=MyCallBack&render=explicit" async defer></script>
        <script>
          var recaptcha1;
          var recaptcha2;
          var recaptcha3;
          var MyCallBack = function() {
            //Render the recaptcha1 on the element with ID "recaptcha1"
            recaptcha1 = grecaptcha.render('recaptcha1', {
              'sitekey' : '[[++recaptchav2.site_key]]', //Replace this with your Site key
              'theme' : 'light'
            });
            
            //Render the recaptcha2 on the element with ID "recaptcha2"
            recaptcha2 = grecaptcha.render('recaptcha2', {
              'sitekey' : '[[++recaptchav2.site_key]]', //Replace this with your Site key
              'theme' : 'dark'
            });
            //Render the recaptcha3 on the element with ID "recaptcha3"
            recaptcha3 = grecaptcha.render('recaptcha3', {
              'sitekey' : '[[++recaptchav2.site_key]]', //Replace this with your Site key
              'theme' : 'light'
            });
          };
        </script>
Небольшое пояснение:
1) к апи идет обращение с параметром MyCallBack он может быть абсолютно любым, далее по коду есть одноименная переменная которой присваивается функция.
2) в функции задаем переменную recaptcha1 и в ней одноименный параметр, это будет id div а в который будет выводится каптча, как называть — ваше дело. Делаем по аналогии для всех трех каптч.
3) далее в sitekey не забываем поставить плейсхолдер системного параметра компонента recaptchav2 и можно пожеланию выбрать тему в параметре theme светлую или темную.

Пятый шаг: Нужно привести вызов сниппета AjaxForm к следующему примерно виду:
[[!AjaxForm?
    &snippet=`FormIt`
    &form=`form.request`
    &hooks=`recaptchav2,email`
    &emailFrom=`[[++mail_smtp_user]]`
    &emailFromName=`Админ сайта`
  	&emailSubject=`Запрос прайса с сайта [[++site_url:replace=`http://== `:replace=`/== `]]`
  	&emailTo=`yourmail@domain.tld`
  	&emailTpl=`tpl.mail.price`
  	&frontend_js=`[[+assetsUrl]]js/custom.js`
    &validate=`name:required,emailclient:email:required,g-recaptcha-response:required`
    &validationErrorMessage=`В форме содержатся ошибки!`
    &successMessage=`Заявка успешно отправлена`
    &name.vTextRequired=`Пожалуйста, укажите, как к вам обращаться`
    &email.vTextRequired=`Пожалуйста, укажите свою электронную почту`
]]
В хуке обязательно указать recaptchav2
а в чанке form.request, в конце формы, перед кнопкой отправки формы добавить див для рендера каптчи:
<div class="form-item">
              <div id="recaptcha1"></div>
              <span class="error_g-recaptcha-response error"></span>
            </div>
И по аналогии в чанках других форм сделать с разницей только лишь в id diva которые мы указали в javascript коде под вызовом api google.
Ниже дива идет span для отработки ошибок ввода каптчи.

Как результат получаем вот что:


При такой конфигурации все должно работать.
Sergey Leleko
17 мая 2017, 11:11
modx.pro
33
7 349
+12

Комментарии: 21

Scorp Satex
17 мая 2017, 19:39
+1
Спасибо, буквально недавно столкнулся с этой задачей. Буду пробовать.
    Павел
    23 мая 2017, 13:43
    +3
    Небольшая пометка. Чтобы высвечивалось необходимость заполнения рекапчи (проверку на галку), т.е. «Это поле обязательно для заполнения.» Нужно в вызов Ajaxform добавить:
    &validate=`g-recaptcha-response:required`
      Sergey Leleko
      24 мая 2017, 06:34
      +1
      Абсолютно верное замечание, спасибо! Я внес правку в код вызова
      Александр Янк
      25 мая 2017, 23:10
      0
      Подскажите пожалуйста, от чего данная ошибка происходит? это в консоле браузера на сайте
      Uncaught Error: ReCAPTCHA placeholder element must be an element or id
          at Object.Yp [as render] (recaptcha__ru.js:470)
          at MyCallBack (common.js:25)
          at c (recaptcha__ru.js:465)
      Yp @ recaptcha__ru.js:470
      MyCallBack @ common.js:25
      c @ recaptcha__ru.js:465
        Sergey Leleko
        26 мая 2017, 07:05
        0
        Добрый день!
        А делали точно все по этой статье? используется точно компонент recaptchav2 и хук указан от него?
        просто первую версию рекаптчи гугл вроде как вообще более не поддерживает…
          Александр Янк
          26 мая 2017, 07:39
          0
          да, а можете показать чанк form.request возможно я там ошибку допустил:
          [[!AjaxForm?
              &snippet=`FormIt`
              &form=`form.callWizard`
              &hooks=`recaptchav2,email`
              &emailFrom=`[[++mail_smtp_user]]`
              &emailFromName=`Админ сайта [[++site_url:replace=`http://== `:replace=`/== `]]`
            	&emailSubject=`Вызов замерщика с сайта [[++site_url:replace=`http://== `:replace=`/== `]]`
            	&emailTo=`artlenk.ru@gmail.com`
            	&emailTpl=`tpl.callWizard`
              &validate=`name:required,phone:required,g-recaptcha-response:required`
              &validationErrorMessage=`В форме содержатся ошибки!`
              &successMessage=`Заявка успешно отправлена`
              &successMessage=`<h3>Ваше заявка отправлена</h3><p style="width: 319px;">Наши специалисты свяжутся с вами в ближайшее время.</p>
          
          `
              &name.vTextRequired=`Пожалуйста, укажите, как к вам обращаться`
              &phone.vTextRequired=`Пожалуйста, укажите свой номер телефона`
          ]]
            Sergey Leleko
            26 мая 2017, 07:44
            0
            да, у меня он такой:
            <form action="" method="post" class="ajax_form form text-top">
             <div class="fields incon">
                <div class="incon" style="width: auto;">
                   <div class="field" data-type="name">
                      <div class="name">
                         <div class="">Имя</div>
                      </div>
                      <div class="input"> <input type="text" name="name" class="form-control" style="border-radius: 4px;"> <span class="error_name"></span>  </div>
                   </div>
                </div>
                <div class="incon" style="width: auto;">
                   <div class="field" data-type="phone">
                      <div class="name">
                         <div class=""> E-mail<span class="required">*</span> </div>
                      </div>
                      <div class="input"> <input type="text" name="emailclient" class="form-control" style="border-radius: 4px;"> <span class="error_email"></span> </div>
                   </div>
                </div>
                <div class="incon">
                        <div class="form-item">
                          <div id="recaptcha1"></div>
                          <span class="error_g-recaptcha-response error"></span>
                        </div>
                </div>
             </div>
             <div class="macros-button">
                <div class="btnwrap">
                   <div class="incon"> <input data-action="" type="submit" class="btn"> </div>
                </div>
             </div>
            </form>
              Sergey Leleko
              26 мая 2017, 07:45
              0
              smtp у вас точно настроен в системных параметрах?
                Александр Янк
                26 мая 2017, 14:12
                0
                нет, у меня там ничего не прописано было. Я убрать пару строк и все заработало
                &emailFrom=`[[++mail_smtp_user]]`
                	&emailFromName=`Админ сайта`
                	&frontend_js=`[[+assetsUrl]]js/custom.js`
                  Sergey Leleko
                  26 мая 2017, 19:39
                  0
                  &frontend_js=`[[+assetsUrl]]js/custom.js`
                  еще этого файла у вас конечно же нету, прописывая этот параметр подразумевал модифицированный стандартный js Ajaxform а
          Константин Ильин
          08 июня 2017, 17:33
          1
          +3
          Немного проще делается с капчей, ведь реально неудобно когда много форм и каждую надо в переменную забивать — это неудобно. Лучше использовать each для прохода.

          Скрипты
          <script src="https://www.google.com/recaptcha/api.js?onload=CaptchaCallback&render=explicit" async defer></script>
          <script>
          var CaptchaCallback = function() {
              $('.g-recaptcha').each(function(index, el) {
                  grecaptcha.render(el, {'sitekey' : '[[++recaptchav2.site_key]]'});
              });
          };
          </script>
          Разметка в любой форме одинаковая
          <form>
          .....
           <div class="g-recaptcha" data-sitekey="[[++recaptchav2.site_key]]"></div>
          .....
          </form>
            Sergey Leleko
            08 июня 2017, 21:07
            0
            Хорошее решение. Не против если его в текст статьи добавлю?

            PS видимо недостаточны мои знания JS)
          Александр Мельник
          08 июня 2017, 22:53
          0
          Использовал такой же подход, он не единажды описан на просторах интернета.
          А вот кто-то пробовал работать с новой невидимой каптчей гугла?
          Есть опыт относительно MODX, AjaxForm и FormIt?

            Viktor
            20 февраля 2018, 20:32
            1
            +2
            Я сделал решение и даже пошаговою инструкцию уже написал, но не хватает рейтинга чтобы запостить. Демо: http://s6728.h5.modhost.pro/
              Роман Ильин
              20 февраля 2018, 21:24
              0
              Приложился к рейтингу, чтоб вы могли сделать публикацию
                Роман Ильин
                20 февраля 2018, 21:25
                0
                Как я понял, вы сделали client-side вариацию этой рекапчи?
                  Viktor
                  20 февраля 2018, 21:36
                  +1
                  Не совсем понял о чем вы. Валидация на стороне сервера тоже есть за счет хука, при отключенном js форма не отправится.
                    Роман Ильин
                    20 февраля 2018, 21:46
                    0
                    Есть два варианта реализации рекапчи:
                    1. Клиент-сайд – валидация капчи происходит чисто средствами JS, без участия сервера.
                    2. Сервер-сайд – валидация капчи происходит на сервере. В случае с modx – хуком в formit.

                    Мне показалось у вас 1 вариант.
                      Viktor
                      20 февраля 2018, 21:58
                      0
                      Валидация есть на стороне клиента и сервера. В моем варианте при отключенном js форма не отправиться. Здесь есть реализация через iframe, но стоит ли заморачиваться?
                      Роман Ильин
                      20 февраля 2018, 21:50
                      0
                      var CaptchaCallback = function() {
                              $(recaptchas).each(function(i, el) {
                                  grecaptcha.render(el, {
                                      'sitekey' : '6LeGKkcUAAAAAF8JYitV9RlNWPy_11hFFvyjktFO',
                                      'size' : 'invisible',
                                      'badge' : 'inline',
                                      'callback' : function() {
                                          afValidated = true;
                                          $(el).closest('form').submit();
                                      }
                                  });
                              });
                          };
                      на эту мысль натолкнул вот этот ваш код и документация по рекапче:
                      developers.google.com/recaptcha/docs/invisible#example
                Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                21