Не удается подключиться к сайту HTTPS с помощью cURL. Возвращает 0 контента длины. Что я могу сделать?

У меня есть сайт, который подключается с помощью cURL (последняя версия) к безопасному шлюзу для оплаты.

Проблема в том, что cURL всегда возвращает содержимое нулевой длины. Я получаю только заголовки. И только когда я установил cURL для возврата заголовков. У меня есть следующие флаги на месте.

curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_URL, $gatewayURI);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_POST, 1);

Возвращенный заголовок

HTTP/1.1 100 Continue

HTTP/1.1 200 OK
Date: Tue, 25 Nov 2008 01:08:34 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Content-Length: 0
Content-Type: text/html
Set-Cookie: ASPSESSIONIDxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; path=/
Cache-control: private

Я также пытался cURL'ing разных сайтов, и они возвращают контент в порядке. Я думаю, что проблема может иметь отношение к соединению https.

Я говорил с компанией, и они бесполезны.

Кто-нибудь еще сталкивался с этой ошибкой и знает обходной путь? Должен ли я бросить CURL и попытаться использовать fsockopen()?

Спасибо.:)

12 ответов

Решение

Вам также следует попробовать проверить сообщения об ошибках в curl_error(). Возможно, вам придется сделать это один раз после каждой функции curl_*.

http://www.php.net/curl_error

У меня была такая же проблема сегодня. Curl поставляется с устаревшим файлом для проверки подлинности сертификатов HTTPS.

получить новый от:

http://curl.haxx.se/ca/cacert.pem

сохранить его в какой-нибудь директории на вашем сайте

и добавить

curl_setopt ($curl_ch, CURLOPT_CAINFO, dirname(__FILE__)."/cacert.pem"); 

На каждый запрос:-)

Проигнорируйте любые тупые комментарии об отключении CURLOPT_VERIFYPEER и CURLOPT_VERIFYHOST!! Это делает ваш код уязвимым для атак посредников!

Декабрь 2016 г. редактировать:

Решите это правильно, используя метод Jasen, упомянутый ниже.

добавлять curl.cainfo=/etc/ssl/certs/ca-certificates.crt вам php.ini

Октябрь 2017 г. редактировать:

Теперь есть пакет composer, который помогает вам управлять сертификатами ca, чтобы вы не были уязвимы, если ваш cacert.pem устарел из-за отзыва сертификатов.

https://github.com/paragonie/certainty -> composer require paragonie/certainty:dev-master

Примечание: это строго не производственное использование. Если вы хотите быстро отладить, это может быть полезно. В противном случае, пожалуйста, используйте ответ @SchizoDuckie выше.

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);     
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); 

Просто добавь их. Оно работает.

Просто была очень похожая проблема и решила ее, добавив

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);

Судя по всему, сайт, который я получаю, перенаправляет в другое место, а php-curl по умолчанию не выполняет перенаправления.

У меня была ситуация, когда это помогло: (PHP 5.4.16 на Windows)

curl_setopt($ch, CURLOPT_SSLVERSION, 3);

Всякий раз, когда я тестирую что-то с помощью PHP/Curl, я сначала пробую это из командной строки, выясняю, что работает, а затем переношу свои опции на PHP.

Иногда вам нужно обновить сертификаты Curl до последней версии, чтобы не было ошибок с https.

Я использовал file_get_contents с помощью stream_create_context и работает нормально

$postdataStr = http_build_query($postdataArr);

$context_options = array (
        'http' => array (    <blink> // this will allways be http!!!</blink>
            'method' => 'POST',
            'header'=> "Content-type: application/x-www-form-urlencoded\r\n"
                . "Content-Length: " . strlen($postdataArr) . "\r\n"
                . "Cookie: " . $cookies."\r\n"
            'content' => $postdataStr
            )
        );

$context = stream_context_create($context_options);
$HTTPSReq = file_get_contents('https://www.example.com/', false, $context);

Я обнаружил эту ошибку в недавнем проекте приложения. Я писал для запуска из командной строки или из окна браузера, поэтому я использовал обнаружение сервера, чтобы получить относительный URL-адрес запрашиваемого документа. Проблема была в том, что сайт https, и каждый раз, когда я пытался получить доступ к http: // (тот же сервер), cURL услужливо менял его на https.

Это отлично работает в браузере, но из командной строки я получу ошибку SSL, даже если оба параметра имеют значение false. Что я должен был сделать,

1) Проверьте $_SERVER['HTTP_HOST']. Если используется, используйте ($_SERVER['HTTPS']? "Https: //": "http: //"). $ _ SERVER ['HTTP_HOST']

2) Проверьте $_SERVER['COMPUTERNAME'] и, если он соответствует производственному серверу, укажите URL-адрес https. (" https: // (имя сервера)")

3) Если ни одно из условий не выполнено, это означает, что я запускаю командную строку на другом сервере и использую " http://localhost/".

Теперь это сработало, но это взломать. Кроме того, я так и не понял, почему на одном сервере (https) cURL изменил мой URL, а на другом (также https) он оставил мой URL в покое.

Weird.

В вашей веб-хостинговой компании, из которой вы тестируете безопасную связь для шлюза, может возникнуть проблема, которая может не позволить вам сделать это.

также может быть имя пользователя, пароль, который необходимо указать перед подключением к удаленному хосту.

или, возможно, ваш IP-адрес должен быть в списке утвержденных IP-адресов для удаленного сервера, который необходимо установить для связи.

Лучший способ использовать https и избежать проблем с безопасностью - это использовать Firefox (или другой инструмент) и загрузить сертификат на свой сервер. Эта веб-страница мне очень помогла, и вот шаги, которые работали для меня:

1) Откройте в Firefox URL-адрес, который вы собираетесь использовать с CURL

2) В адресной строке нажмите на padlock > more information (FF версии могут иметь разные меню, просто найдите его). Нажмите кнопку Просмотр сертификата > Details Вкладка.

3) Выделите "правильный" сертификат в Certificate hierarchy, В моем случае это был второй из трех, который назывался "Центр сертификации cPanel, Inc.". Я только что нашел правильный метод "методом проб и ошибок".

4) Нажмите кнопку " Экспорт". В моем случае тот, кто работал, был тип файла "PEM с цепями" (снова методом проб и ошибок).

5) Затем в свой PHP-скрипт добавьте:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);    
curl_setopt($ch, CURLOPT_CAINFO, [PATH_TO_CRT_FILE]);

Кроме того, я бы сказал, что мы должны обратить внимание на тот факт, что эти шаги, вероятно, придется повторять один раз в год или всякий раз, когда сертификат URL заменяется или обновляется.

Вы используете метод POST, но предоставляете ли вы массив данных? Например

curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
Другие вопросы по тегам