Acapadev

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:

HeaderDescrição
X-Acapadev-SignatureAssinatura HMAC-SHA256 do payload
X-Acapadev-TimestampTimestamp UNIX do envio (proteção contra replay)
X-Acapadev-DeliveryID ú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:

PropriedadeTipoDescrição
$event->eventstringNome do evento recebido (ex: user.logout, role.updated)
$event->payloadarrayPayload 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).

Enter para selecionar ESC para sair