PHP

Como Usar Webhooks em PHP: Recebendo e Processando Eventos Externos em Produção

8 min de leitura

Como Usar Webhooks em PHP: Recebendo e Processando Eventos Externos em Produção

O que são Webhooks e Por Que Importam Webhooks são mecanismos de comunicação orientada por eventos que permitem que sistemas externos notifiquem sua aplicação sobre ocorrências específicas em tempo real. Diferente de APIs tradicionais onde você faz requisições e aguarda respostas, webhooks funcionam em modelo push: um serviço externo envia dados para você quando algo acontece. Na prática, é como assinar um boletim informativo — você não precisa verificar constantemente se há novidades; elas chegam automaticamente. Em PHP, receber webhooks significa criar um endpoint HTTP que aceita POST requests de serviços como Stripe, GitHub, Shopify ou APIs customizadas. Seu servidor processa esses eventos de forma assíncrona, permitindo atualizações em tempo real sem polling. Isso é fundamental para pagamentos, notificações de deployment, sincronização de dados e automações. Criando Seu Primeiro Webhook em PHP Estrutura Básica do Endpoint O primeiro passo é criar um arquivo PHP que ouça requisições HTTP. Vamos usar um exemplo prático de um webhook de pagamento do Stripe:

<h2>O que são Webhooks e Por Que Importam</h2>

<p>Webhooks são mecanismos de comunicação orientada por eventos que permitem que sistemas externos notifiquem sua aplicação sobre ocorrências específicas em tempo real. Diferente de APIs tradicionais onde você faz requisições e aguarda respostas, webhooks funcionam em modelo push: um serviço externo envia dados para você quando algo acontece. Na prática, é como assinar um boletim informativo — você não precisa verificar constantemente se há novidades; elas chegam automaticamente.</p>

<p>Em PHP, receber webhooks significa criar um endpoint HTTP que aceita POST requests de serviços como Stripe, GitHub, Shopify ou APIs customizadas. Seu servidor processa esses eventos de forma assíncrona, permitindo atualizações em tempo real sem polling. Isso é fundamental para pagamentos, notificações de deployment, sincronização de dados e automações.</p>

<h2>Criando Seu Primeiro Webhook em PHP</h2>

<h3>Estrutura Básica do Endpoint</h3>

<p>O primeiro passo é criar um arquivo PHP que ouça requisições HTTP. Vamos usar um exemplo prático de um webhook de pagamento do Stripe:</p>

<pre><code class="language-php">&lt;?php

// webhook.php

// Define o tipo de conteúdo como JSON

header(&#039;Content-Type: application/json&#039;);

// Lê o corpo da requisição

$input = file_get_contents(&#039;php://input&#039;);

$event = json_decode($input, true);

// Verifica se o JSON é válido

if (json_last_error() !== JSON_ERROR_NONE) {

http_response_code(400);

echo json_encode([&#039;error&#039; =&gt; &#039;JSON inválido&#039;]);

exit;

}

// Registra o evento recebido (importante para debug)

file_put_contents(&#039;logs/webhook.log&#039;, date(&#039;Y-m-d H:i:s&#039;) . &#039; - &#039; . $input . PHP_EOL, FILE_APPEND);

// Retorna sucesso imediatamente

http_response_code(200);

echo json_encode([&#039;status&#039; =&gt; &#039;received&#039;]);

?&gt;</code></pre>

<p>Este código simples recebe qualquer dados POST, valida o JSON e retorna um status 200. O cliente (serviço externo) precisa receber um status 2xx rapidamente—geralmente em menos de 5 segundos. Sempre processe eventos de forma assíncrona, nunca bloqueie a resposta com lógica pesada.</p>

<h3>Validação e Segurança</h3>

<p>Nunca confie cegamente em dados de webhooks. Serviços respeitáveis enviam assinaturas (signatures) para validar que a requisição é legítima:</p>

<pre><code class="language-php">&lt;?php

// webhook-seguro.php

define(&#039;WEBHOOK_SECRET&#039;, &#039;seu_secret_do_stripe&#039;);

header(&#039;Content-Type: application/json&#039;);

$input = file_get_contents(&#039;php://input&#039;);

$signature = $_SERVER[&#039;HTTP_STRIPE_SIGNATURE&#039;] ?? &#039;&#039;;

// Valida a assinatura (exemplo Stripe)

$timestamp = explode(&#039;,&#039;, $signature)[0];

$hash = explode(&#039;=&#039;, explode(&#039;,&#039;, $signature)[1])[1] ?? &#039;&#039;;

$signed_content = $timestamp . &#039;.&#039; . $input;

$expected_hash = hash_hmac(&#039;sha256&#039;, $signed_content, WEBHOOK_SECRET);

if (!hash_equals($hash, $expected_hash)) {

http_response_code(403);

echo json_encode([&#039;error&#039; =&gt; &#039;Assinatura inválida&#039;]);

exit;

}

$event = json_decode($input, true);

http_response_code(200);

echo json_encode([&#039;status&#039; =&gt; &#039;verified&#039;]);

?&gt;</code></pre>

<p>Esta abordagem usa HMAC-SHA256 para validar que a requisição veio realmente do Stripe. Sempre implemente essa validação em produção—é a diferença entre um sistema seguro e vulnerável.</p>

<h2>Processando Eventos com Lógica Robusta</h2>

<h3>Roteamento de Eventos</h3>

<p>Webhooks geralmente contêm um campo <code>type</code> ou <code>event</code> que indica qual evento ocorreu. Você deve rotear e processar cada tipo diferentemente:</p>

<pre><code class="language-php">&lt;?php

// webhook-router.php

class WebhookProcessor {

private $validatedEvent;

public function __construct($event) {

$this-&gt;validatedEvent = $event;

}

public function process() {

$eventType = $this-&gt;validatedEvent[&#039;type&#039;] ?? null;

switch ($eventType) {

case &#039;payment.success&#039;:

return $this-&gt;handlePaymentSuccess($this-&gt;validatedEvent[&#039;data&#039;]);

case &#039;payment.failed&#039;:

return $this-&gt;handlePaymentFailed($this-&gt;validatedEvent[&#039;data&#039;]);

case &#039;user.created&#039;:

return $this-&gt;handleUserCreated($this-&gt;validatedEvent[&#039;data&#039;]);

default:

error_log(&quot;Evento desconhecido: $eventType&quot;);

return false;

}

}

private function handlePaymentSuccess($data) {

// Atualiza status do pedido no banco

$orderId = $data[&#039;order_id&#039;];

$amount = $data[&#039;amount&#039;];

// Simula atualização DB

error_log(&quot;Pagamento recebido: Order #$orderId - R$ $amount&quot;);

// Envia email de confirmação

mail($data[&#039;customer_email&#039;],

&#039;Pagamento Confirmado&#039;,

&#039;Seu pagamento foi processado com sucesso.&#039;);

return true;

}

private function handlePaymentFailed($data) {

error_log(&quot;Pagamento falhou: &quot; . $data[&#039;error_message&#039;]);

return false;

}

private function handleUserCreated($data) {

// Sincroniza com CRM, envia boas-vindas, etc

error_log(&quot;Novo usuário: &quot; . $data[&#039;email&#039;]);

return true;

}

}

// No seu arquivo webhook principal

$input = file_get_contents(&#039;php://input&#039;);

$event = json_decode($input, true);

$processor = new WebhookProcessor($event);

$processor-&gt;process();

http_response_code(200);

?&gt;</code></pre>

<h3>Implementação com Fila (Recomendado)</h3>

<p>Para aplicações críticas, adicione eventos a uma fila (Redis, RabbitMQ, ou até banco de dados) em vez de processar sincronamente:</p>

<pre><code class="language-php">&lt;?php

// webhook-com-fila.php

class WebhookQueue {

private $redisClient;

public function __construct() {

$this-&gt;redisClient = new Redis();

$this-&gt;redisClient-&gt;connect(&#039;localhost&#039;, 6379);

}

public function enqueue($event) {

$queueKey = &#039;webhooks:&#039; . $event[&#039;type&#039;];

$this-&gt;redisClient-&gt;lpush($queueKey, json_encode($event));

error_log(&quot;Evento enfileirado: &quot; . $event[&#039;type&#039;]);

return true;

}

}

// Seu webhook endpoint

$input = file_get_contents(&#039;php://input&#039;);

$event = json_decode($input, true);

// Valida assinatura aqui (código omitido por brevidade)

$queue = new WebhookQueue();

$queue-&gt;enqueue($event);

http_response_code(202); // Accepted - será processado em breve

echo json_encode([&#039;status&#039; =&gt; &#039;queued&#039;]);

?&gt;</code></pre>

<p>Com filas, você retorna 202 imediatamente e processa o evento em background via worker scripts (rodados com cron ou supervisord), aumentando confiabilidade e performance.</p>

<h2>Testes e Monitoramento</h2>

<h3>Testando Webhooks Localmente</h3>

<p>Use ferramentas como <code>ngrok</code> para expor seu servidor local à internet:</p>

<pre><code class="language-bash"># Terminal 1: Inicia seu servidor PHP

php -S localhost:8000

Terminal 2: Expõe via ngrok

ngrok http 8000

Isso gera URL pública como https://abc123.ngrok.io</code></pre>

<p>Então configure o webhook em seu serviço de teste apontando para <code>https://abc123.ngrok.io/webhook.php</code>. Você verá todas as requisições no terminal do ngrok em tempo real, facilitando debug.</p>

<h3>Logging e Monitoramento</h3>

<p>Sempre registre webhooks recebidos, respostas processadas e erros:</p>

<pre><code class="language-php">&lt;?php

// webhook-logger.php

class WebhookLogger {

private $logFile;

public function __construct($logPath = &#039;logs/webhooks.log&#039;) {

$this-&gt;logFile = $logPath;

}

public function log($event, $status, $error = null) {

$entry = json_encode([

&#039;timestamp&#039; =&gt; date(&#039;c&#039;),

&#039;event_type&#039; =&gt; $event[&#039;type&#039;] ?? &#039;unknown&#039;,

&#039;status&#039; =&gt; $status,

&#039;error&#039; =&gt; $error,

&#039;ip_source&#039; =&gt; $_SERVER[&#039;REMOTE_ADDR&#039;]

]) . PHP_EOL;

file_put_contents($this-&gt;logFile, $entry, FILE_APPEND);

}

}

// Uso

$logger = new WebhookLogger();

try {

$processor-&gt;process();

$logger-&gt;log($event, &#039;success&#039;);

} catch (Exception $e) {

$logger-&gt;log($event, &#039;failed&#039;, $e-&gt;getMessage());

http_response_code(500);

}

?&gt;</code></pre>

<p>Revisar logs regularmente ajuda identificar padrões de falha e comportamentos anormais antes que causem problemas maiores.</p>

<h2>Conclusão</h2>

<p>Webhooks são essenciais para integrar sua aplicação PHP com serviços externos modernos. Os três pontos principais a lembrar são: (1) <strong>sempre valide e autentique</strong> requisições via assinaturas HMAC; (2) <strong>responda rapidamente</strong> com status 2xx e processe eventos de forma assíncrona usando filas quando possível; (3) <strong>registre tudo</strong> em logs estruturados para debugging e monitoramento de produção. Com essas práticas, você construirá sistemas robustos que reagem a eventos em tempo real sem sacrificar performance ou segurança.</p>

<h2>Referências</h2>

<ul>

<li>https://stripe.com/docs/webhooks</li>

<li>https://docs.github.com/en/developers/webhooks-and-events/webhooks</li>

<li>https://www.php.net/manual/en/book.hash.php</li>

<li>https://redis.io/</li>

<li>https://www.php-fig.org/psr/psr-18/</li>

</ul>

Comentários

Mais em PHP

Upload de Arquivos com PHP: Validação e Segurança na Prática
Upload de Arquivos com PHP: Validação e Segurança na Prática

Upload de Arquivos com PHP: Validação e Segurança Upload de arquivos é uma fu...

Guia Completo de Laravel: Instalação, Estrutura de Pastas e Primeiros Passos
Guia Completo de Laravel: Instalação, Estrutura de Pastas e Primeiros Passos

Instalação e Configuração Inicial A instalação do Laravel é simples graças ao...

Boas Práticas de Laços de Repetição: for, while, foreach e do-while para Times Ágeis
Boas Práticas de Laços de Repetição: for, while, foreach e do-while para Times Ágeis

Fundamentos dos Laços de Repetição Um laço de repetição é uma estrutura de co...