【问题标题】:cURL Recaptcha not working PHPcURL Recaptcha 不工作 PHP
【发布时间】:2015-09-30 00:30:36
【问题描述】:

我有什么

$data = array(
            'secret' => "my-app-secret",
            'response' => "the-response"
        );

$verify = curl_init();
curl_setopt($verify, CURLOPT_URL, "https://www.google.com/recaptcha/api/siteverify");
curl_setopt($verify, CURLOPT_POST, true);
curl_setopt($verify, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($verify, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($verify);

var_dump($response);

我得到了什么bool(false)(这意味着 curl_exec() 失败)

我的期望:JSON 对象响应

请帮忙。谢谢。

【问题讨论】:

  • 我认为 post fields 参数中不需要“http_build_query”。我的工作没有它。
  • @danielson317 google 接受application/x-www-form-urlencoded 格式和multipart/form-data 格式,当您在此处添加 http_build_query() 时,它会从第二个(这是给 CURLOPT_POSTFIELDS 一个数组时的默认格式)转换为首先,这里使用 OP 提供的 $data 需要 42 字节的带宽编码为第一个,但 280 字节的数据以multipart/form-data 格式编码! (multipart/form-data 对于大型和二进制数据更节省空间,但对于小型数据集,application/x-www-form-urlencoded 格式更节省空间。)

标签: php curl


【解决方案1】:
$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://www.google.com/recaptcha/api/siteverify",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "secret=$secret&response=$response",
  CURLOPT_HTTPHEADER => array(
    "cache-control: no-cache",
    "content-type: application/x-www-form-urlencoded"
  ),
));

$responsedata = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $responsedata;
}

【讨论】:

    【解决方案2】:

    通常我会做这样的事情

    public static function validateRecaptcha($recaptcha)
    {
      $dataArr = [
    
        'secret' => 'secret_key',
        'response' => $recaptcha,
        'remoteip'=> $_SERVER['REMOTE_ADDR'] //optional field
    
      ];
    
      $url = "https://www.google.com/recaptcha/api/siteverify";
    
      try
      {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($dataArr));
    
        $response = curl_exec($curl);
    
        //get error code
        $responseCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    
        if ($responseCode >= 400) 
        {
          throw new Exception ("Response error code: {$responseCode}");
        }
    
        $response = json_decode($response, true);        
    
        if ($response['success'] === true) 
        {
            // Success
            return 'success';
        }
    
        throw new Exception ($response);
      }
      catch(Exception $e)
      {
        return $e->getMessage();
      }
    }
    

    【讨论】:

      【解决方案3】:

      在 POST 中使用“file_get_contents”更容易:

      $postdata = http_build_query( [
          'secret'   => YOUR_SECRET_KEY,
          'response' => $_POST[ 'g-recaptcha-response' ]
      ] );
      
      $opts = [
          'http' => [
              'method'  => 'POST',
              'header'  => 'Content-type: application/x-www-form-urlencoded',
              'content' => $postdata
          ]
      ];
      
      $context  = stream_context_create( $opts );
      
      $result = file_get_contents(
          'https://www.google.com/recaptcha/api/siteverify', false, $context
      );
      
      $check = json_decode( $result );
      if( $check->success ) {
          echo "validate";
      } else {
          echo "wrong recaptcha";
      }
      

      【讨论】:

        【解决方案4】:

        对于那些喜欢使用 shell_exec curl的人:

            $arrayku = array();
            $arrayku['secret'] = 'Your_SECRET_KEY';
            $arrayku['response'] = trim($_POST['g-recaptcha-response']);
            $dataku = http_build_query($arrayku);
            $respon_google = shell_exec('curl -s -L -X POST "https://www.google.com/recaptcha/api/siteverify" --data "'.$dataku.'" --max-time 10 --compressed');
            $array_respon = json_decode($respon_google, true);
            if($array_respon['success']===false){
            echo 'Wrong recaptcha'; echo PHP_EOL;
                //goto wrong_captcha;
                exit;
            }
        

        【讨论】:

          【解决方案5】:

          因为您尝试通过 SSL 进行连接,所以您需要调整 cURL 选项来处理它。如果您添加curl_setopt($verify, CURLOPT_SSL_VERIFYPEER, false);

          ,则可以快速解决此问题

          CURLOPT_SSL_VERIFYPEER 设置为 false 将使它接受任何给它的证书,而不是验证它们。

          <?php
          
          $data = array(
                      'secret' => "my-secret",
                      'response' => "my-response"
                  );
          
          $verify = curl_init();
          curl_setopt($verify, CURLOPT_URL, "https://www.google.com/recaptcha/api/siteverify");
          curl_setopt($verify, CURLOPT_POST, true);
          curl_setopt($verify, CURLOPT_POSTFIELDS, http_build_query($data));
          curl_setopt($verify, CURLOPT_SSL_VERIFYPEER, false);
          curl_setopt($verify, CURLOPT_RETURNTRANSFER, true);
          $response = curl_exec($verify);
          
          var_dump($response);
          

          【讨论】:

          • 请删除 SSL_VERIFYPEER=false 东西。 Google 始终使用有效的证书。
          • 它曾经为我工作了 2 年多,没有你建议的额外线路 (CURLOPT_SSL_VERIFYPEER) 但今天我遇到了与报告相同的问题,通过添加这一行问题就消失了.所以谢谢你。但是我真的很想了解现在问题出在哪里?这是我的服务器还是谷歌?哪个证书现在没有验证,由哪一方验证?
          • 如果 google API 失败并且将 CURLOPT_SSL_VERIFYPEER 设置为 false 可以解决问题,请尝试更新您的 CA 证书。
          • CURLOPT_SSL_VERIFYHOST: 2, CURLOPT_SSL_VERIFYPEER: 1, CURLOPT_CAINFO:$path_to_cert 其中 path_to_cert 可以是来自 curl.se/ca/cacert.pem 的 cacert.pem 文件
          【解决方案6】:

          这是我发现的 cURL 的另一种方法,如果它可以帮助任何人。显然输入 $secret$response 变量才能正确传递。抱歉,问题是要求 cURL 解决方案,但这是我见过的最快的方法,所以我认为无论如何它都会添加它,因为我知道它会帮助那里的人。 :)

          $response = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".$secret."&response=".$response);
          $response = json_decode($response, true);
          if($response["success"] === true){
              // actions if successful
          }else{
              // actions if failed
          }
          

          【讨论】:

          • 如果您的 PHP 配置中有 allow_url_fopen=0,cURL 可能是唯一的选择。