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

Google reCAPTCHA v3点击第二个按钮出现timeout-or-duplicate错误原因

分析与解决reCAPTCHA v3返回timeout-or-duplicate的问题

这个问题我之前排查过不少次,timeout-or-duplicate这个错误码本质上指向两种情况:要么请求到Google验证服务器超时,要么你提交的token已经被验证过一次了。结合你的代码细节,主要有几个高概率的原因和对应的解决办法:

1. 同一个token被重复提交验证

这是最常见的触发这个错误的原因。reCAPTCHA v3的token是一次性有效的,一旦提交到Google的siteverify接口验证过,再次用同一个token验证就会直接返回timeout-or-duplicate。

看你的代码逻辑:在verify函数里已经调用了VerifyCaptchaV3验证token,如果你的Buy Web服务方法内部,又再次调用了VerifyCaptchaV3来验证同一个token,那第二次验证就会触发这个错误——而Contact Us的方法里可能没有重复验证,所以正常工作。

解决办法:
确保每个token只被提交到Google验证一次:

  • 方案一:在verify函数验证通过后,直接执行对应的业务逻辑(调用ContactUs/Buy方法),不在业务方法里重复验证captcha;
  • 方案二:把verify里的验证结果(比如success状态)传递给业务方法,业务方法不再重复提交token到Google验证。

2. GET请求的URL编码问题

你的服务器端代码用WebClient.DownloadString以GET方式调用Google的siteverify接口,而reCAPTCHA的token是包含特殊字符的长字符串,直接拼到URL里会出现编码错误(比如+会被解析为空格,部分字符因URL长度限制被截断),这会让Google无法正确识别token,进而返回类似timeout-or-duplicate的错误。

解决办法:
改用POST请求调用siteverify接口,并且用表单数据提交参数(这也是Google推荐的方式)。修改后的C#代码示例:

public string VerifyCaptchaV3(string response)
{
    var postData = new List<KeyValuePair<string, string>>
    {
        new KeyValuePair<string, string>("secret", "your_actual_secret_key"),
        new KeyValuePair<string, string>("response", response)
    };
    var content = new FormUrlEncodedContent(postData);
    
    using (var client = new HttpClient())
    {
        var result = client.PostAsync("https://www.google.com/recaptcha/api/siteverify", content).Result;
        return result.Content.ReadAsStringAsync().Result;
    }
}

3. reCAPTCHA execute调用缺少action参数

你的前端grecaptcha.execute调用没有传入action参数,而reCAPTCHA v3要求每个操作对应一个唯一的action(比如contactus、buy)。虽然这不一定直接触发timeout-or-duplicate,但不符合Google的规范,可能会影响验证的准确性,甚至在某些边缘场景下触发异常。

另外注意:你代码里grecaptcha.execute('clientkeyValue')的key和加载api时render=keyValue的key不一致,这可能是笔误,要改成同一个站点key。

解决办法:
修改execute调用,传入对应的action参数:

grecaptcha.execute('your_actual_site_key', {action: action})

4. 快速重复点击导致token复用

如果用户快速点击Buy按钮两次,可能第二次请求还没获取到新的token,就复用了第一次的token,导致重复验证。

解决办法:
在按钮点击后暂时禁用按钮,直到ajax请求完成,避免重复点击:

function verify(action) {
    // 获取当前点击的按钮并禁用
    const targetBtn = action === "contactus" ? $("#submit") : $("#submit1");
    targetBtn.prop("disabled", true);
    
    grecaptcha.execute('your_actual_site_key', {action: action})
    .then(function (token) {
        $.ajax({
            type: "POST",
            url: "SomeWebService.asmx/VerifyCaptchaV3",
            data: JSON.stringify({ response: token }),
            success: function (r) {
                const result = JSON.parse(r);
                if (result.success === true) {
                    if (action === "contactus") {
                        // 调用ContactUs业务逻辑
                    } else if (action === "buy") {
                        // 调用Buy业务逻辑
                    }
                } else {
                    // 处理验证失败逻辑
                }
            },
            error: function() {
                // 处理请求错误
            },
            complete: function() {
                // 请求完成后恢复按钮可用状态
                targetBtn.prop("disabled", false);
            },
            contentType: "application/json; charset=utf-8",
            dataType: "json"
        });
    });
}

总结一下,优先排查重复验证token和GET请求编码这两个问题,大概率能解决你的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:34:59