Plugin para notificações via webhook de eventos das entidades do Mapas Culturais.
- Notificações automáticas quando entidades são criadas, atualizadas ou removidas
 - Suporte a múltiplos tipos de entidades (Agentes, Projetos, Espaços, Eventos, Oportunidades, Inscrições)
 - Configuração flexível via variáveis de ambiente ou código
 - Sistema de retry automático para falhas na entrega
 - Validação de assinatura com chave secreta (opcional)
 - Timeout configurável para requisições HTTP
 
- Copie a pasta 
Webhooksparasrc/plugins/ - Ative o plugin no arquivo de configuração:
 
// Em config/config.php ou config.d/plugins.php
'plugins' => [
    'Webhooks' => [
        'enabled' => true,
        'url' => 'https://seu-endpoint.com/webhook'
    ]
]Configure as seguintes variáveis no arquivo .env:
# Habilitar/desabilitar webhooks
WEBHOOKS_ENABLED=true
# URL do endpoint que receberá os webhooks (obrigatório quando habilitado)
WEBHOOKS_URL=https://exemplo.com/webhook
# Eventos para notificar (separados por vírgula)
WEBHOOKS_EVENTS=created,updated
# Entidades para monitorar (separados por vírgula, use * para todas)
WEBHOOKS_ENTITIES=Agent,Project,Space,Event,Opportunity,Registration
# Timeout da requisição HTTP em segundos
WEBHOOKS_TIMEOUT=5
# Chave secreta para assinatura dos webhooks (opcional)
WEBHOOKS_SECRET=sua-chave-secreta
# Número máximo de tentativas de entrega
WEBHOOKS_MAX_ATTEMPTS=5'plugins' => [
    'Webhooks' => [
        'enabled' => true,
        'url' => 'https://exemplo.com/webhook',
        'events' => ['created', 'updated', 'deleted'],
        'entities' => ['Agent', 'Project', 'Space'],
        'timeout' => 10,
        'secret' => 'minha-chave-secreta',
        'maxAttempts' => 3
    ]
]created- Quando uma entidade é criadaupdated- Quando uma entidade é atualizadadeleted- Quando uma entidade é removida
Agent- Agentes culturaisProject- ProjetosSpace- Espaços culturaisEvent- EventosOpportunity- OportunidadesRegistration- Inscrições*- Todas as entidades acima
O webhook será enviado via POST com o seguinte payload JSON:
{
  "event": "created",
  "entityClass": "MapasCulturais\\Entities\\Agent",
  "entityId": 123,
  "controller": "agent",
  "timestamp": "2024-01-15T10:30:00Z",
  "uuid": "a1b2c3d4e5f6g7h8",
  "changes": null,
  "entity": {
    "id": 123,
    "name": "Nome do Agente",
    "type": 1,
    "status": 1
  }
}event- Tipo do evento (created,updated,deleted)entityClass- Classe completa da entidadeentityId- ID da entidadecontroller- Nome do controller da entidadetimestamp- Data/hora do evento em ISO 8601uuid- Identificador único do webhookchanges- Array com os campos alterados (apenas para eventoupdated)entity- Dados da entidade
Se configurado com secret, o webhook incluirá um header de assinatura:
X-Webhook-Signature: sha256=hash_do_payload_com_sua_chave
function validateWebhook($payload, $signature, $secret) {
    $expectedSignature = 'sha256=' . hash_hmac('sha256', $payload, $secret);
    return hash_equals($expectedSignature, $signature);
}
// Uso
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$secret = 'sua-chave-secreta';
if (validateWebhook($payload, $signature, $secret)) {
    // Webhook válido, processar dados
    $data = json_decode($payload, true);
} else {
    // Webhook inválido
    http_response_code(401);
}O plugin implementa um sistema de retry automático:
- Tentativas são feitas em caso de falha na entrega
 - Número máximo de tentativas configurável via 
maxAttempts - Intervalos exponenciais entre tentativas
 - Webhooks são processados via sistema de jobs em background
 
Content-Type: application/json
X-Webhook-Event: created|updated|deleted
X-Webhook-Entity: Agent|Project|Space|Event|Opportunity|Registration
X-Webhook-ID: uuid-único-do-webhook
X-Webhook-Signature: sha256=hash (se secret configurado)
User-Agent: MapasCulturais-Webhook/1.0
<?php
// webhook-receiver.php
$payload = file_get_contents('php://input');
$data = json_decode($payload, true);
// Validar assinatura (se usando secret)
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
if ($signature && !validateWebhook($payload, $signature, 'sua-chave')) {
    http_response_code(401);
    exit('Unauthorized');
}
// Processar evento
switch ($data['event']) {
    case 'created':
        // Entidade foi criada
        logEvent("Nova {$data['controller']} criada: {$data['entity']['name']}");
        break;
    case 'updated':
        // Entidade foi atualizada
        $changes = implode(', ', array_keys($data['changes'] ?? []));
        logEvent("Entidade {$data['entityId']} atualizada: {$changes}");
        break;
    case 'deleted':
        // Entidade foi removida
        logEvent("Entidade {$data['entityId']} removida");
        break;
}
// Responder com sucesso
http_response_code(200);
echo 'OK';
function logEvent($message) {
    error_log(date('Y-m-d H:i:s') . " - $message\n", 3, 'webhooks.log');
}
function validateWebhook($payload, $signature, $secret) {
    $expectedSignature = 'sha256=' . hash_hmac('sha256', $payload, $secret);
    return hash_equals($expectedSignature, $signature);
}
?>Os webhooks são processados via jobs em background. Para monitorar:
- Verificar logs do sistema de jobs
 - Verificar status das tentativas na interface de administração
 - Monitorar resposta HTTP do seu endpoint
 
Use ferramentas como webhook.site para testar:
WEBHOOKS_URL=https://webhook.site/seu-uuid-aquiPara debug, você pode temporariamente modificar o código para logar informações:
// Em Plugin.php, método enqueueWebhook()
error_log('Enviando webhook: ' . json_encode($data));- Verificar se 
WEBHOOKS_ENABLED=true - Verificar se 
WEBHOOKS_URLestá configurada - Confirmar que a entidade está na lista 
WEBHOOKS_ENTITIES - Verificar se o evento está em 
WEBHOOKS_EVENTS 
- Verificar conectividade com a URL de destino
 - Confirmar que o endpoint responde com status 200
 - Verificar timeout (
WEBHOOKS_TIMEOUT) - Revisar logs do sistema de jobs
 
- Verificar configuração do 
secretem ambos os lados - Confirmar que o endpoint aceita 
Content-Type: application/json - Validar estrutura JSON esperada
 
Para contribuir com melhorias:
- Fork do repositório
 - Criar branch para feature/bugfix
 - Implementar testes se necessário
 - Enviar Pull Request
 
Este plugin segue a licença AGPL.