Suas ideias em realidade digital!
Webhook é uma requisição HTTP enviada automaticamente por outro sistema quando um evento acontece.
Exemplos:
Mas existe um problema grave: qualquer pessoa pode tentar enviar requisição para seu endpoint.
Por isso você precisa validar a assinatura (HMAC).
<?php
header('Content-Type: application/json; charset=UTF-8');
$secret = "SEU_SEGREDO_SUPER_SECRETO";
$payload = file_get_contents("php://input");
$signature = $_SERVER["HTTP_X_SIGNATURE"] ?? "";
if (!$payload || !$signature) {
http_response_code(400);
echo json_encode(["error" => "Payload ou assinatura ausente"]);
exit;
}
---
A maioria dos gateways usa:
hash_hmac('sha256', payload, secret)
<?php
$computed = hash_hmac("sha256", $payload, $secret);
if (!hash_equals($computed, $signature)) {
http_response_code(401);
echo json_encode(["error" => "Assinatura inválida"]);
exit;
}
⚠️ Sempre use hash_equals() para evitar ataques de timing.
Alguns provedores enviam timestamp no header. Você pode bloquear requisições antigas:
<?php
$timestamp = $_SERVER["HTTP_X_TIMESTAMP"] ?? 0;
if (abs(time() - (int)$timestamp) > 300) {
http_response_code(403);
echo json_encode(["error" => "Requisição expirada"]);
exit;
}
---
<?php
$data = json_decode($payload, true);
if (!$data) {
http_response_code(400);
echo json_encode(["error" => "JSON inválido"]);
exit;
}
switch ($data["event"] ?? "") {
case "payment.approved":
// atualiza pedido
break;
case "subscription.cancelled":
// cancela plano
break;
default:
// loga evento desconhecido
}
---
Webhooks devem responder rápido (200 OK).
<?php
http_response_code(200);
echo json_encode(["status" => "ok"]);
---
<?php
$secret = "SEU_SEGREDO";
$payload = file_get_contents("php://input");
$signature = $_SERVER["HTTP_X_SIGNATURE"] ?? "";
if (!hash_equals(hash_hmac("sha256", $payload, $secret), $signature)) {
http_response_code(401);
exit;
}
$data = json_decode($payload, true);
http_response_code(200);
echo json_encode(["status" => "ok"]);
---