57

I'm building a personal stock platform (not distributed). A component I would like to have is the EPS graph on this page:

https://eresearch.fidelity.com/eresearch/evaluate/fundamentals/earnings.jhtml?stockspage=earnings&symbols=AAPL&showPriceLine=yes

As you can see, the page is https, so after days of hammering things out, I enabled openssl and now it seems to work for all https pages such as the homepages of facebook and twitter, however it is still not working for the one I need.

file_get_contents('https://facebook.com'); /* works */
file_get_contents('https://twittercom'); /* works */
file_get_contents('https://eresearch.fidelity.com/eresearch/evaluate/fundamentals/earnings.jhtml?stockspage=earnings&symbols=AAPL&showPriceLine=yes');

I'm getting the warning:

Warning: file_get_contents(): SSL: crypto enabling timeout in C:\xampp\htdocs\index.php on line 3
Warning: file_get_contents(): Failed to enable crypto in C:\xampp\htdocs\index.php on line 3
Warning: file_get_contents(https://eresearch.fidelity.com/eresearch/evaluate/fundamentals/earnings.jhtml?stockspage=earnings&symbols=AAPL&showPriceLine=yes): failed to open stream: operation failed in C:\xampp\htdocs\index.php on line 3
Fatal error: Maximum execution time of 30 seconds exceeded in C:\xampp\htdocs\index.php on line 3

The only difference I can see is that the fidelity page has a triangle near the https label.

fidelity https label

John Smith
  • 1,750
  • 3
  • 18
  • 31
  • http://stackoverflow.com/questions/1975461/file-get-contents-with-https – René Höhle Dec 29 '12 at 02:45
  • 1
    @Stony I have tested all the stackoverflow answers. For the link you provided, the first answer: `openssl: yes http wrapper: yes https wrapper: yes` From phpinfo() all SSL options opened or enabled. The second answer: `extension=php_openssl.dll` and `allow_url_include = On` are enabled in php.ini. – John Smith Dec 29 '12 at 02:46
  • Very interesting i've tried it but i got an timeout after 30 seconds. There is something wrong with the target site. Perhaps you try a curl request. – René Höhle Dec 29 '12 at 02:47
  • Hm... then I will have to figure out how to configure CURL. – John Smith Dec 29 '12 at 02:48
  • Ok with CURL its the same problem. Perhaps the people who made the site have changed something that you cannot get the data from the site. Perhaps its the aim. Perhaps the site has an API? – René Höhle Dec 29 '12 at 02:51
  • I enabled CURL. I highly doubt there is an API, but I will check. – John Smith Dec 29 '12 at 02:52

4 Answers4

62

Ok I have found a solution. The problem is that the site uses SSLv3. And I know that there are some problems in the openssl module. Some time ago I had the same problem with the SSL versions.

<?php
function getSSLPage($url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_SSLVERSION,3); 
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

var_dump(getSSLPage("https://eresearch.fidelity.com/eresearch/evaluate/analystsOpinionsReport.jhtml?symbols=api"));
?>

When you set the SSL Version with curl to v3 then it works.

Edit:

Another problem under Windows is that you don't have access to the certificates. So put the root certificates directly to curl.

http://curl.haxx.se/docs/caextract.html

here you can download the root certificates.

curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . "/certs/cacert.pem");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);

Then you can use the CURLOPT_SSL_VERIFYPEER option with true otherwise you get an error.

smottt
  • 3,272
  • 11
  • 37
  • 44
René Höhle
  • 26,716
  • 22
  • 73
  • 82
  • 3
    Yes the problem is that the `file_get_contents` method use an old SSL version. There are some Bug reports but until now there are not solutions. – René Höhle Dec 29 '12 at 02:59
  • 2
    @Stony Do you happen to have a reference to which PHP bug report is applicable for this? – Magnus Nordlander Jan 09 '13 at 10:05
  • 4
    Is there a solution without curl? – rubo77 Jan 14 '14 at 15:41
  • 1
    I don't think this is a PHP bug (it's not that PHP has an old SSL version) - it's the the site you're connecting to is using old SSL. SSLv3 has effectively been obsolete since 1999! [This pull request](https://github.com/php/php-src/pull/469) adds control of which crypto library to use, but it looks like it will only appear in PHP 5.5 in some future version. In the mean time, curl does solve the problem, or you can achieve the same with the pecl_http extension. – Synchro Jan 14 '14 at 16:21
  • 2
    Set CURLOPT_SSL_VERIFYPEER to FALSE only if you know what you're doing. – Marius Balčytis Mar 13 '14 at 13:26
11

Had same problem - it was somewhere in the ca certificate, so I used the ca bundle used for curl, and it worked. You can download the curl ca bundle here: https://curl.haxx.se/docs/caextract.html

For encryption and security issues see this helpful article:
https://www.venditan.com/labs/2014/06/26/ssl-and-php-streams-part-1-you-are-doing-it-wrongtm/432

Here is the example:

    $url = 'https://www.example.com/api/list';
    $cn_match = 'www.example.com';

    $data = array (     
        'apikey' => '[example api key here]',               
        'limit' => intval($limit),
        'offset' => intval($offset)
        );

    // use key 'http' even if you send the request to https://...
    $options = array(
        'http' => array(
            'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
            'method'  => 'POST',                
            'content' => http_build_query($data)                
            )
        , 'ssl' => array(
            'verify_peer' => true,
            'cafile' => [path to file] . "cacert.pem",
            'ciphers' => 'HIGH:TLSv1.2:TLSv1.1:TLSv1.0:!SSLv3:!SSLv2',
            'CN_match' => $cn_match,
            'disable_compression' => true,
            )
        );

    $context  = stream_context_create($options);
    $response = file_get_contents($url, false, $context);

Hope that helps

user7457877
  • 161
  • 2
  • 3
  • 1
    Found a shorter answer for my needs : https://stackoverflow.com/questions/26148701/file-get-contents-ssl-operation-failed-with-code-1-and-more – Chopchop Sep 06 '18 at 12:44
4

A workaround that works for me is to disable peer verification. Be careful when you use it because it shouldn't be use in production.

$arrContextOptions = array(
      "ssl" => array(
        "verify_peer" => false,
        "verify_peer_name" => false,
      )
);  
  
$context = stream_context_create($arrContextOptions);
$contents = file_get_contents($url,false,$context);
m50
  • 766
  • 8
  • 11
0

Check which php.ini file is currently used by php-fpm service. Set the curl_cainfo and openssl.cafile variables are using the same and vaid ca file.this will resolve my issue.

Liju
  • 1
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community May 01 '23 at 12:41