You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确在PHP联系表单中集成reCaptcha V3?求助排查

问题排查与修复方案

我来帮你一步步拆解并解决遇到的这几个核心问题:


1. 解决ReferenceError: $ is not defined错误

这个报错的直接原因是页面没有引入jQuery库,但你的reCaptcha脚本里使用了$(jQuery的简写语法)。

修复步骤:

在页面的<head>标签中,务必在reCaptcha脚本之前引入jQuery库:

<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script src="https://www.google.com/recaptcha/api.js?render=YOUR_SITE_KEY"></script>

你也可以下载jQuery文件到本地服务器,使用本地路径引入,避免依赖外部CDN。

同时,你的reCaptcha脚本还有两个逻辑错误:

  • 生成token隐藏字段时存在语法漏洞:value="' + token + '&gt;' 缺少闭合的双引号,应改为 value="' + token + '"&gt;'
  • 当前脚本会在页面加载完成后自动提交表单,这不符合用户手动提交的预期,应该改为监听表单的提交事件,在用户点击按钮时再获取token。

修改后的reCaptcha脚本:

<script>
$(document).ready(function() {
    // 监听表单提交事件
    $('#contact').on('submit', function(e) {
        e.preventDefault(); // 阻止默认提交行为
        const form = this;
        
        grecaptcha.ready(function() {
            grecaptcha.execute('YOUR_SITE_KEY', {action: 'contact'}).then(function(token) {
                // 移除已存在的token和action字段(避免重复添加)
                $(form).find('input[name="token"], input[name="action"]').remove();
                // 添加合法的隐藏字段
                $(form).prepend('<input type="hidden" name="token" value="' + token + '">');
                $(form).prepend('<input type="hidden" name="action" value="contact">');
                // 提交表单
                form.submit();
            });
        });
    });
});
</script>

2. 解决"阈值设为1.0时表单仍可提交"的问题

这个问题的核心是原后端代码中,reCaptcha验证失败时没有设置$formok = false,所以即使reCaptcha判定为机器人,只要其他表单字段验证通过,表单依然会被提交。

另外还有两个细节需要修正:

  • $arrResponse["success"]是布尔值,不是字符串,应该用=== true判断,而非== '1'
  • 确保你确实修改了后端的阈值参数(比如从0.5改为1.0)

修复后的reCaptcha验证代码:

// reCaptcha V3 验证逻辑
define("RECAPTCHA_V3_SECRET_KEY", 'YOUR_SECRET_KEY');
$token = $_POST['token'] ?? ''; // 使用null合并运算符避免未定义索引报错
$action = $_POST['action'] ?? '';

// 先检查必要参数是否存在
if(empty($token) || empty($action)) {
    $formok = false;
    $errors[] = "reCaptcha验证失败:缺少必要参数";
} else {
    // 调用Google验证接口
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL,"https://www.google.com/recaptcha/api/siteverify");
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array(
        'secret' => RECAPTCHA_V3_SECRET_KEY,
        'response' => $token,
        'remoteip' => $_SERVER['REMOTE_ADDR'] // 可选:添加用户IP提高验证准确性
    )));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($ch);
    curl_close($ch);
    
    $arrResponse = json_decode($response, true);
    
    // 验证响应:注意success是布尔值,不是字符串
    if($arrResponse["success"] === true && $arrResponse["action"] === $action && $arrResponse["score"] >= 1.0) {
        // 验证通过,继续执行后续逻辑
    } else {
        $formok = false;
        $errors[] = "reCaptcha验证失败:你可能是机器人";
        // 可选:添加调试信息(上线前移除)
        // var_dump($arrResponse);
    }
}

3. 解决"添加$formok = false后表单一直提交失败"的问题

这个问题大概率是因为token没有正确提交到后端,导致reCaptcha验证一直失败,$formok被持续设为false。

你可以通过以下方式排查:

  1. 前端调试:提交表单前,打开浏览器开发者工具的Elements面板,查看<form id="contact">内部是否生成了token和action隐藏字段。
  2. 后端调试:在reCaptcha验证代码前添加调试代码,检查是否收到了token:
// 调试用(上线前务必移除)
var_dump($_POST);
exit;

另外,后端代码还有一个致命问题:session_start()的位置错误,它必须放在文件的最开头(任何输出之前),否则session无法正确初始化,导致错误信息无法回显到表单页面。

修复后的后端代码开头:

<?php
session_start(); // 必须放在最开头,确保session正常初始化

if( isset($_POST) ){
    // 剩余代码...
}

其他需要修复的小问题

  • 后端mail()函数参数为空:mail("",'',$emailbody,$headers); 需要填写收件人邮箱、邮件主题等必要参数,例如:
$to = "your-email@example.com";
$subject = "新的联系表单提交";
mail($to, $subject, $emailbody, $headers);
  • 表单中部分<option>的value与文本不一致:比如<option value="sessions" ...>Events</option>,会导致后端收到的enquiry值是sessions而非Events,建议保持value与文本一致,或者后端处理时做映射修正。

内容的提问来源于stack exchange,提问作者ThunderMunch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:43:22