网站集成Google ReCAPTCHA V3(PHP)遇异常求排查
Google ReCAPTCHA V3(PHP版本)集成异常排查
参考示例实现Google ReCAPTCHA V3的PHP版本集成后,出现两类异常问题:
- 昨日测试时,mail.php返回验证成功(得分0.9),但form.js仍提示「Something went wrong, your message could not be sent」;
- 今日多次测试后,验证得分降至0.3,触发「Error! The security token has expired or you are a bot」错误,怀疑是多次提交导致,请求排查问题并完成集成,后续将更换IP测试。
昨日测试输出
mail.php - print_r($response)
{ "success": true, "challenge_ts": "2024-03-05T08:42:59Z", "hostname": "fakedomain.com", "score": 0.9, "action": "homepage" }
form.js提示
Something went wrong, your message could not be sent
今日测试输出
mail.php - print_r($response)
{ "success": true, "challenge_ts": "2024-03-06T20:58:07Z", "hostname": "fakedomain.com", "score": 0.3, "action": "homepage" }
form.js提示
Error! The security token has expired or you are a bot
当前实现代码
HTML文件
<!doctype html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Contact</title> <link rel="stylesheet" href="/assets/css/style.css" /> <!-- Google Recaptcha V3 Begin --> <script src="https://www.google.com/recaptcha/api.js?render=reCAPTCHA-site-key-goes-here"></script> <!-- Google Recaptcha V3 End --> </head> <body> <section> <div> <div class="card"> <h2 class="card-header">Contact Form</h2> <div class="card-body"> <form class="contact_form" method="post" action="mail.php"> <div class="row"> <div class="col-md-6 form-group"> <input name="name" type="text" class="form-control" placeholder="Name" required> </div> <div class="col-md-6 form-group"> <input name="email" type="email" class="form-control" placeholder="Email" required> </div> <div class="col-md-6 form-group"> <input name="phone" type="text" class="form-control" placeholder="Phone" required> </div> <div class="col-md-6 form-group"> <input name="subject" type="text" class="form-control" placeholder="Subject" required> </div> <div class="col-12 form-group"> <textarea name="message" class="form-control" rows="5" placeholder="Message" required></textarea> </div> <div class="row"> <div class="col-12"> <div class="contact_msg" style="display: none"> <p>Your message was sent.</p> </div> </div> </div> <div class="col-12"> <input type="submit" value="Submit Form" class="btn btn-success" name="post"> </div> <input type="hidden" id="token" name="token"> </div> </form> </div> </div> </div> </section> <!-- Google Recaptcha V3 Script Begin --> <script> grecaptcha.ready(function() { grecaptcha.execute('reCAPTCHA-site-key-goes-here', {action: 'homepage'}).then(function(token) { // console.log(token); document.getElementById("token").value = token; }); // refresh token every minute to prevent expiration setInterval(function(){ grecaptcha.execute('reCAPTCHA-site-key-goes-here', {action: 'homepage'}).then(function(token) { console.log( 'refreshed token:', token ); document.getElementById("token").value = token; }); }, 60000); }); </script> <!-- Google Recaptcha V3 Script End --> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <!-- form.js Begin --> <script src="form.js"></script> <!-- form.js End --> </body> </html>
mail.php
<?php if ($_SERVER["REQUEST_METHOD"] == "POST") { # BEGIN Setting reCaptcha v3 validation data $url = "https://www.google.com/recaptcha/api/siteverify"; $data = [ 'secret' => "reCAPTCHA-secret-key-goes-here", 'response' => $_POST['token'], 'remoteip' => $_SERVER['REMOTE_ADDR'] ]; $options = array( 'http' => array( 'header' => "Content-type: application/x-www-form-urlencoded ", 'method' => 'POST', 'content' => http_build_query($data) ) ); # Creates and returns stream context with options supplied in options preset $context = stream_context_create($options); # file_get_contents() is the preferred way to read the contents of a file into a string $response = file_get_contents($url, false, $context); # Takes a JSON encoded string and converts it into a PHP variable $res = json_decode($response, true); # END setting reCaptcha v3 validation data print_r($response); # Post form OR output alert and bypass post if false. NOTE: score conditional is optional # since the successful score default is set at >= 0.5 by Google. Some developers want to # be able to control score result conditions, so I included that in this example. if ($res['success'] == true && $res['score'] >= 0.5) { # Recipient email $mail_to = "mailto-address-goes-here@fakedomain.com"; # Sender form data $subject = trim($_POST["subject"]); $name = str_replace(array(" "," "),array(" "," ") , strip_tags(trim($_POST["name"]))); $email = filter_var(trim($_POST["email"]), FILTER_SANITIZE_EMAIL); $phone = trim($_POST["phone"]); $message = trim($_POST["message"]); if (empty($name) OR !filter_var($email, FILTER_VALIDATE_EMAIL) OR empty($phone) OR empty($subject) OR empty($message)) { # Set a 400 (bad request) response code and exit http_response_code(400); echo '<p class="alert-warning">Please complete the form and try again.</p>'; exit; } # Mail content $content = "Name: $name "; $content .= "Email: $email "; $content .= "Phone: $phone "; $content .= "Message: $message "; # Email headers $headers = "From: $name <$email>"; # Send the email $success = mail($mail_to, $subject, $content, $headers); if ($success) { # Set a 200 (okay) response code http_response_code(200); echo '<p class="alert alert-success">Thank You! Your message has been successfully sent.</p>'; } else { # Set a 500 (internal server error) response code http_response_code(500); echo '<p class="alert alert-warning">Something went wrong, your message could not be sent.</p>'; } } else { echo '<div class="alert alert-danger"> Error! The security token has expired or you are a bot. </div>'; } } else { # Not a POST request, set a 403 (forbidden) response code http_response_code(403); echo '<p class="alert-warning">There was a problem with your submission, please try again.</p>'; } ?>
form.js
(function ($) { 'use strict'; var form = $('.contact_form'), message = $('.contact_msg'), form_data; // Success function function done_func(response) { message.fadeIn() message.html(response); setTimeout(function () { message.fadeOut(); }, 10000); form.find('input:not([type="submit"]), textarea').val(''); } // fail function function fail_func(data) { message.fadeIn() message.html(data.responseText); setTimeout(function () { message.fadeOut(); }, 10000); } form.submit(function (e) { e.preventDefault(); form_data = $(this).serialize(); $.ajax({ type: 'POST', url: form.attr('action'), data: form_data }) .done(done_func) .fail(fail_func); }); })(jQuery);
内容的提问来源于stack exchange,提问作者Joe Bobby
相关产品推荐
相关产品推荐

