Chamar uma API web a partir do PHP com o cURL e ler a resposta em JSON

Para falar com uma API a partir do PHP usa-se o cURL: abre-se um pedido, envia-se, lê-se o código de estado (200, 401, 404…) e só depois se descodifica o JSON da resposta. A maior parte dos problemas vem de saltar o segundo passo: o código assume que correu bem e trata como dados uma mensagem de erro.

Um pedido GET completo

Este exemplo vai a um endereço de exemplo (api.example.com), envia a chave no cabeçalho e verifica tudo o que pode correr mal:

<?php
$ch = curl_init('https://api.example.com/v1/produtos');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_TIMEOUT        => 20,
  CURLOPT_HTTPHEADER     => [
    'Accept: application/json',
    'Authorization: Bearer ' . $chave,
  ],
]);
$corpo  = curl_exec($ch);
$estado = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$erro   = curl_error($ch);
curl_close($ch);

if ($corpo === false) { /* falha de rede: $erro diz porquê */ }
elseif ($estado !== 200) { /* a API respondeu, mas com erro */ }
else { $dados = json_decode($corpo, true); }

Enviar dados (POST em JSON)

Para enviar JSON acrescentam-se três coisas ao pedido: o método, o corpo e o cabeçalho que diz ao outro lado o que vai lá dentro.

CURLOPT_POST       => true,
CURLOPT_POSTFIELDS => json_encode($pedido),
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Accept: application/json'],

O que cada resposta quer dizer

Estado ou sintoma Significa O que fazer
curl_exec devolve false O pedido nem chegou ou não terminou. Leia curl_error(): tempo esgotado, nome que não se resolve, ligação recusada.
401 ou 403 A chave falta, está errada ou não tem permissão. Confira o cabeçalho de autorização e as permissões da chave no serviço.
404 O endereço do pedido está errado. Compare com a documentação da API, incluindo a versão no caminho.
429 Fez demasiados pedidos. Espere e reduza a frequência. Não repita em ciclo apertado.
500 ou 502 O erro é do outro lado. Tente mais tarde; guarde o pedido para repetir.
200, mas json_decode dá null A resposta não é JSON válido. Veja o que está mal no JSON.
Nunca desligue a verificação do certificado para «fazer passar». Pôr CURLOPT_SSL_VERIFYPEER a false cala o erro e deixa o pedido aberto a quem se meta no caminho. Um erro de certificado (cURL 60) resolve-se com o nome certo no endereço ou com o certificado do outro lado, não com isto.
A chave da API é uma palavra-passe. Não a escreva no código nem a publique num repositório: ponha-a num ficheiro fora da pasta pública (ficheiros .env e permissões). Quem a tem faz pedidos em seu nome, e muitas APIs cobram por pedido.
«Call to undefined function curl_init()»? A extensão cURL não está ligada naquela versão do PHP: ligue-a em Select PHP Version (ligar uma extensão do PHP). E ponha sempre um tempo limite: sem ele, uma API lenta prende o seu script até o PHP o cortar.

A chamada falha e a mensagem do cURL não lhe diz nada? Envie-nos o texto do erro e a versão do PHP, sem a chave da API.

Abrir um pedido de suporte

VEJA TAMBÉM

json_decode dá null: o que está mal no JSON

Palavras-passe fora do código: ficheiros .env

Ligar ao MySQL a partir do PHP: mysqli e PDO

Onde está o registo de erros do PHP

PRODUTO RECOMENDADO

Alojamento de sites com cPanel

Domínio e SSL incluídos, cópias diárias e o painel que já conhece. desde $6.60/mês (plano de 3 anos, com cupão)

Ver planos
  • 0 Utilizadores acharam útil
Esta resposta foi útil?