Skip to content

Improve webhook validation and reorder request method checks#192

Open
souzadavi wants to merge 7 commits into
nfe:mainfrom
LinkNacional:main
Open

Improve webhook validation and reorder request method checks#192
souzadavi wants to merge 7 commits into
nfe:mainfrom
LinkNacional:main

Conversation

@souzadavi
Copy link
Copy Markdown

@souzadavi souzadavi commented Mar 4, 2026

Correção de issue CNPJ, calback check e blindagem de código webhook.

Configuração para selecionar a emissao de nota fiscal por pais.

andrenfe added a commit that referenced this pull request May 12, 2026
…ation

Webhook v2 entrega notificações no formato:

    {"action": "issued_successfully", "payload": {<invoice fields>}}

O callback esperava os campos id/status/flowStatus/environment na raiz
(comportamento v1) e rejeitava todo payload v2 como "Payload inválido"
com HTTP 400.

Desembrulhamos o envelope quando presente, mantendo retrocompatibilidade
caso a NFE.io entregue o formato antigo. Confirmado via payload real
capturado em ambiente Development.

Estrutura também identificada em #192 (LinkNacional).
andrenfe added a commit that referenced this pull request May 12, 2026
… NFS-e filters (#196)

* fix: use webhook API v2 endpoint (api.nfse.io/v2/webhooks)

- Replace SDK-based webhook calls with direct cURL to api.nfse.io/v2/webhooks
  (the old endpoint api.nfe.io/v1/hooks was returning 404)
- Fix error handling in gnfe_issue_nfe to prevent webhook secret from being
  overwritten with empty value when webhook creation fails
- No company scope needed for webhook endpoints

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: increase webhook API timeout from 5s to 30s

api.nfse.io can take longer than 5 seconds to respond, causing
timeout errors on webhook get/create operations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: adapt to webhook API v2 response structure

The v2 API at api.nfse.io returns webhook data wrapped in "webHook"
(camelCase) with "uri" instead of "url":
  {"webHook": {"id": "...", "uri": "...", "secret": "...", "status": "Active"}}

Updated Controller.php and Functions.php to extract webhook data from
the correct property path, with fallback for v1 format.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use webhook API v2 request schema in createWebhook

A v2 (api.nfse.io/v2/webhooks) requer payload envelopado em `webHook` com
`uri`, `contentType` no enum ("json"|"form-urlencoded") e `filters` opcional
no padrão `Resource.EventAction`. O código estava enviando o schema v1 plano
(`url`, `contentType: application/json`, `events`) e a criação falhava em
runtime mesmo com o endpoint correto.

Sem `filters` o webhook recebe todos os eventos da conta; o callback já
valida o payload de NFS-e e descarta o que não bate.

* fix: restrict webhook v2 filters to NFS-e lifecycle events

Webhook v2 entrega todos os eventos da conta por padrão. Sem filters, o
callback recebia eventos de outras entidades (product_invoice.*,
consumer_invoice.*, etc.) e logava "Payload inválido" para cada um,
gerando ruído.

Filters aplicados cobrem o ciclo de emissão e cancelamento de NFS-e —
substituem o trio v1 (issue/cancel/WaitingCalculateTaxes), sendo que
WaitingCalculateTaxes deixou de existir em v2 e foi absorvido pelos
estados intermediários do issued.*.

Event types confirmados via GET /v2/webhooks/eventTypes.

* fix(webhook): compare HMAC signature as hex instead of decoding as base64

A NFE.io envia X-Hub-Signature como HMAC em hexadecimal (formato
"sha1=<hex>"), conforme documentado em
nfe.io/docs/documentacao/webhooks/duvidas-frequentes.

O código original computava `hex2bin(hash_hmac(...))` (bytes raw) e
aplicava `base64_decode()` na assinatura recebida — base64_decode em
string hex produz bytes matematicamente diferentes do esperado, então
hash_equals nunca casa e todo callback de webhook era rejeitado com 403
"Assinatura inválida".

Fix: comparar a assinatura recebida (hex) contra `hash_hmac` (hex) com
hash_equals normalizado em lowercase, alinhado com o padrão
X-Hub-Signature usado por GitHub e outros provedores.

Bug originalmente identificado e proposto por @ianchamba em #190.

Co-authored-by: Ian Chamba <86791147+ianchamba@users.noreply.github.com>

* fix(webhook): unwrap v2 envelope {action, payload} before field validation

Webhook v2 entrega notificações no formato:

    {"action": "issued_successfully", "payload": {<invoice fields>}}

O callback esperava os campos id/status/flowStatus/environment na raiz
(comportamento v1) e rejeitava todo payload v2 como "Payload inválido"
com HTTP 400.

Desembrulhamos o envelope quando presente, mantendo retrocompatibilidade
caso a NFE.io entregue o formato antigo. Confirmado via payload real
capturado em ambiente Development.

Estrutura também identificada em #192 (LinkNacional).

---------

Co-authored-by: Ian Chamba <86791147+ianchamba@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant