Skip to content

Runbook — falha de webhook EMIS/Unitel ​

Procedimento de suporte quando o pagamento foi feito (terminal, app ou Multicaixa) mas a fatura no SIGA continua em aberto.

Triagem rápida (60 segundos) ​

text
Encarregado pagou?
  ├─ Não → orientar pagamento / referência em /faturas
  └─ Sim → fatura ainda open no SIGA?
        ├─ Não (paid) → informar recibo; fim
        └─ Sim → seguir runbook abaixo

Prioridade imediata: se o dinheiro saiu da conta do pagador, a tesouraria pode confirmar manualmente na fatura (PaymentReferenceCard → confirmar pagamento) enquanto se investiga o webhook. Isto não substitui corrigir a integração — evita bloqueio operacional.

Informação a recolher ​

Preencher antes de escalar:

CampoExemplo
Escola (slug / hostname)colegio-esperanca.portal-siga.com
CanalMulticaixa (/gateway/confirm) ou Unitel (/unitel/confirm)
ID ou n.º da faturaUUID ou FAT-2026-…
Referência EMIS (9 dígitos)123456789
Montante pago (Kz inteiros)45000
Data/hora do pagamento
HTTP status + corpo JSON do webhookdo portal banco ou logs
Comprovativo do pagadorSMS, recibo ATM, captura app

Mapa HTTP → acção ​

Respostas do SIGA (POST …/gateway/confirm ou …/unitel/confirm):

HTTPMensagem típicaCausaQuem resolveAcção
401API key inválidamerchantId ou chave errada no portalEscola + bancoCopiar webhookApiKey de Definições → Integrações; não usar entidade EMIS como key
401Escola não identificadaIntegração inactiva ou key de outra escolaEscolaReinstalar integração; verificar tenant
400Corpo JSON inválidoPortal envia formato erradoBanco / integradorValidar JSON; Content-Type application/json
400Modo dev: invoiceId em faltaSimulador sem invoiceIdDevAdicionar invoiceId ao corpo
404Fatura não encontradaUUID errado ou fatura de outra escolaEscolaConfirmar invoiceId na fatura SIGA
404Plano ou fatura não encontradosSem plano pending_gateway ou referência erradaEscolaReemitir referência; criar plano gateway
409Referência não coincideReferência do portal ≠ plano SIGAEscola + bancoComparar dígitos; regenerar em /faturas
502Erro ao liquidar / permissões SGARPC register_payment falhouOperador plataformaSQL SGA; confirmar manual na tesouraria
200 + «já liquidada»IdempotênciaWebhook repetido—Normal; verificar recibo existente
Timeout / sem respostaRede / DNS / TLSHostname inacessível, certificadoOperador + escolaTestar URL pública; ADMIN /domains

Passos por perfil ​

Administrador escolar (tesouraria) ​

  1. Abrir /faturas → fatura em questão.
  2. Ver Referência EMIS e montante — comparar com comprovativo.
  3. Se pagamento confirmado pelo encarregado: Confirmar manualmente (PaymentReferenceCard).
  4. Definições → Integrações → copiar URL + API key correctas para o banco.
  5. Multicaixa: confirmar Merchant EMIS (não 99824 em produção).
  6. Unitel: URL deve ser /api/finance/gateway/unitel/confirm, não a rota Multicaixa.

Operador SIGA Plus (plataforma) ​

  1. ADMIN /tenants — escola activa, subscrição não suspensa.
  2. ADMIN /domains — hostname active, SSL ok.
  3. Pedir à escola: slug, invoiceId, referência, timestamp do webhook.
  4. Reproduzir com simulador (staging):
sh
npm run siga:gateway-simulate -- --invoice-id=<uuid> [--amount=45000]
npm run siga:gateway-simulate -- --invoice-id=<uuid> --unitel
  1. Se 502 com mensagem de permissões: escola precisa de SQL SGA (npm run siga:sql → APPLY_IN_SQL_EDITOR.sql).
  2. Registar em ticket interno: tenant_id, school_id, invoice_id, status HTTP, message.

Banco / EMIS / Unitel (externo) ​

  1. Confirmar URL de callback exacta (hostname público da escola).
  2. Confirmar corpo POST com reference, amount (Kz inteiros) e externalId, e os cabeçalhos X-SIGA-Timestamp/X-SIGA-Signature (relógio do emissor certo: ±5 min).
  3. Reenviar webhook de teste com mesma referência e montante da fatura SIGA.
  4. Fornecer logs do lado deles (timestamp, HTTP status recebido, corpo resposta).

Escalonamento ​

NívelQuandoDestino
L1Dúvida de referência ou confirmação manualSecretaria / tesouraria escolar
L2401/404/409 persistente após verificar IntegraçõesSuporte SIGA Plus (operador)
L3502, hostname, multi-tenant, SQL SGAEquipa técnica plataforma
L4Portal banco não envia webhook ou envia formato inválidoGestor contrato EMIS/Unitel da escola

SLA sugerido: L1 resolve no mesmo dia útil (confirmação manual). L2–L3 em 1–2 dias úteis com dados completos da tabela acima.

Observabilidade ​

Cada chamada ao webhook (sucesso ou falha) fica registada na tabela finance_gateway_webhook_events e em log JSON (tag: gateway-webhook). A tesouraria vê os últimos 5 eventos em Definições → Integrações (Multicaixa / Unitel).

Operador plataforma ​

Painel ADMIN → Webhooks gateway (/gateway-webhooks): totais 24h/7d, falhas recentes cross-tenant, escolas com mais falhas na semana.

sh
# Últimos 20 eventos (todas as escolas)
npm run siga:gateway-events-recent

# Só falhas
npm run siga:gateway-events-recent -- --failures-only

# Limite customizado
npm run siga:gateway-events-recent -- --limit=50

Requer SUPABASE_URL + SUPABASE_SECRET_KEY no .env. Se a tabela não existir, executar npm run siga:sql → APPLY_IN_SQL_EDITOR.sql.

Alertas Slack (opcional) ​

Defina SIGA_GATEWAY_ALERT_SLACK_URL (Incoming Webhook) no ambiente de produção do SIGA. Falhas com HTTP ≥ 400 disparam uma mensagem compacta (canal, escola, referência mascarada, mensagem).

Alerta de taxa de falha 24h (plataforma) ​

Quando a taxa de falha nas últimas 24h excede 25% (mínimo 5 eventos), o SIGA pode alertar a equipa de plataforma:

VariávelDefeitoDescrição
SIGA_GATEWAY_FAILURE_RATE_ALERT_SLACK_URLfallback SIGA_GATEWAY_ALERT_SLACK_URLSlack Incoming Webhook
SIGA_GATEWAY_FAILURE_RATE_ALERT_EMAIL_TO—Destinatários (Resend)
SIGA_GATEWAY_FAILURE_RATE_THRESHOLD0.25Limiar 0–1
SIGA_GATEWAY_FAILURE_RATE_MIN_EVENTS5Mínimo de eventos antes de alertar
SIGA_GATEWAY_FAILURE_RATE_COOLDOWN_HOURS6Evita spam (registo em saas_audit_logs)
  • Automático: após cada falha de webhook, o servidor verifica a taxa (se alertas configurados).
  • Cron: npm run siga:gateway-failure-rate-check (sugerido de hora a hora).
  • GitHub Actions: workflow gateway-failure-rate-check.yml (mesmos secrets, skip se Supabase em falta).

Modelo para pedir credenciais ao banco: Pedido ao banco EMIS/Unitel.

Logs estruturados ​

Procurar no stdout do servidor:

json
{"tag":"gateway-webhook","ok":false,"status":401,"channel":"multicaixa_express",…}

Referências são mascaradas nos logs e na BD (últimos 4 dígitos). A API key nunca é persistida.

Verificação pós-correcção ​

  • [ ] Simulador ou webhook de teste → HTTP 200, planSettled: true
  • [ ] Fatura de teste nova → pagamento real ou simulado → paid
  • [ ] Recibo visível na tesouraria
  • [ ] Escola documentou URL + API key no portal banco

Prevenção ​

  • Seguir Checklist de produção antes do go-live.
  • Não partilhar API keys entre escolas.
  • Após mudança de hostname (domínio custom), actualizar URL no portal banco.
  • CI nocturno @live alerta regressões (gateway-live.spec.ts).

Ver também ​

WEB vende · ADMIN controla · SIGA trabalha · PAYFLOW cobra · DOC explica