I'm trying to migrate from using Google reCaptcha v2 to the invisible reCaptcha. I use Parsley.js for form validation and submit the form using the Malsup Ajax form plugin. my current code looks like this :
HTML:
<form action="send1.php" method="post" class="contact_form">
<label for="name_1">Name</label>
<input type="text" name="name_1" id="name_1" value="" required />
<div class="g-recaptcha" data-sitekey="XXX"></div>
<input type="submit" class="button" value="">
</form>
JS:
$('.contact_form').parsley();
$('.contact_form').submit(function(){
if($('.contact_form').parsley().validate()){
$('.contact_form').ajaxSubmit();
}
return false;
});
this successfully passes a g-recaptcha-response to send1.php, where the reCaptcha is validated.
How can i integrate Invisible reCaptcha with this script?
i tried using this:
<div id='recaptcha' class="g-recaptcha"
data-sitekey="XXX"
data-callback="onSubmit"
data-size="invisible"></div>
</div>
But I'm not sure how to use the data-callback. If I add
grecaptcha.execute();
Before the ajaxSubmit() then the field g-recaptcha-response is added to the Ajax call, but it's value is blank...
Any help, please?
(I Copied my answer from here)
For ParsleyJS you will to do a little workaround:
1.Add hidden input field, with data-parsley-required="true", value = "", like this:
<input id="myField" data-parsley-errors-container="#errorContainer" data-parsley-required="true" value="" type="text" style="display:none;">
2.Add error container (just below or under your g-recaptcha div):
<span id='errorContainer'></span>
3.Add this simple function somewhere in your js code:
function recaptchaCallback() {
document.getElementById('myField').value = 'nonEmpty';
}
4.Add the attribute data-callback with value of custom function:
<div class="g-recaptcha" data-sitekey="***" data-callback="recaptchaCallback"></div>
I'll share with you how I got ParsleyJS and Invisible reCaptcha working for me. Below is the code I used. This was POC code only, not production; and I did not do an AJAX post. And please excuse any uglyness, because I had to strip out a lot of fluff:
<!DOCTYPE html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="../node_modules/parsleyjs/dist/parsley.min.js"></script>
</head>
<body>
<form action="#" data-parsley-validate class="js-validate">
<div>
<label for="input-first-name">First Name*</label>
<input
type="text"
id="input-first-name"
name="first-name"
data-parsley-trigger="blur"
data-parsley-error-message="First Name is required"
required>
</div>
<div>
<label for="input-last-name">Last Name*</label>
<input
type="text"
name="last-name"
id="input-last-name"
data-parsley-trigger="blur"
data-parsley-error-message="Last Name is required"
required>
</div>
<div>
<button type="submit" id="theSubmitBtn">Submit</button>
</div>
<script src="https://www.google.com/recaptcha/api.js?render=explicit&onload=onScriptLoad" async defer></script>
<script>
function onScriptLoad() {
var htmlEl = document.querySelector('.g-recaptcha');
var captchaOptions = {
sitekey: 'Your_Site_Key',
size: 'invisible',
callback: function (token) {
$('.js-validate').submit();
console.log('test: ',token);
}
};
recaptchaId = window.grecaptcha.render(htmlEl, captchaOptions, false);
$('#theSubmitBtn').click(function(e){
e.preventDefault();
if(grecaptcha.getResponse() != ''){
grecaptcha.reset();
}
grecaptcha.execute();
});
}
</script>
<div id='recaptcha' class="g-recaptcha"></div>
</form>
</body>
</html>
So if you want to do submit via AJAX, you can add a ParsleyJS event listener and do your Ajax call that way.
$('.js-validate').parsley().on('form:submit', function() {
//AJAX post here
return false;
});
I based my solution mostly off this post (so credit to him): Invisible google Recaptcha and ajax form
Hope it helps, because I also looked for solutions for a while.
I hope this will help you out, I haven't dealt with parsley, but the way reCaptcha integrates with it should be the same. Let me know if you have any questions!
I use a method like this to render my reCaptchas. This allows you to have multiple captchas on the same page, as well as validation.
For form validation, I've added your parsley validation to the below function. Notice that if the validation returns false, we reset the captcha... this is important. If that doesn't happen, the form cannot be re-submitted.
function renderRecaptcha() {
for (var i = 0; i < document.forms.length; ++i) {
var form = document.forms[i];
var button = form.querySelector('[data-sitekey]');
if (null === button) {
continue;
}
(function (frm) {
var sitekey = button.getAttribute("data-sitekey");
var buttonId = grecaptcha.render(button, {
"sitekey": sitekey,
"size": "invisible",
"badge": "inline",
"callback": function (recaptchaToken) {
if ($(frm).parsley().validate()) {
$(frm).ajaxSubmit();
// HTMLFormElement.prototype.submit.call(frm);
} else {
grecaptcha.reset(buttonId);
}
}
});
frm.onsubmit = function (evt) {
evt.preventDefault();
grecaptcha.execute(buttonId);
};
})(form);
}
}
Your button will be what has the sitekey instead of a div. This simplifies things a lot.
<button type="submit" class="common-form__submit" data-sitekey="SITEKEY_HERE">Send Your Request</button>