Reputation: 159
Trying to get my form which uses google invisible recaptcha to work correctly with my my jQuery AJAX and PHP. From my research it seems that the token is not being sent to my PHP page correctly via AJAX. Keep getting the Error below from my PHP page when form is submitted.
array(2) {
["success"]=>
bool(false)
["error-codes"]=>
array(1) {
[0]=>
string(22) "invalid-input-response"
}
}
My HTML / jQuery Code Below
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Demo</title>
<script src="js/jquery-3.2.1.min.js"></script>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<style>
.grecaptcha-badge {
display: block;
float: left;
}
</style>
</head>
<body>
<form id="myForm">
<div>First Name*</div>
<div><input id="first_name" name="first_name" required="" type="text"></div>
<!--<span class="form-error">Please enter your first name.</span>-->
<div>Last Name*</div>
<div><input id="last_name" name="last_name" required="" type="text"></div>
<!--<span class="form-error">Please enter your last name.</span>-->
<button class="g-recaptcha" data-sitekey="6Ld1..." data-callback="onSubmit">submit</button>
</form>
<div id="status"></div>
<script defer>
function onSubmit(token) {
var f = $("#myForm");
$.ajax({
type: "POST",
url: "request.php",
data: f.serialize(),
dataType: "json",
beforeSend: function() {
$("#status").html("submitting data...");
},
success: function(response) {
$("#status").html(response.text);
if (response.type == "success") {
window.location.replace("/myaccount");
} else {
$("#status").html("Captcha failed.");
}
},
error: function() {
$("#status").html("Failed.");
}
});
}
</script>
</body>
</html>
My PHP code which is not handling the token correctly is below
<?php
if(isset($_POST['g-recaptcha-response'])) {
$result = json_decode(file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret=['secret key']&response=$_POST["g-recaptcha-response"]&remoteip=$_SERVER["REMOTE_ADDR"]'), TRUE);
//echo 'success';
if($result['success'] == 'true') {
// Captcha ok
echo 'success';
} else {
// Captcha failed
echo 'failed';
}
var_dump($result);
}
?>
Thanks in advance! The reCAPTCHA documentation really sucks....
Upvotes: 2
Views: 4086
Reputation: 46620
I just tested your front end code and it works fine, but your backend code is incorrect.
I've tweaked all the code to handle json and errors etc, but essentially the problem is because of the way your passing the $_POST
parameters to the site verify url.
Below is tested and working:
request.php
<?php
define('RECAPTCHA_SECRET_KEY', '******');
// json response helper
$json_response = function($data = []) {
header('Content-Type: application/json; charset=utf-8');
exit(json_encode($data));
};
// handle post
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
// define errors array
$errors = [];
// check g-recaptcha-response
if (!isset($_POST['g-recaptcha-response'])) {
$errors['recaptcha'] = 'Check the captcha form.';
}
// check other params
if (empty($_POST['first_name'])) {
$errors['first_name'] = 'First name is a required field.';
}
if (empty($_POST['last_name'])) {
$errors['last_name'] = 'Last name is a required field.';
}
// if all good call API else error out
if (!empty($errors)) {
$json_response(['errors' => $errors]);
}
// call recaptcha site verify
$response = file_get_contents(
'https://www.google.com/recaptcha/api/siteverify?'.http_build_query([
'secret' => RECAPTCHA_SECRET_KEY,
'response' => $_POST['g-recaptcha-response'],
'remoteip' => $_SERVER['REMOTE_ADDR'],
])
);
$response = json_decode($response, true);
// handle status and respond with json
if (intval($response["success"]) !== 1) {
$json_response(['errors' => ['recaptcha' => 'Captcha failed.']]);
} else {
$json_response(['success' => true]);
}
}
?>
Your frontend code, just added handling of the json.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Demo</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script src='https://www.google.com/recaptcha/api.js'></script>
<style>
.grecaptcha-badge {
display: block;
float: left;
}
.form-error {
display:none;
}
</style>
</head>
<body>
<form id="myForm">
<div>First Name*</div>
<div><input id="first_name" name="first_name" required="" type="text"></div>
<span class="form-error">Please enter your first name.</span>
<div>Last Name*</div>
<div><input id="last_name" name="last_name" required="" type="text"></div>
<span class="form-error">Please enter your last name.</span>
<button class="g-recaptcha" data-sitekey="******" data-callback="onSubmit">submit</button>
</form>
<div id="status"></div>
<script defer>
function onSubmit(token) {
var f = $("#myForm");
f.find('.form-error').hide();
$.ajax({
type: "POST",
url: "./request.php",
data: f.serialize(),
dataType: "json",
beforeSend: function() {
$("#status").html("submitting data...");
},
success: function(response) {
if (response.errors) {
if (response.errors.first_name) {
$('#first_name').parent().next().show();
}
if (response.errors.last_name) {
$('#last_name').parent().next().show();
}
if (response.errors.recaptcha) {
$('#status').html(response.errors.recaptcha);
} else {
$("#status").html("Please complete form.");
}
} else if (response.success) {
window.location.replace("/myaccount");
} else {
$("#status").html("Captcha failed.");
}
},
error: function() {
$("#status").html("Failed.");
}
});
}
</script>
</body>
</html>
Hope it helps.
Upvotes: 4