Webhook não é fonte de verdade: o que aprendi integrando nota fiscal eletrônica
O problema: a resposta não vem na hora
No Oficina Simples, a oficina emite nota de peça (NF-e) e de serviço (NFS-e) a partir da ordem de serviço. A emissão passa por um intermediário, que conversa com a SEFAZ e com as prefeituras.
Quase tudo ali é assíncrono. Você envia a nota e recebe de volta um "processando". A autorização, ou a rejeição, chega minutos depois por um webhook.
A tentação é óbvia: receber o webhook, ler o status que veio no corpo e gravar no banco. Funciona no primeiro teste. E é exatamente o tipo de código que eu não queria em produção.
Regra 1: o webhook é um aviso, não a resposta
O endpoint que recebe o aviso faz quatro coisas, nesta ordem:
- Confere um segredo por empresa no cabeçalho, com comparação em tempo constante.
- Procura a nota pela referência, dentro da empresa da URL.
- Se a referência não existe, registra no log e responde 200. Pode ser uma nota emitida fora do sistema ou de outro ambiente, e não adianta fazer o remetente tentar de novo.
- Se existe, consulta a nota na origem e só então atualiza o status.
O corpo do webhook não é usado para nada além da referência. A consequência é que um POST forjado não autoriza nota nenhuma: no máximo, provoca uma consulta. O segredo no cabeçalho não é a defesa principal, ele só evita consultas à toa.
Esse padrão vale para qualquer integração: pagamento, frete, assinatura eletrônica. Use o webhook para saber que algo mudou. Pergunte à origem o que mudou.
Regra 2: aviso se perde, então alguém precisa conferir
Webhook falha. O servidor estava em deploy, a rede oscilou, o remetente desistiu depois de algumas tentativas. Se o sistema depende só do aviso, a nota fica para sempre em "Processando".
Por isso existe uma varredura que roda a cada minuto e consulta as notas pendentes, com intervalo crescente:
- Nos primeiros 30 minutos: consulta a cada 1 minuto.
- Até 6 horas: a cada 15 minutos.
- Depois disso: de hora em hora, por até 3 dias.
Cada nota guarda quando foi consultada pela última vez, a varredura pega no máximo 100 por rodada e uma falha em uma nota não derruba as outras. Na tela, a lista se atualiza sozinha a cada 10 segundos enquanto houver nota processando.
O webhook deixa a experiência rápida. A varredura deixa o sistema correto.
Regra 3: valide antes de chamar quem vai recusar
Uma rejeição da SEFAZ vem com um código e uma mensagem que nenhum dono de oficina precisa aprender a ler.
Antes de qualquer emissão, o sistema confere tudo o que seria recusado: CNPJ e regime tributário da oficina, certificado vencido, NCM das peças, documento e endereço do cliente. A resposta volta como uma lista em português que aponta onde corrigir, como "Informe o CNPJ da oficina em Dados da Empresa".
É mais código do que simplesmente repassar o erro. Mas é a diferença entre um suporte por dia e nenhum.
Regra 4: guarde o mínimo possível
O certificado digital A1 é a credencial mais sensível da operação. No modo revenda, o arquivo não é guardado: ele vai direto para o intermediário e o temporário é apagado em seguida. O sistema guarda só os tokens, cifrados, e a data de validade, que alimenta lembretes com 30, 15, 7 e 1 dia de antecedência.
Não dá para vazar o que você não armazenou.
Regra 5: o que não está coberto deve ser bloqueado, não adivinhado
Imposto tem casos de borda demais. Um deles, a venda para consumidor final de outro estado no Lucro Presumido ou Real, eu decidi não cobrir nesta versão.
A saída fácil seria emitir com uma regra aproximada. A saída que escolhi: bloquear com um aviso claro para emitir pelo contador. Uma nota errada custa muito mais do que uma nota que não foi emitida pelo sistema.
Regra 6: ser honesto sobre o que foi testado
A integração foi escrita a partir da documentação oficial e testada com uma API simulada. Isso não é o mesmo que emitir de verdade.
Por isso a documentação tem um checklist de homologação explícito, com o que só se confirma com CNPJ e certificado reais: formato da alíquota de ISS da cidade, retorno da carta de correção, campos da reforma tributária. E a emissão começa desligada para todo mundo, liberada por uma chave no painel administrativo, sem deploy.
Integração fiscal não é o lugar para "funcionou na minha máquina". É o lugar para desconfiar de todo retorno até ver a origem confirmar.
Posts relacionados
Esconder o menu não é controlar acesso: como fiz módulos que cada cliente liga e desliga
Oficina pequena não quer ver comissão, nota fiscal e portal do cliente no primeiro dia. De...
Meu segundo SaaS começou com o código do primeiro: o que deu para reaproveitar e o que precisei reescrever
O Oficina Simples nasceu de um fork do Estoque Simples. Login, planos, cobrança, LGPD e mu...
Você não ficou 4x mais rápido. Ficou 10x mais inseguro — e agora existem os dados
Quase metade do código gerado por IA nasce com uma falha do OWASP Top 10. Os commits saem...