I have 2 forms on a page that both need Google ReCaptcha V2 Invisible. I have this working perfectly using the following code.
In the Header:
<script src='https://www.google.com/recaptcha/api.js?onload=myCallBack&render=explicit' async defer></script>
Here is the form. Pretty simple. You can see the ReCaptcha is tied to the button, and that it has a unique callback and 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>
When the ReCaptcha api in the header loads, and fires off the onload callback (myCallBack) the following code is called to render the ReCaptcha on each of the form's buttons.
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'
});
};
And finally, when a submit button is clicked, ReCaptcha processes, and uses the callback specified on the button to trigger the actual form submission.
function captchaSubmit1(data) {
document.getElementById("mainForm").submit();
}
function captchaSubmit2(data) {
document.getElementById("subForm").submit();
}
On the backend in my server-side processing I am using the following code to verify the 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;
}
?>
If the form validation fails due to Google ReCaptcha verify failure, it simply redirects to the thank you page with a code so I know it was the recaptcha that failed. There is a separate code if the form field data fails validation. Just a way to help me see what is going on.
OK! so now the problem is that these forms do not perform the HTML client-side field validation. I have tried to incorporate this solution with no luck: How to run reCaptcha ONLY if HTML5 validation has passed?
These bits of code are the main take-aways from that article. I replaced the submit button:
Before:
<button class="g-recaptcha form-submit-button" data-sitekey="MySiteKey" data-callback="captchaSubmit2" id="recaptcha2">Submit</button>
After:
<button class="form-submit-button" type="submit">Submit</button>
And I added this div into the form just above the submit button:
<div id="recaptcha2" class="g-recaptcha"
data-sitekey="MySiteKey"
data-size="invisible"
data-callback="captchaSubmit2">
And these are the new handlers for the form submit:
$('#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();
}
});
So the final flow here is that page loads the api, the api calls the recaptcha render that renders the recaptcha on the g-recaptcha div, the form is submitted, the default behavior is prevented allowing the HTML validation to function (Which it does), and when the form actually does submit, it triggers the above function to call grecaptcha.execute(); which processes, and when it completes, calls the callback function tied to it (captchaSubmit2) which does the real final submit. Then my server-side script is failing google validation, and sadness ensues...
I've spent two days beating on this now, with the usual "Is it done yet?" echoing from above. I am so close I can taste it, but I am obviously missing something.
I just need Google ReCaptcha V2 Invisible working on 2 forms on the same page with HTML form validation for required fields.