I have this working. I'll try to describe the solution so it's useful for everyone.
First, of course, go to hcaptcha.com and register. This will get you the "sitekey" and "secret" you'll need.
Next, you'll make a couple of edits to your theme.php. I use the Clean theme. If you are using a different on, then you might need to make some adjustments to these instructions.
Find the <link> that loads the theme's style sheet. Below that, add:
Code: Select all
<?php // include hCaptcha but only for pages named 'contact'
if ($Wcms->currentPage == 'contact') {
echo '<script src="https://js.hcaptcha.com/1/api.js?hl=en" async defer></script>';
} ?>
I only want the captcha on the contact page, hence the "if" block.
Still in the theme.php, toward the bottom, find the "if (!Wcms->loggedIn)" block. After (not inside) that block, add:
Code: Select all
<?php // include hCaptcha submit test, but only for pages named 'contact'
if ($Wcms->currentPage == 'contact') { ?>
<script>
$("form").submit(function(event) {
var hcaptchaVal = $('[name=h-captcha-response]').val();
if (hcaptchaVal === "") {
event.preventDefault();
alert("Please complete the hCaptcha");
}
});
</script>
<?php } ?>
Finally, we need to modify the plugins/contact-form/contact-form.php file.
Inside the <form> locate the <input type=submit> line. Before or after that line, depending on where you want the hcaptcha to appear, add:
Code: Select all
// add hCaptcha sitekey
$final_content .= '<div class="h-captcha" data-sitekey="YOUR_SITEKEY"></div>';
You'll need your actual sitekey, of course.
Lastly, find the line "if(isset($_POST..." which should be followed by "$aFout = array()". AFTER the $aFout line, add:
Code: Select all
// validate the hCaptcha response
if(isset($_POST['h-captcha-response']) && !empty($_POST['h-captcha-response']))
{
$hcaptchaSecret = 'YOUR_SECRET;
$verifyResponse = file_get_contents('https://hcaptcha.com/siteverify?secret='.$hcaptchaSecret.'&response='.$_POST['h-captcha-response'].'&remoteip='.$_SERVER['REMOTE_ADDR']);
$responseData = json_decode($verifyResponse);
if($responseData->success) {
$hcaptchaOkay = TRUE;
} else {
$aFout[] = 'hCaptcha verification failed';
$hcaptchaOkay = FALSE;
}
} else {
$hcaptchaOkay = TRUE;
}
As with the sitekey, you need to use your "secret" here.
At this point, hCaptcha should work.
Note that setting $hcaptchaOkay is not necessary and can be omitted. I was using it for something, then dropped it, but didn't change this bit of code.
The key thing is the setting of $aFout[]. If that array is empty, then the contact form is allowed to post. This is how things like missing name or subject get flagged. I've simply co-opted that by setting a message when hcaptcha fails.
I've also used the GET method for verification. The downside of that is 1) it's not guaranteed to be supported, and 2) the recommended POST method is more secure. So, if you want to prevent future headaches, figure out the POST method instead.
As with anything that mods a theme or plugin, to protect your changes from updates you should make copies and work from them.
Hope this helps.