Aparência
EMIS / Multicaixa Express e Unitel Money
Guia para tesourarias e equipas técnicas configurarem pagamentos automáticos de propinas no SIGA Plus.
Visão geral
text
Fatura emitida → plano pending_gateway (referência EMIS)
→ pagador paga no terminal / app
→ gateway externo POST webhook → SIGA
→ register_payment + plano settled
→ alternativa: confirmar manualmente (PaymentReferenceCard)O SIGA gera referências determinísticas (mesma fatura → mesma referência). A confirmação automática depende do webhook configurado no portal EMIS ou Unitel.
Onde configurar no SIGA
- Entrar como administrador escolar.
- Definições → Integrações.
- Instalar Multicaixa Express e/ou Unitel Money.
- Copiar a API key de webhook gerada na instalação.
- Para Multicaixa: preencher Merchant EMIS / Multicaixa (4–6 dígitos).
A secção «Webhook de confirmação» na integração mostra URL e API key prontos a copiar.
Entidade EMIS por escola
Cada escola deve usar a entidade EMIS atribuída pelo banco/EMIS — não o valor de demonstração partilhado.
| Campo na UI | Campo no config | Regra |
|---|---|---|
| Merchant EMIS / Multicaixa | merchantId ou emisEntity | 4–6 dígitos |
| (vazio) | — | não há referências Multicaixa até a entidade ser preenchida |
A entidade entra nas referências Multicaixa geradas em /faturas e no PaymentReferenceCard. O webhook valida montante e referência contra o plano pending_gateway da escola.
Webhook EMIS / Multicaixa Express
| Item | Valor |
|---|---|
| Método | POST |
| URL | https://{hostname-siga}/api/finance/gateway/confirm |
| Content-Type | application/json |
| Autenticação | assinatura HMAC-SHA256 com a API key de Integrações (a key não vai no pedido) |
| Cabeçalhos | X-SIGA-Timestamp: <segundos Unix> e X-SIGA-Signature: sha256=<hex> |
Corpo JSON:
json
{
"reference": "123456789",
"amount": 45000,
"externalId": "<id da transacção no provedor>"
}reference— a referência que o SIGA emitiu no plano de pagamento (só se liquidam referências de planos pendentes).amount— valor em kwanzas inteiros (ex.45000= 45 000 Kz).externalId— obrigatório; o mesmo identificador nunca gera dois recibos.invoiceId— opcional; se vier, tem de ser a fatura do plano da referência.
Assinatura: X-SIGA-Signature = "sha256=" + hex(HMAC_SHA256(apiKey, timestamp + "." + corpo)), sobre os bytes exactos do corpo enviado. Pedidos com carimbo a mais de 5 minutos são recusados.
sh
ts=$(date +%s); body='{"reference":"123456789","amount":45000,"externalId":"tx-1"}'
sig=$(printf '%s.%s' "$ts" "$body" | openssl dgst -sha256 -hmac "$API_KEY" -hex | sed 's/^.* //')
curl -X POST "$URL" -H 'Content-Type: application/json' \
-H "X-SIGA-Timestamp: $ts" -H "X-SIGA-Signature: sha256=$sig" --data "$body"Resposta esperada: 200 com { "ok": true } quando o pagamento for registado.
Webhook Unitel Money
Unitel usa URL dedicada (canal fixo unitel_money):
| Item | Valor |
|---|---|
| Método | POST |
| URL | https://{hostname-siga}/api/finance/gateway/unitel/confirm |
| Corpo e assinatura | iguais ao EMIS (reference, amount, externalId; cabeçalhos X-SIGA-*) |
Configure esta URL no portal Unitel Money, não a rota Multicaixa genérica.
Hostname do SIGA
Em produção use o hostname público da escola (subdomínio portal-siga.com ou domínio custom activo). Exemplos:
https://colegioesperanca.portal-siga.com/api/finance/gateway/confirmhttps://pagamentos.escola.ao/api/finance/gateway/unitel/confirm
O hostname deve ser o mesmo que os encarregados usam para aceder ao SIGA — o webhook corre na mesma instância multi-tenant.
Teste local (desenvolvimento)
sh
# .env — chave dev partilhada (simulador)
SIGA_GATEWAY_DEV_API_KEY=dev-gateway-key-local
npm run siga:gateway-simulate -- --invoice-id=<uuid-fatura> [--amount=45000]
npm run siga:gateway-simulate -- --invoice-id=<uuid-fatura> --unitelCom integração instalada na escola, use a API key real copiada da UI em vez da chave dev.
Verificação @live (CI)
Com Supabase configurado, npm run siga:e2e-playwright-live inclui gateway-live.spec.ts:
- Modo dev —
SIGA_GATEWAY_DEV_API_KEY+invoiceIdno corpo - Modo escola EMIS —
webhookApiKeyem Integrações → Multicaixa Express - Modo Unitel —
POST /api/finance/gateway/unitel/confirm(dev key ouwebhookApiKeyUnitel)
Provisionamento → fatura → webhook → liquidada.
sh
SIGA_E2E_LIVE=1 npm run siga:e2e-playwright-liveResolução de problemas
| Sintoma | Verificar |
|---|---|
401 / API key inválida | webhookApiKey em Integrações; não confundir com merchantId |
| Referência não encontrada | Plano em pending_gateway; referência igual à da fatura |
| Montante rejeitado | amount em kwanzas inteiros, igual ao plano |
| Unitel não liquida | URL /unitel/confirm, não /gateway/confirm |
| Entidade errada no terminal | Campo Merchant EMIS na integração Multicaixa |
Observabilidade
| Onde | O quê |
|---|---|
| SIGA → Integrações | Últimos 5 webhooks por canal |
| ADMIN → Webhooks gateway | Métricas 24h/7d cross-tenant |
| CLI | npm run siga:gateway-events-recent |
| Alertas | SIGA_GATEWAY_ALERT_SLACK_URL, SIGA_GATEWAY_FAILURE_RATE_* |
Detalhes: Runbook observabilidade.
Rotação de API key
Se a webhookApiKey foi exposta ou o contrato com o banco mudou:
- Definições → Integrações → secção webhook → Rotacionar key
- Copiar a nova key para o portal EMIS/Unitel
- Durante 24 h a key anterior continua válida (período de graça)
- Confirmar webhook de teste → HTTP
200
Ver Checklist produção § Segurança.