Receber um webhook em PHP e verificar a assinatura

Um webhook é um pedido que outro serviço lhe faz quando algo acontece. Num ficheiro PHP do seu site recebe-o em quatro passos: ler o corpo em bruto, verificar a assinatura, responder depressa e tratar depois. O passo da assinatura é o que impede que qualquer pessoa que descubra o endereço lhe envie dados falsos.

O esqueleto, em quatro passos

1 Leia o corpo em bruto com file_get_contents('php://input'). Não use ainda o json_decode: a assinatura calcula-se sobre o texto exactamente como chegou.
2 Calcule a assinatura esperada com hash_hmac('sha256', $corpo, $segredo), em que o segredo é o que combinou com o serviço. Leia a assinatura enviada no cabeçalho que o serviço indica, por exemplo $_SERVER['HTTP_X_ASSINATURA']. O nome do cabeçalho muda de serviço para serviço.
3 Compare com hash_equals, e não com ==. Se forem diferentes, responda 401 e pare.
4 Responda 200 depressa. Muitos serviços desistem e repetem o envio se não houver resposta em poucos segundos. Grave o evento num ficheiro ou numa tabela e deixe uma tarefa cron tratá-lo. Veja correr um script PHP a partir de uma tarefa cron.

Provar que funciona, sem esperar pelo serviço

1 Calcule uma assinatura de teste no terminal: echo -n '{"teste":1}' | openssl dgst -sha256 -hmac "SEGREDO".
2 Faça o pedido com ela, com curl -i -X POST, o cabeçalho da assinatura e o mesmo corpo. Veja o que é um webhook e como o testar com curl.
3 Repita com um corpo ligeiramente diferente. Tem de receber 401. Se receber 200, a verificação não está a funcionar.

Quando o webhook não chega ou é recusado

Sintoma Causa provável
A assinatura nunca bate Segredo diferente, ou o corpo foi alterado antes de calcular (analisado e reescrito).
O serviço fala em formato diferente Alguns juntam um prefixo ao valor, como o nome do algoritmo. Siga a documentação do serviço.
O pedido chega como GET, sem corpo Um redireccionamento de http para https, ou de www para sem www, transforma o POST em GET. Use o endereço final.
403 antes de chegar ao PHP Uma regra de segurança ou um bloqueio por IP. Veja erros do site explicados.
O mesmo evento duas vezes Os serviços repetem quando não recebem 200. Guarde o identificador do evento e ignore repetidos.
Um segredo no código é um segredo à vista. Guarde-o num ficheiro fora de public_html, e não o ponha num repositório. Veja manter senhas fora do código PHP. E nunca confie nos dados de um webhook sem assinatura como se fossem seus.
Registe cada pedido recebido (hora, resultado da verificação, tamanho do corpo), sem gravar os dados sensíveis. Quando o serviço jura que enviou e você não vê nada, o registo diz de que lado está o problema.

Quer um plano com PHP para receber os seus webhooks? Veja os planos de hospedagem.

Ver os planos

VEJA TAMBÉM

O que é um webhook e como o testar com curl

Receber mensagens: os webhooks da Evolution API

Os webhooks da Meta: verificar e receber

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 cupom)

Ver planos
  • 0 Usuários acharam útil
Esta resposta lhe foi útil?