Description
openedon Nov 2, 2018
Hello, while this is not specific to the PHP client library, but I hope to get some answers about the use of the new reCAPTCHA v3.
Basically I have a contact form in PrestaShop, and I want to be able to add reCAPTCHA v3 so that there is no extra interaction for users while making sure I don't get spammed from bots. From the docs page, the idea being brought forward is to add the script tag with the link toapi.js
with the render GET parameter ?render=reCAPTCHA_site_key
. Doing so you will not need to run grecaptcha.render()
manually, which is an important point (more on this later).
Now, I have to add grecaptcha.execute()
in the callback of grecaptcha.ready()
. Here I can define an action, and finally in the then()
promise fulfillment I get a token
. I take this token and update the value
attribute of a hidden input tag in the form, named g-recaptcha-response
. This way it gets sent to the server alongside with the regular form fields and I can make the server verification in ContactController::postProcess()
method.
Since I want users to fill the form with several fields and a message, they might take even minutes to submit the form. I'm also using jQuery to run on the form submission, doing some validation checks and in case calling event.preventDefault()
and showing an alert if some required fields are empty or invalid.
In my tests I found out that tokens expire rather quickly. Since we don't manually run grecaptcha.render()
as mentioned above, we cannot specify an expired-callback
to run when the token expires. At this point I resorted to add a setInterval
with a 60000 delay (1 minute) to run again grecaptcha.execute()
.
Is this the right way to use the frontend library? Is it correct to run multiple checks once per minute? Will this affect users' score?
$(document).ready(function () {
function reCAPTCHA_execute () {
// grecaptcha instantiated by external script from Google
// reCAPTCHA_site_key comes from backend
grecaptcha.execute(reCAPTCHA_site_key, { action: 'contactForm' }).then(function (token) {
$('[name="g-recaptcha-response"]').val(token);
}, function (reason) {
console.log(reason);
});
}
if (typeof grecaptcha !== 'undefined' && typeof reCAPTCHA_site_key !== 'undefined') {
grecaptcha.ready(reCAPTCHA_execute);
setInterval(reCAPTCHA_execute, 60000);
}
});
Initially I thought of running grecaptcha.execute()
on form submission, in the same callback function that does data validation, but since grecaptcha.execute()
is asynchronous, I cannot stop the form submission (event.preventDefault()
) and the resume in the promise fulfillment.
$('.contact-form-box').on('submit', function (e) {
// Check if email is empty
if ($('#email').val() === '') {
e.preventDefault();
window.alert(contact_emptyEmail);
return;
}
// Check if email is not valid
if (!validate_isEmail($('#email').val())) {
e.preventDefault();
window.alert(contact_invalidEmail);
return;
}
// etc…
// here I cannot do grecaptcha.execute() because it's asynchronous,
// and stopping the form submission cannot be reverted.
});