Smartlanding

Как связать reCaptcha с формой обратной связи

как подключить рекаптчу Всем привет. Недавно помогал связать форму обратной связи, которая сделана с применением технологии ajax (то есть без перезагрузки страницы) с recaptca от Google и решил, что многим это тоже может быть интересно.

Да, есть много плагинов для CMS, но вручную сделать это немного сложнее, а раз появился такой вопрос у одного, то может и кому-то из вас пригодится статья.

Делать буду на примере свой же формы.

Форма обратной связи с recaptcha от Google

Итак, для тех, кто еще не понял, мы пытаемся добавить такую штуку в нашу форму:

recaptcha для формы обратной связи

Посмотреть пример

В первую очередь нужно получить API key для домена, на котором будет использоваться reСaptcha. Чтобы его получить, нужно перейти на эту страницу придумать названия и указать нужный домен:

recaptcha на сайт

После этого, вас перебросят на страницу, где кратко будет описана интеграция на сайт, а также находиться ваш секретный ключ и ключ сайта:

Получение секретного ключа recaptcha

Дальше, нам говорят, что перед закрывающимся тегом </head> нужно разместить следующий скрипт:

<script src='https://www.google.com/recaptcha/api.js'></script>

А в форму, там, где будет располагаться каптча — следующий блок:

<div class="g-recaptcha" data-sitekey="6LcYtSQTAAAAAPNjrDKIiFFhwwcpaqzIkxwxxZMS"></div>

Есть несколько дополнительных настроек, например:

  •  светлый или темный внешний вид — data-theme=»light» или data-theme=»dark».
  • нормальный или компактный размер — data-size=»compact», data-size=»norml»

Подробнее о том, какие еще есть настройки и как встроить рекаптчу в несколько форм на одной странице можно почитать тут.

Так как в моей форме все скрипты располагаются в конце страницы, то я решил и скрипт от Google поместить там же. Выглядит это все так:

<script src="modalform/libs/remodal/remodal.min.js"></script>
<script src="modalform/js/form.js"></script>
<!-- API ключ от Google -->
<script src='https://www.google.com/recaptcha/api.js'></script>
</body>
</html>

Еще раз повторюсь, что recaptcha подключается к уже существующей форме, ссылка на которую есть в первом параграфе, поэтому не буду здесь описывать каждую строку, отвечающую за форму. Если что-то будет непонятно, загляните на соседнюю страницу с формой. Или спрашивайте в комментариях.

Разметка формы сейчас выглядит так:

<div class="remodal" data-remodal-id="firstModal" data-remodal-options="hashTracking: false,closeOnConfirm: false">
  <button data-remodal-action="close" class="remodal-close"></button>
  <div class="formArea">
    <p class="formTitle">Оставьте ваши контактные данные и наш консультант свяжется с вами</p>
    <p class="msgs"></p>
    <form id="firstForm" class="form" autocomplete="off">
      <fieldset class="form-fieldset ui-input __first">
        <input name="uname" type="text" id="username" tabindex="0" />
        <label for="username">
          <span data-text="Введите ваше имя">Введите ваше имя</span>
        </label>
      </fieldset>

      <fieldset class="form-fieldset ui-input __second">
        <input name="uemail" type="email" id="email" tabindex="0" />
        <label for="email">
          <span data-text="Введите ваш e-mail">Введите ваш e-mail</span>
        </label>
      </fieldset>

      <input name="formInfo" class="formInfo" type="hidden" value=""/>
      <!-- DIV - в котором выводится блок с recaptcha -->
      <div class="g-recaptcha" data-sitekey="6LcYtSQTAAAAAPNjrDKIiFFhwwcpaqzIkxwxxZMS" data-theme="light"></div>
      <div class="form-footer">
        <input type="submit" class="formBtn" value="Отправить заявку" />
      </div>
      <p class="formCreator"><a href="http://smartlanding.biz">smartlanding.biz</a></p>
    </form>
  </div>
</div>

Еще раз повторюсь, не обращайте внимание на форму, если не используете ту, о которой шла речь в одной из прошлых статей. Просто добавьте в нужное место своей формы div с ключом, который выдал Google.

Теперь, если попытаться получить данные переданные методом POST, мы получим не только данные из полей (имя и телефон), а и значение переменной g-recaptcha-response. Его и нужно отправить Гуглу для прохождения верификации.

Самостоятельно сделать это достаточно сложно, но есть готовый скрипт, который просто подключается к обработчику формы. Скачать его можно с Github на этой страничке:

Теперь необходимо подключить его к обработчику (php файлу, который отправляет письмо) или вставить скрипт прямо в него. У меня это файл mail.php. Подключать в самом начале:

<?php
require_once __DIR__ . '/recaptchalib.php';

if ($_SERVER["REQUEST_METHOD"] == "POST") {
  if (empty($_POST['uname']) && (empty($_POST['uemail']) || empty($_POST['uphone']))){
    echo 'Ошибка. Вы заполнили не все обязательные поля!';
  } else{
    if (isset($_POST['uname'])) {
      $uname = strip_tags($_POST['uname']);
      $unameFieldset = "<b>Имя пославшего:</b>";
    }
    if (isset($_POST['uemail'])) {
      $uemail = strip_tags($_POST['uemail']);
      $uemailFieldset = "<b>Почта:</b>";
    }
    if (isset($_POST['uphone'])) {
      $uphone = strip_tags($_POST['uphone']);
      $uphoneFieldset = "<b>Телефон:</b>";
    }
    if (isset($_POST['formInfo'])) {
      $formInfo = strip_tags($_POST['formInfo']);
      $formInfoFieldset = "<b>Тема:</b>";
    }

    $to = "dima.d.v@yandex.ru"; /*Укажите адрес, на который должно приходить письмо*/
    $sendfrom = "smart-landing@yandex.ru"; /*Укажите адрес, с которого будет приходить письмо, можно не настоящий, нужно для формирования заголовка письма*/
    $headers  = "From: " . strip_tags($sendfrom) . "\r\n";
    $headers .= "Reply-To: ". strip_tags($sendfrom) . "\r\n";
    $headers .= "MIME-Version: 1.0\r\n";
    $headers .= "Content-Type: text/html;charset=utf-8 \r\n";
    $headers .= "Content-Transfer-Encoding: 8bit \r\n";
    $subject = "$formInfo";
    $message = "$unameFieldset $uname
                $uemailFieldset $uemail
                $uphoneFieldset $uphone
                $formInfoFieldset $formInfo";

    $send = mail ($to, $subject, $message, $headers);
        if ($send == 'true') {
            echo 'Спасибо за отправку вашего сообщения!';
        } else {
          echo '<b>Ошибка. Сообщение не отправлено!</b>';
        }
  }
} else {
  header ("Location: https://smartlanding.biz"); // главная страница вашего лендинга
}

В этом файле написан код, который передаст наш секретный ключ, значение g-recaptcha-response в Google, затем произойдет проверка успешна ли пройдена каптча. Но сначала, нужно добавить несколько переменных:

// Введите свой секретный ключ
$secret = "6LcYtSQTAAAAAFcHhlqotRTiINOPlznKRfbyqmpG";
 
// пустой ответ каптчи
$response = null;

// Для проверка вашего секретного ключа
$reCaptcha = new ReCaptcha($secret);
if ($_POST["g-recaptcha-response"]) {
$response = $reCaptcha->verifyResponse(
        $_SERVER["REMOTE_ADDR"],
        $_POST["g-recaptcha-response"]
    );
}

Почти все готово, осталось добавить проверку в форму, чтобы показать пользователями, что они не заполнили каптчу. Я делаю такую:

if ($response != null &amp;amp;&amp;amp; $response->success) {
//отправка
else {
 echo 'Не пройдена каптча! Попробуйте еще раз!';
}

Полный код моего обработчика:

<?php
require_once __DIR__ . '/recaptchalib.php';
// Введите свой секретный ключ
$secret = "6LcYtSQTAAAAAFcHhlqotRTiINOPlznKRhcytynG";
// пустой ответ каптчи
$response = null;
// Проверка вашего секретного ключа
$reCaptcha = new ReCaptcha($secret);
if ($_POST["g-recaptcha-response"]) {
$response = $reCaptcha->verifyResponse(
        $_SERVER["REMOTE_ADDR"],
        $_POST["g-recaptcha-response"]
    );
}

if ($_SERVER["REQUEST_METHOD"] == "POST") {
  if (empty($_POST['uname']) && (empty($_POST['uemail']) || empty($_POST['uphone']))){
    echo '<p class="fail">Ошибка. Вы заполнили не все обязательные поля!</p>';
  } else {
    if ($response != null && $response->success) {
    if (isset($_POST['uname'])) {
      $uname = strip_tags($_POST['uname']);
      $unameFieldset = "<b>Имя пославшего:</b>";
    }
    if (isset($_POST['uemail'])) {
      $uemail = strip_tags($_POST['uemail']);
      $uemailFieldset = "<b>Почта:</b>";
    }
    if (isset($_POST['uphone'])) {
      $uphone = strip_tags($_POST['uphone']);
      $uphoneFieldset = "<b>Телефон:</b>";
    }
    if (isset($_POST['formInfo'])) {
      $formInfo = strip_tags($_POST['formInfo']);
      $formInfoFieldset = "<b>Тема:</b>";
    }

    $to = "dima.d.v@yandex.ru"; /*Укажите адрес, на который должно приходить письмо*/
    $sendfrom = "smart-landing@yandex.ru"; /*Укажите адрес, с которого будет приходить письмо, можно не настоящий, нужно для формирования заголовка письма*/
    $headers  = "From: " . strip_tags($sendfrom) . "\r\n";
    $headers .= "Reply-To: ". strip_tags($sendfrom) . "\r\n";
    $headers .= "MIME-Version: 1.0\r\n";
    $headers .= "Content-Type: text/html;charset=utf-8 \r\n";
    $headers .= "Content-Transfer-Encoding: 8bit \r\n";
    $subject = "$formInfo";
    $message = "$unameFieldset $uname<br>
                $uemailFieldset $uemail<br>
                $uphoneFieldset $uphone<br>
                $formInfoFieldset $formInfo";

    $send = mail ($to, $subject, $message, $headers);
        if ($send == 'true') {
            echo '<p class="success">Спасибо за отправку вашего сообщения!</p>';
        } else {
          echo '<p class="fail"><b>Ошибка. Сообщение не отправлено!</b></p>';
        }
    } else {
      echo '<p class="success">Не пройдена каптча! Попробуйте еще раз!</p>';
    }
  }
} else {
  header ("Location: http://smartlanding.biz"); // главная страница вашего лендинга
}

Обратите внимание на почту и не забудьте поменять на свою. Кроме того, способ подключения файла recaptchalib.php предполагает, что что mail.php и recaptchalib.php находятся рядом, то есть в одной папке. Если будет «вываливаться» ошибка, убедитесь, что пути прописаны правильно или скопируйте код прямо в обработчик (в самый верх).

Вот так, достаточно просто подключить reCaptcha для к своим формам. Надеюсь статья была полезной. Помните, что этот способ не только для той формы, о которой шла речь в начале статьи. Вы легко подключите каптчу и к любой другой. На этом — все. Пока!

Скачать исходник

Поделитесь статьей в социальных сетях, чтобы не потерять

38 комментариев

  • Егор

    Привет, а можешь помочь как внедрить в твою же форму эту капчу с лендингом и битриксом? https://smartlanding.biz/crm-sistema-bitrix24-dlya-landing-page.html вот в этой статье, чтобы капча была в форме тоже и обрабатывалась нормально?

    Ответить
  • dimadv7

    Привет. Ну есть же статья о том как связать с битриксом, просто добавить код сюда.

    Ответить
  • Егор

    Ммм, не нашел статью про связку с битриксом.. Куда добавить?

    Ответить
  • dimadv7

    Вот статья о связке с битриксом.
    И вот.
    Но лучше по первой делай, там проще и понятнее.

    Ответить
  • Валерий

    А что в коде надо изменить, чтобы отправка происходила через движок Wirdpress? Знаю что есть плагин контакт 7 и прочие, но я думаю что данной формой будут пользоваться крайне редко, а грузить она будет всегда движок. Вот и думаю реализовать «Обратную связь» без плагинов.
    На хостинге я настроил отправку через «Яндекс для домена», потому через функцию вордпрес необходимо отправлять почту, ибо там плагин, который переводит отправку через SMTP сервера Яндекса.

    Ответить
  • dimadv7

    Ничего практически, главное пути к файлам прописать

    Ответить
  • Азамат

    Сделал все как нужно. Пишет что Не пройдена каптча! Попробуйте еще раз! Целый день уже с ней мучаюсь((

    Ответить
  • Лера

    А почему нельзя использовать самую простую конструкцию, типа:

    function check_captcha($secret, $response){
    $result_capcha = json_decode(file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret='.$secret.'&response='.$response));

    if (isset ($result_capcha->success) && $result_capcha->success != 1)
    return false;
    else
    return true;
    }
    и потом:
    $secret = '6LfZCgQTAABAAMRHnFbMydXчегототамещё';
    $response = $_POST['g-recaptcha-response'];

    if(check_captcha($secret, $response))
    echo 'Всё ок';
    else
    echo 'Ошибка капчи';

    Ответить
  • Михаил

    Вроде все рассказано. Спасибо. Только у меня 4 (четыре) файла mail.php в разных папках. Какой из них является обработчиком, как узнать?

    Ответить
  • Anonimus

    Возможно каждый из них для разных форм/страниц сайта.

    Ответить
  • Лада

    Спасибо большое! Очень-очень пригодилась информация :-)

    Ответить
  • Алексей

    Решили? У меня то же самое.

    Ответить
  • Сергей

    А как добавить в этот обработки загрузку файлов? Можете подсказать?

    Ответить
  • Сергей

    Всё замечательно, но вот если в первый раз что то забыл дописать или например с ящиком ошибся вовремя отправки, то приходится перезагружать страницу, т.к. капча вроде как и проверена (зеленая галочка) но по факту после второй отправки ошибка проверки капчи.
    нужно сделать чтобы капча сбрасывалась после отправки.
    И это кстати у вас в примере.

    Ответить
  • Сергей

    Как оказалось лечится просто

    grecaptcha.reset();
    Ответить
  • dimadv7

    Спасибо, что отписались)

    Ответить
  • Виктор

    Прикрутил вашу форму со своими ключами к своему сайту. В аккаунте капче-гугла вверху в красной рамке такое сообщение красуется «We detected that your site is not verifying reCAPTCHA solutions. This is required for the proper use of reCAPTCHA on your site. Please see our developer site for more information.»
    хотя сообщения отправляются, на почту все приходит, в форме капчи «вы не робот» подтверждается зеленой птичкой. Что это за сообщение? Так проходит все-таки проверка капчей или нет?

    Ответить
  • dimadv7

    Не знаю, не сталкивался с такой ошибкой. А проверить можно не заполняя каптчу, если отправится — значит не работает… Но никаких сообщений, лишних, быть не должно.

    Ответить
  • Виктор

    Если не заполнить капчу — сообщение не отправляется. В вашем варианте пишет «Не пройдена капча. Попробуйте еще раз». Если заполнить — то все работает штатно. Но предупреждение в гугл аккаунте все равно присутствует. Можно ли как-то еще узнать, проходит ли проверка? Или эта капча просто как ничего не значащий чек-бокс?

    Ответить
  • Александр

    Привет!
    Как привязать капчу к форме, которая отправляет данные в телеграм? ( из этой статьи https://smartlanding.biz/otpravka-dannyx-formy-v-telegram.html)

    Ответить
  • Александр

    Как оказалось лечится просто
    grecaptcha.reset();

    А куда это подставлять?

    Ответить
  • Кирилл

    Здравствуйте а подскажите пожалуйста как к этой форме прикрутить отправку файлов во вложении?

    Ответить
  • dimadv7

    В данном случае — никак. Другой подход нужен. Не через serialize, а через FormData.

    Ответить
  • Кирилл

    dimadv7 спасибо я принципе разобрался только такой вопрос при нажатии на кнопку отправить сообщение ничего происходит, изначально всё отправляла форма через день перестала, посмотрел лог ошибок не видит send.php пишет типа php.sock в чём проблема может быть? получается что нет связи между js и php от тупо не отправляет данные в обработчик чтобы отправить письмо!

    Ответить
  • Артём

    Помогите, сделал всё как у вас но пишет ОШИБКА: неверный домен ключа

    Ответить
  • dimadv7

    Ошибка возникает когда используете ключи не зарегистрированные для конкретного домена.

    Ответить
  • Мiki

    Добрый день. Уточните у меня выскакивает ошибка php Fatal error: Class 'ReCaptcha' not found . Я так понял, что движок Php на сайте слишком старый для этого когда?? (WordPress 3.1.4) Или еще в чем проблема ?

    Ответить
  • Мiki

    Мiki, Php версия 5.5.15

    Ответить
  • dimadv7

    Здравствуйте, похоже, что просто файл не подключен. Проверьте все пути еще раз. Особенно тут: require_once __DIR__ . '/recaptchalib.php';

    А насчет версии PHP, я только в 5.6 и 7.1 тестировал.

    Ответить
  • Кирилл

    Пишет, что не пройдена каптча, где может быть загвоздка?

    Ответить
  • Настя

    Большое спасибо, Дмитрий!
    А не подскажите, всплывающая подсказка с восклицательным знаком на оранжевом фоне и текст: «Адрес электронной почты должен одержать символ «@» » при нажатии на кнопку «Отправить заявку» она втроена в браузер? я не могу найти её ни в консоли, ни в стилях, ни в php

    Ответить
  • Настя

    type=»email» — Вот что проверяло на валидность электронный адрес. Не зря говорят, что утро вечера мудреннее.
    Удобная эта встроенная валидация, главное, что теперь известно, как её добавить/убрать.
    Ещё раз спасибо за форму. В сети много хороших уроков по созданию форм, по валидации, но нигде нет одновременной привязки капчи и формы без перезагрузки с аяксом. Это такой головняк! Редко такие спецы встречаются, чтобы при этом делились знаниями в довольно доходчивой форме.

    Ответить
  • dimadv7

    Настя, спасибо. Здорово что разобрались. Да атрибут значение в атрибуте type влияют на стандартное поведение и реакцию браузера. То есть то, как он реагирует на конкретное поле. Вот тут о них подробнее

    Ответить
  • Настя

    Мне помогло это:

    $(document).ready(function(){
            $('.formBtn').click(function(){
        grecaptcha.reset();
    });
    });
    

    где .formBtn — класс кнопки, которая отправляет сообщение. Ну вы видели её в разметке.
    А вот как сделать так, чтобы данные полей не удалялись после появления сообщения об ошибке?

    Ответить
  • dimadv7

    Настя, попробуйте очищать поля не по success, а при complete. Это в ajax запросе в файле form.js. Ведь success — это просто успешный ответ сервера, но это не значит, что форма успешно ушла. Если на стороне сервера, например, форма не прошла валидация то в success выводится ошибка и поля очищаются. Делайте это при complete.

    Ответить
  • Настя

    dimadv7, Вот эта строка? я её закомментировала для обоих вариантов ( success и error), а complete я не нашла.
    $('input').not(':input[type=submit], :input[type=hidden]').val(»);
    И вроде работает

    А вот эта конструкция, которую я описала в предыдущем сообщении, вредная:
    $(document).ready(function(){
    $('.formBtn').click(function(){
    grecaptcha.reset();
    });
    });
    Капча как бы обновляется, но даже при прохождении скрипт считает её не пройденной и выдаёт соответствующее сообщение об ошибке

    Ответить
  • dimadv7

    Настя, complete и нет в исходнике. Нужно самой дописывать. Но предварительно нужно загуглить про ajax jquery и разобраться со всем. Там будет описанные все доступные события и методы

    Ответить
  • Настя

    dimadv7, Большое спасибо за наводку! Работает! Сделала событие complete сразу после события error, это помогло для капчи
    },
    complete: function(){
    grecaptcha.reset();
    } …
    но не помогло для сброса содержимого полей. Они очищались и при ошибке, и при не введённой капче. Вставила рядом с echo с сообщением об успешной отправке данных очищение формы в php, а из js их убрала:
    …if ($send == 'true') {
    echo 'Спасибо за отправку вашего сообщения!';
    ?>
    $('.reset').val(»);
    <?php
    } else {….
    класс reset добавила каждому полю ввода

    Ответить

Добавить комментарий

Подписывайтесь на обновления, чтобы ничего не пропустить.