Acapadev SDK
Webhooks & Eventos
A comunicação principal entre o Acapadev ID e a tua aplicação faz-se através de webhooks silenciosos. Sempre que acontece algo crucial na rede (ex: um administrador revoga o acesso do Utilizador X, ou o Utilizador Y mudou de departamento), o Acapadev ID envia um pedido POST invisível para a tua aplicação.
A Rota Registada Automaticamente
A rota é criada automaticamente pelo AcapadevServiceProvider no endereço configurável (por padrão /acapadev/webhook):
POST /acapadev/webhook
Route Name: acapadev.webhook
Middleware: throttle:60,1, VerifyWebhookSignature
Configura este URL no painel de Developer Apps do Acapadev ID, na secção de Webhooks da tua App. O path pode ser personalizado através da variável de ambiente ACAPADEV_WEBHOOK_PATH.
Validação da Assinatura (HMAC)
O middleware VerifyWebhookSignature valida automaticamente cada pedido recebido antes de o processar. Três headers são verificados:
| Header | Descrição |
|---|---|
X-Acapadev-Signature | Assinatura HMAC-SHA256 do payload |
X-Acapadev-Timestamp | Timestamp UNIX do envio (proteção contra replay) |
X-Acapadev-Delivery | ID único de entrega (usado para deduplicação) |
// Lógica interna do SDK (não precisas de escrever isto)
$expectedSignature = hash_hmac('sha256', $timestamp . '.' . $payload, $webhookSecret);
if (!hash_equals($expectedSignature, $receivedSignature)) {
return response()->json(['error' => 'Assinatura inválida.'], 403);
}
Proteção Contra Replay Attack e Duplicação
Pedidos com um X-Acapadev-Timestamp com mais de 5 minutos são rejeitados com 403. Além disso, cada X-Acapadev-Delivery é guardado em cache durante 24 horas — se o mesmo webhook chegar duplicado, a aplicação responde 200 sem reprocessar.
O Evento WebhookReceived
Não precisas de validar assinaturas, descodificar JSON nem gerir respostas HTTP — o pacote trata de tudo isto. A tua única responsabilidade é "ouvir" o evento que o SDK dispara dentro do teu código. O evento expõe duas propriedades públicas:
| Propriedade | Tipo | Descrição |
|---|---|---|
$event->event | string | Nome do evento recebido (ex: user.logout, role.updated) |
$event->payload | array | Payload completo validado, incluindo dados do utilizador |
Exemplo de Listener
use Acapadev\Sdk\Events\WebhookReceived;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Log;
public function boot(): void
{
Event::listen(WebhookReceived::class, function (WebhookReceived $webhook) {
if ($webhook->event === 'user.logout') {
Log::info("Utilizador {$webhook->payload['user_id']} fez logout na central!");
// Destruir as sessões do utilizador aqui
}
});
}
Mapeamento para Eventos Nativos (Opcional)
Se preferires trabalhar com eventos Laravel dedicados em vez de inspecionar $event->event manualmente, podes mapear tipos de webhook para as tuas próprias classes de evento em config/acapadev.php:
'webhooks' => [
'events' => [
'user.logout' => \App\Events\AcapadevUserLoggedOut::class,
'user.role_updated' => \App\Events\AcapadevRoleUpdated::class,
],
],
Quando um webhook chega com um event mapeado, o SDK dispara tanto o WebhookReceived genérico como a tua classe de evento personalizada (recebendo o payload completo no construtor).