PHP CURL验证reCAPTCHA时response字段被截断问题排查
解决PHP CURL调用reCAPTCHA时response字段被截断的问题
问题现状
用PHP CURL验证reCAPTCHA时,Postman发起的请求可正常通过,但CURL调用www.google.com/recaptcha/api/siteverify返回invalid-input-response错误。将请求指向本地脚本排查后,发现response字段被截断,这是导致验证失败的核心原因。
问题根源
- Content-Type设置错误:当前代码将请求头设为
text/html,但实际传递的是JSON数据,接收端无法正确解析参数结构。 - 参数格式不匹配:reCAPTCHA的
siteverify接口默认接受application/x-www-form-urlencoded格式的表单参数,而非JSON。用JSON传递时,不仅接口可能无法正确解析,本地接收端用$_POST也无法读取到正常的键值对($_POST仅解析表单编码的参数),进而出现字段截断。
修复方案
方案一:改用表单格式提交(推荐)
这是reCAPTCHA官方推荐的参数传递方式,无需处理JSON解析问题,能彻底避免字段截断:
$postData = [ 'secret' => $recaptcha_secret_key, 'response' => $recaptcha_response, 'remoteip' => "111.111.111.111" // 替换为实际用户IP ]; // 转换为表单编码格式 $formParams = http_build_query($postData); $ch = curl_init("https://www.google.com/recaptcha/api/siteverify"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_SSLVERSION, 6); // 指定TLS 1.2 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_NOSIGNAL, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); curl_setopt($ch, CURLOPT_TIMEOUT, 30); // 设置正确的表单类型请求头 curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/x-www-form-urlencoded"]); curl_setopt($ch, CURLOPT_POSTFIELDS, $formParams); $output = curl_exec($ch); curl_close($ch); // 解析验证结果 $result = json_decode($output, true); if ($result['success']) { // 验证通过逻辑 } else { // 验证失败,输出错误码 print_r($result['error-codes']); }
方案二:正确使用JSON格式提交(若需保留JSON)
如果必须用JSON传递参数,需确保请求头和接收端解析方式正确:
发送端代码修正:
$jdata = [ 'secret' => $recaptcha_secret_key, 'response' => $recaptcha_response, 'remoteip' => "111.111.111.111" // 替换为实际用户IP ]; $jsonParams = json_encode($jdata); $ch = curl_init("https://www.google.com/recaptcha/api/siteverify"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_SSLVERSION, 6); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_NOSIGNAL, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); curl_setopt($ch, CURLOPT_TIMEOUT, 30); // 设置正确的JSON类型请求头 curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]); curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonParams); $output = curl_exec($ch); curl_close($ch);
本地接收端代码修正(用于排查):
若要本地测试JSON格式请求,需读取原始请求体而非使用$_POST:
<h1>Request Data</h1> <?php // 读取原始POST数据 $rawData = file_get_contents('php://input'); $data = json_decode($rawData, true); if ($data) { foreach ($data as $key => $value) { $valueLen = strlen($value); echo "Key: $key<br>Value Length: $valueLen<br>Value: $value<br><br>"; } } else { echo "Invalid JSON data"; } ?> <h2>Done</h2>
关键提醒
- 优先使用表单格式提交,这是reCAPTCHA接口的标准要求,兼容性更强。
- 确保前端传递的
recaptcha_response是完整字符串,没有在前端被截断或编码错误。
内容的提问来源于stack exchange,提问作者rob boudrie
相关产品推荐
相关产品推荐

