Google reCAPTCHA v3集成遇阻求助:添加验证后表单失效
Google reCAPTCHA v3 实现问题排查与修复
我是新手开发者,正在做网站开发,死活搞不定Google reCAPTCHA v3的实现。看了一堆教程视频还是找不到问题——给按钮加g-recaptcha类后表单就没法正常工作,删掉这个类表单就恢复正常了。下面是我跟着教程写的代码:
原代码展示
JavaScript代码
<script src="https://www.google.com/recaptcha/api.js"></script> <script> function onSubmit(token) { document.getElementById("contact-form").submit(); } </script>
HTML表单代码
<div class="rainbow-contact-area rainbow-section-gapBottom" data-sal="slide-up" data-sal-duration="400" data-sal-delay="150"> <div class="container"> <div class="row mt--40 row--15"> <div class="col-lg-7"> <form class="contact-form-1 rainbow-dynamic-form" id="contact-form" method="POST" action="mail.php"> <div class="form-group"> <input type="text" name="contact-name" id="contact-name" placeholder="Your Name"> </div> <div class="form-group"> <input type="text" name="contact-phone" id="contact-phone" placeholder="Phone Number"> </div> <div class="form-group"> <input type="email" id="contact-email" name="contact-email" placeholder="Your Email"> </div> <div class="form-group"> <input type="text" id="subject" name="subject" placeholder="Your Subject"> </div> <div class="form-group"> <textarea name="contact-message" id="contact-message" placeholder="Your Message"></textarea> </div> <div class="form-group text-center"> <button name="submit" type="submit" id="submit" class="btn-default btn-large rainbow-btn g-recaptcha" data-sitekey="site_key" data-callback='onSubmit' data-action='submit'>Submit Now</button> </div> </form> </div>
PHP代码
<?php if ($_SERVER['REQUEST_METHOD'] == 'POST') { $recaptcha_url = 'https://www.google.com/recaptcha/api/siteverify'; $recaptcha_secret = 'sercet_key'; $recaptcha_response = $_POST['g-recaptcha-response']; $recaptcha = file_get_contents($recaptcha_url . '?secret=' . $recaptcha_secret . '&response=' . $recaptcha_response); $recaptcha = json_decode($recaptcha, true); $name = trim($_POST['contact-name']); $phone = trim($_POST['contact-phone']); $email = trim($_POST['contact-email']); $message = trim($_POST['contact-message']); if ($name == "") { $msg['err'] = " Name can not be empty!"; $msg['field'] = "contact-name"; $msg['code'] = FALSE; } else if ($phone == "") { $msg['err'] = " Phone number can not be empty!"; $msg['field'] = "contact-phone"; $msg['code'] = FALSE; } else if (!preg_match("/^[0-9 \-\+]{4,17}$/i", trim($phone))) { $msg['err'] = " Please put a valid phone number!"; $msg['field'] = "contact-phone"; $msg['code'] = FALSE; } else if ($email == "") { $msg['err'] = " Email can not be empty!"; $msg['field'] = "contact-email"; $msg['code'] = FALSE; } else if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) { $msg['err'] = " Please put a valid email address!"; $msg['field'] = "contact-email"; $msg['code'] = FALSE; } else if ($message == "") { $msg['err'] = " Message can not be empty!"; $msg['field'] = "contact-message"; $msg['code'] = FALSE; } else { $to = 'myemail2@mymail.com'; $subject = 'Website Form Submission'; $_message = '<html><head></head><body>'; $_message .= '<p>Name: ' . $name . '</p>'; $_message .= '<p>Message: ' . $phone . '</p>'; $_message .= '<p>Email: ' . $email . '</p>'; $_message .= '<p>Message: ' . $message . '</p>'; $_message .= '</body></html>'; $headers = 'MIME-Version: 1.0' . " "; $headers .= 'Content-type: text/html; charset=iso-8859-1' . " "; $headers .= 'From: <myemail@mymail.com' . " "; $headers .= 'cc: myemail2@mymail.com' . " "; mail($to, $subject, $_message, $headers, '-f myemail@mymail.com'); $msg['success'] = " Email has been sent successfully."; $msg['code'] = TRUE; } } echo json_encode($msg);?>
问题根源与修复方案
核心问题
你用了reCAPTCHA v2的调用方式(g-recaptcha类+点击回调)来实现v3,但v3是隐形验证,不需要用户手动触发验证,而是在后台自动完成打分。另外PHP代码存在逻辑顺序错误、拼写错误和内容错误。
修改后的完整代码
1. JavaScript代码(适配v3逻辑)
<script src="https://www.google.com/recaptcha/api.js?render=你的站点密钥"></script> <script> document.getElementById('contact-form').addEventListener('submit', function(e) { e.preventDefault(); // 阻止默认提交行为 // 调用reCAPTCHA v3获取验证token grecaptcha.execute('你的站点密钥', {action: 'submit'}).then(function(token) { // 创建隐藏字段存储token,提交给后端验证 let tokenInput = document.createElement('input'); tokenInput.type = 'hidden'; tokenInput.name = 'g-recaptcha-response'; tokenInput.value = token; document.getElementById('contact-form').appendChild(tokenInput); // 提交表单 document.getElementById('contact-form').submit(); }); }); </script>
2. HTML按钮(移除v2相关属性)
<button name="submit" type="submit" id="submit" class="btn-default btn-large rainbow-btn">Submit Now</button>
3. PHP代码(修正逻辑与错误)
<?php if ($_SERVER['REQUEST_METHOD'] == 'POST') { $msg = []; // 第一步:先验证reCAPTCHA $recaptcha_url = 'https://www.google.com/recaptcha/api/siteverify'; $recaptcha_secret = '你的密钥'; // 注意拼写是secret,原代码写的sercet是错误的 $recaptcha_response = $_POST['g-recaptcha-response'] ?? ''; // 用urlencode避免参数拼接错误 $recaptcha = file_get_contents($recaptcha_url . '?secret=' . urlencode($recaptcha_secret) . '&response=' . urlencode($recaptcha_response)); $recaptcha = json_decode($recaptcha, true); // 验证是否通过,score阈值可根据需求调整(0-1,越高越像真人) if (!$recaptcha['success'] || $recaptcha['score'] < 0.5) { $msg['err'] = "机器人验证失败,请重试!"; $msg['code'] = FALSE; echo json_encode($msg); exit; // 验证失败直接终止流程 } // 第二步:校验表单字段 $name = trim($_POST['contact-name'] ?? ''); $phone = trim($_POST['contact-phone'] ?? ''); $email = trim($_POST['contact-email'] ?? ''); $message = trim($_POST['contact-message'] ?? ''); if ($name == "") { $msg['err'] = "姓名不能为空!"; $msg['field'] = "contact-name"; $msg['code'] = FALSE; } else if ($phone == "") { $msg['err'] = "手机号不能为空!"; $msg['field'] = "contact-phone"; $msg['code'] = FALSE; } else if (!preg_match("/^[0-9 \-\+]{4,17}$/i", $phone)) { $msg['err'] = "请输入有效的手机号!"; $msg['field'] = "contact-phone"; $msg['code'] = FALSE; } else if ($email == "") { $msg['err'] = "邮箱不能为空!"; $msg['field'] = "contact-email"; $msg['code'] = FALSE; } else if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { $msg['err'] = "请输入有效的邮箱地址!"; $msg['field'] = "contact-email"; $msg['code'] = FALSE; } else if ($message == "") { $msg['err'] = "留言内容不能为空!"; $msg['field'] = "contact-message"; $msg['code'] = FALSE; } else { $to = 'myemail2@mymail.com'; $subject = '网站表单提交'; // 用htmlspecialchars防止XSS注入 $_message = '<html><head></head><body>'; $_message .= '<p>姓名: ' . htmlspecialchars($name) . '</p>'; $_message .= '<p>手机号: ' . htmlspecialchars($phone) . '</p>'; // 原代码把phone写成Message,已修正 $_message .= '<p>邮箱: ' . htmlspecialchars($email) . '</p>'; $_message .= '<p>留言: ' . htmlspecialchars($message) . '</p>'; $_message .= '</body></html>'; $headers = 'MIME-Version: 1.0' . "\r\n"; $headers .= 'Content-type: text/html; charset=utf-8' . "\r\n"; // 改成utf-8避免中文乱码 $headers .= 'From: <myemail@mymail.com>' . "\r\n"; // 原代码From标签未闭合,已修正 $headers .= 'cc: myemail2@mymail.com' . "\r\n"; // 发送邮件并判断结果 if(mail($to, $subject, $_message, $headers, '-f myemail@mymail.com')){ $msg['success'] = "邮件发送成功!"; $msg['code'] = TRUE; } else { $msg['err'] = "邮件发送失败,请稍后重试!"; $msg['code'] = FALSE; } } echo json_encode($msg); } ?>
额外注意事项
- 替换代码中的
你的站点密钥和你的密钥为Google reCAPTCHA控制台获取的真实密钥,注意区分站点密钥(site key)和密钥(secret key) - reCAPTCHA v3的score阈值(0.5)可根据业务调整,比如垃圾请求多的话可以提高到0.7
- 生产环境建议用cURL替代
file_get_contents,避免因allow_url_fopen关闭导致请求失败
内容的提问来源于stack exchange,提问作者DARKLiING
相关产品推荐
相关产品推荐

