Как выполнить проверку формы HTML с помощью Google ReCaptcha V2 Invisible AND Multiple Forms? - PullRequest
0 голосов
/ 05 февраля 2020

У меня есть 2 формы на странице, для которых требуется Google ReCaptcha V2 Invisible. У меня это работает отлично, используя следующий код.

В заголовке:

<script src='https://www.google.com/recaptcha/api.js?onload=myCallBack&render=explicit' async defer></script>

Вот форма. Довольно просто Вы можете видеть, что ReCaptcha привязан к кнопке и имеет уникальный обратный вызов и ID.

<form id="subForm" action="form-processing.php" method="POST">         
    <input placeholder="Name" id="name" name="fname" type="text" required/>
    <input placeholder="Email" id="email" name="email" type="text" required/>
    <textarea placeholder="Comments" id="comments" cols="30" name="comments" rows="6" required></textarea>

    <button class="g-recaptcha form-submit-button" data-sitekey="MySiteKey" data-callback="captchaSubmit2" id="recaptcha2">Submit</button>
</form>

Когда загружается API ReCaptcha в заголовке и запускается обратный вызов onload (myCallBack), выполните следующие действия. код вызывается для рендеринга ReCaptcha на каждой из кнопок формы.

var recaptcha1;
var recaptcha2;
var myCallBack = function() {
    //Render recaptcha1 on element with ID "recaptcha1"
    recaptcha1 = grecaptcha.render('recaptcha1', {
      'sitekey' : 'MySiteKey',
      'theme' : 'light'
    });

    //Render recaptcha2 on element with ID "recaptcha2"
    recaptcha2 = grecaptcha.render('recaptcha2', {
      'sitekey' : 'MySiteKey',
      'theme' : 'light'
    });
};

И, наконец, когда нажата кнопка отправки, ReCaptcha обрабатывает и использует обратный вызов, указанный на кнопке, для запуска фактической отправки формы .

function captchaSubmit1(data) {
    document.getElementById("mainForm").submit();
}
function captchaSubmit2(data) {
    document.getElementById("subForm").submit();
}

В серверной части обработки на сервере я использую следующий код для проверки ReCaptcha.

<?php
    // reCaptcha info
    $secret = "MySecretKey";
    $remoteip = $_SERVER["REMOTE_ADDR"];
    $url = "https://www.google.com/recaptcha/api/siteverify";

    // Form info
    $first = $_POST["first"];
    $last = $_POST["last"];
    $response = $_POST["g-recaptcha-response"];

    // Curl Request
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl, CURLOPT_POSTFIELDS, array(
        'secret' => $secret,
        'response' => $response,
        'remoteip' => $remoteip
        ));
    $curlData = curl_exec($curl);
    curl_close($curl);

    // Parse data
    $recaptcha = json_decode($curlData, true);
    if ($recaptcha["success"])
    { 
       /// MY DATA VALIDATION & EMAILING OF FORM DATA ///
    }else{
        header('Location: /thank-you-for-contacting-us/?gvx');
        exit;
    }
?>

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

ОК! поэтому теперь проблема в том, что эти формы не выполняют HTML проверку поля на стороне клиента. Я попытался внедрить это решение безуспешно: Как запустить reCaptcha ТОЛЬКО если прошла проверка HTML5?

Эти фрагменты кода являются основными выводами из этой статьи. Я заменил кнопку отправки:

До:

<button class="g-recaptcha form-submit-button" data-sitekey="MySiteKey" data-callback="captchaSubmit2" id="recaptcha2">Submit</button>

После:

<button class="form-submit-button" type="submit">Submit</button>

И я добавил этот div в форму чуть выше кнопки отправки:

<div id="recaptcha2" class="g-recaptcha" 
data-sitekey="MySiteKey"
data-size="invisible"
data-callback="captchaSubmit2">

И вот новые обработчики для отправки формы:

$('#mainForm').submit(function (event) {
    if (!grecaptcha.getResponse()) {
        event.preventDefault(); //prevent form submit
        grecaptcha.reset();
        grecaptcha.execute();
    } 
});
$('#subForm').submit(function (event) {
    if (!grecaptcha.getResponse()) {
        event.preventDefault(); //prevent form submit
        grecaptcha.reset();
        grecaptcha.execute();
    } 
});

Итак, последний поток здесь заключается в том, что страница загружает API, API вызывает рендеринг recaptcha, который отображает recaptcha на g-recaptcha div, форма отправлена, поведение по умолчанию предотвращено, что позволяет проверять HTML функцию (что она и делает), а когда форма действительно отправляет, она вызывает вышеуказанную функцию для вызова grecaptcha.execute () ; который обрабатывает, и когда он завершается, вызывает привязанную к нему функцию обратного вызова (captchaSubmit2), которая выполняет реальную окончательную отправку. Тогда мой серверный скрипт не проходит проверку Google, и возникает грусть ...

Я потратил два дня на это, с обычным "Это уже сделано?" эхом сверху. Я так близко, что могу попробовать, но мне явно чего-то не хватает.

Мне просто нужен Google ReCaptcha V2 Invisible, работающий над двумя формами на одной странице с HTML проверкой формы для обязательных полей.

Любая помощь будет принята с благодарностью.

1 Ответ

1 голос
/ 06 февраля 2020

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

Это тег, к которому он прикрепляется:

<div class="recaptcha-holder"></div>

Я до сих пор не уверен, почему моя собственная реализация не сработала. Каждый раз, когда мне присоединяли recaptcha к нескольким формам, обработка на стороне сервера давала сбой, и отладка показала, что он не получает данные recaptcha.

Просто замечание, это реализуется на сайте WordPress, так что я добавление javascript к моему существующему включению js, в которое я вставил свой пользовательский код.

Этот код является последней записью по этому вопросу ( Реализация новой невидимой reCaptcha от Google ) размещено Mch ({ ссылка }). Все спасибо им за интерфейсное решение. Как ни странно, он был опубликован в самом конце 2016 года.

Пример внешнего интерфейса Mch

<!DOCTYPE html>
<html>
<body>

<form action="" method="post">
    <input type="text" name="first-name-1"> <br />
    <input type="text" name="last-name-1"> <br />

    <div class="recaptcha-holder"></div>

    <input type="submit" value="Submit">
</form>

<br /><br />

<form action="" method="post">
    <input type="text" name="first-name-2"> <br />
    <input type="text" name="last-name-2"> <br />

    <div class="recaptcha-holder"></div>

    <input type="submit" value="Submit">
</form>
<script src="https://www.google.com/recaptcha/api.js?onload=renderGoogleInvisibleRecaptcha&render=explicit" async defer></script>
</body>
</html>

Mch's Javascript (добавлен в мои существующие JS include)

  var renderGoogleInvisibleRecaptcha = function() {
    for (var i = 0; i < document.forms.length; ++i) {
      var form = document.forms[i];
      var holder = form.querySelector('.recaptcha-holder');
      if (null === holder){
        continue;
      }

      (function(frm){

        var holderId = grecaptcha.render(holder,{
          'sitekey': 'CHANGE_ME_WITH_YOUR_SITE_KEY',
          'size': 'invisible',
          'badge' : 'bottomright', // possible values: bottomright, bottomleft, inline
          'callback' : function (recaptchaToken) {
            HTMLFormElement.prototype.submit.call(frm);
          }
        });

        frm.onsubmit = function (evt){
          evt.preventDefault();
          grecaptcha.execute(holderId);
        };

      })(form);
    }
  };

И, наконец, моя внутренняя (серверная) обработка:

<?php
    // reCaptcha info
    $secret = "MySecretKey";
    $remoteip = $_SERVER["REMOTE_ADDR"];
    $url = "https://www.google.com/recaptcha/api/siteverify";

    // Form info
    $first = $_POST["first"];
    $last = $_POST["last"];
    $response = $_POST["g-recaptcha-response"];

    // Curl Request
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl, CURLOPT_POSTFIELDS, array(
        'secret' => $secret,
        'response' => $response,
        'remoteip' => $remoteip
        ));
    $curlData = curl_exec($curl);
    curl_close($curl);

    // Parse data
    $recaptcha = json_decode($curlData, true);
    if ($recaptcha["success"])
    { 
        // MY DATA VALIDATION & EMAILING OF FORM DATA
    }else{
        // Google ReCaptcha Failed to Verify - Send to False Positive
        header('Location: /thank-you-for-contacting-us/?gvx');
        exit;
    }
?>
...