Como fazer o file_get_contents () funcionar com HTTPS?

106

Estou trabalhando na configuração do processamento de cartão de crédito e preciso usar uma solução alternativa para o CURL. O código a seguir funcionou bem quando eu estava usando o servidor de teste (que não estava chamando um URL SSL), mas agora, quando estou testando no servidor em funcionamento com HTTPS, ele está falhando com a mensagem de erro "falha ao abrir fluxo".

function send($packet, $url) {
  $ctx = stream_context_create(
    array(
      'http'=>array(
        'header'=>"Content-type: application/x-www-form-urlencoded",
        'method'=>'POST',
        'content'=>$packet
      )
    )
  );
  return file_get_contents($url, 0, $ctx);
}
James Simpson
fonte

Respostas:

89

Tente o seguinte script para ver se há um wrapper https disponível para seus scripts php.

$w = stream_get_wrappers();
echo 'openssl: ',  extension_loaded  ('openssl') ? 'yes':'no', "\n";
echo 'http wrapper: ', in_array('http', $w) ? 'yes':'no', "\n";
echo 'https wrapper: ', in_array('https', $w) ? 'yes':'no', "\n";
echo 'wrappers: ', var_export($w);

a saída deve ser algo como

openssl: yes
http wrapper: yes
https wrapper: yes
wrappers: array(11) {
  [...]
}
VolkerK
fonte
@volker É por isso que pedi allow_url_fopen
Gordon
Bem, o que é estranho é que ele diz que o openssl está desativado, mas de acordo com phpinfo () ele foi compilado com ele, a menos que eu esteja vendo errado.
James Simpson
phpinfo () diz isso na linha de configuração ou há uma seção inteira chamada "OpenSSL"?
VolkerK
Ok, é apenas na linha de configuração, não uma seção para isso. Eu acho que esse é o problema?
James Simpson
Eu tenho tudo isso e ainda não funciona. E allow_url_fopen. Apenas urls não https funcionam no localhost.
Curtis
116

Para permitir o wrapper https:

  • a php_opensslextensão deve existir e estar habilitada
  • allow_url_fopen deve ser definido para on

No arquivo php.ini, você deve adicionar estas linhas se não existirem:

extension=php_openssl.dll

allow_url_fopen = On
Hassan
fonte
Ambos estão definidos como Ativados na minha instalação, mas ainda recebo o erro SSL "Aviso: file_get_contents (): SSL: Tempo limite do handshake esgotado"
Adamantus
53

Experimente o seguinte.

function getSslPage($url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_REFERER, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

Nota: Isso desativa a verificação SSL, significando que a segurança oferecida pelo HTTPS é perdida . Use este código apenas para teste / desenvolvimento local, nunca na internet ou outras redes públicas. Se este código funcionar, isso significa que o certificado SSL não é confiável ou não pode ser verificado, o que você deve procurar consertar como um problema separado.

Benjamin Crouzier
fonte
29
Por que você desabilitaria a verificação SSL ao lidar com o processamento de cartão de crédito?
Pedro de
Obrigado, o truque está aqui: curl_setopt ($ ch, CURLOPT_SSL_VERIFYPEER, FALSE);
Dylan B
46
$url= 'https://example.com';

$arrContextOptions=array(
      "ssl"=>array(
            "verify_peer"=>false,
            "verify_peer_name"=>false,
        ),
    );  

$response = file_get_contents($url, false, stream_context_create($arrContextOptions));

Isso permitirá que você obtenha o conteúdo do url, seja um HTTPS

Dushyant Dagar
fonte
Obrigado! Isso funcionou no meu fim. Estou tentando chamar FB Open Graph API :)
decodingpanda
Eu estava tentando acessar um domínio meu com certificado inválido apenas para fins de teste e, embora isso desabilite a validação de SSL, era o que eu precisava.
carla
Ótimo! Estou tentando há 5 dias baixar um calendário airbnb no meu site de teste XAMPP usando file_get_contents, isso resolveu o problema, obrigado.
JohnnyBeGood de
Funcionou para mim ao tentar me conectar à caixa de teste do Vagrant sem um certificado HTTP válido por https. Link para as opções de contexto do SSL do PHP sendo definidas aqui: php.net/manual/en/context.ssl.php ; verificar par = Exigir verificação do certificado SSL usado; verify_peer_name = Requer verificação do nome do par.
Anthony
isso não está quebrando a certificação SSL e é uma falha de segurança?
webchun
10

Isso provavelmente se deve ao fato de o servidor de destino não ter um certificado SSL válido.

Emil Vikström
fonte
O servidor solicitante não precisa ter um certificado SSL.
ceejayoz
15
Eu não disse o servidor solicitante, disse o servidor de destino.
Emil Vikström
2
Isso vai me ensinar a folhear. Heh! Por favor, aceite minhas desculpas e voto positivo.
ceejayoz
O servidor de destino não possui um certificado SSL válido.
James Simpson
@James, você obtém um erro se tentar conectar com cURL? Ou isso é absolutamente impossível de tentar?
Emil Vikström
6

Basta adicionar duas linhas em seu arquivo php.ini.

extension=php_openssl.dll

allow_url_include = On

está funcionando para mim.

Ritesh Chandora
fonte
1
Você provavelmente quer dizer, allow_url_fopenjá que a questão diz respeito à abertura do url, não incluindo.
shukshin.ivan
5

Eu tive o mesmo erro. Definir allow_url_include = Onem php.iniconsertou para mim.

Jim Jones
fonte
5

HTTPS é suportado a partir do PHP 4.3.0, se você compilou o suporte para OpenSSL. Além disso, certifique-se de que o servidor de destino possui um certificado válido, o firewall permite conexões de saída e allow_url_fopenno php.ini está definido como verdadeiro.

Gordon
fonte
Tenho PHP 5.2.8 com suporte a OpenSSL. Estou recebendo o mesmo erro com isso e o servidor de destino tem um certificado válido.
James Simpson
2
o firewall está configurado para permitir conexões https de saída? Normalmente, o servidor da web que executa https não é executado na porta 80. há algo mais no erro além de 'falha ao abrir o fluxo'?
Gordon
1
Pelo que eu sei, este é o erro completo: Aviso: fopen (https: // ...) [function.fopen]: falha ao abrir o stream: Não existe esse arquivo ou diretório em / home / user / public_html / test.php na linha 993
James Simpson
e allow_url_fopen em php.ini está definido para quê?
Gordon
Isso é estranho. Você pode fazer um GET em um URL HTTP e HTTPS para ver se funciona? sem o contexto do stream?
Gordon
3

No meu caso, o problema era devido ao WAMP usar um php.ini para CLI diferente do Apache, então suas configurações feitas por meio do menu WAMP não se aplicam à CLI. Basta modificar o CLI php.ini e ele funciona.

dtbarne
fonte
1

Às vezes, um servidor escolherá não responder com base no que vê ou não vê nos cabeçalhos de solicitação http (como um agente de usuário apropriado). Se você puder se conectar a um navegador, pegue os cabeçalhos que ele envia e imite-os em seu contexto de stream.

GZipp
fonte
0

Eu estava preso com https não funcional no IIS. Resolvido com:

file_get_contents ('https ..) não carregava.

  • baixe https://curl.haxx.se/docs/caextract.html
  • instalar em ..phpN.N / extras / ssl
  • edite php.ini com:

    curl.cainfo = "C: \ Arquivos de programas \ PHP \ v7.3 \ extras \ ssl \ cacert.pem" openssl.cafile = "C: \ Arquivos de programas \ PHP \ v7.3 \ extras \ ssl \ cacert.pem"

finalmente!

Teson
fonte
-1

PARA VERIFICAR SE UM URL ESTÁ ACIMA OU NÃO

O código em sua pergunta pode ser reescrito como uma versão funcional:

function send($packet=NULL, $url) {
// Do whatever you wanted to do with $packet
// The below two lines of code will let you know if https url is up or not
$command = 'curl -k '.$url;
return exec($command, $output, $retValue);
}
Homem comum
fonte