NF-e e Split Payment: preparando um e-commerce para o novo cenário fiscal

Como planejar a emissão de Nota Fiscal Eletrônica em um e-commerce Astro + Cloudflare e preparar a arquitetura de pagamentos para o split payment da reforma tributária.

O problema em duas frentes

Um e-commerce brasileiro que vende produto físico precisa resolver duas questões fiscais que costumam ser tratadas tarde demais no ciclo de desenvolvimento:

  1. Hoje: emitir Nota Fiscal Eletrônica (NF-e) a cada venda, de forma automatizada e auditável.
  2. A partir de 2027: conviver com o split payment da reforma tributária, em que a própria liquidação financeira segrega CBS e IBS antes de o valor líquido chegar ao lojista.

Este artigo documenta o planejamento das duas frentes para uma stack Astro + Cloudflare + Supabase, com foco em decisões de arquitetura que não precisem ser refeitas quando as regras mudarem.

Parte 1 — Nota Fiscal Eletrônica

Qual documento emitir

A primeira decisão não é técnica, é fiscal. Para venda de produto físico pela internet, o documento é a NF-e modelo 55. O resumo:

OperaçãoDocumento
Venda de produto físico pelo siteNF-e modelo 55
Venda presencial ao consumidor em lojaNFC-e modelo 65
Prestação de serviço (desenvolvimento, consultoria)NFS-e
Venda com produto e serviço separáveisAvaliação caso a caso

Um detalhe que gera confusão: dados bancários não participam da emissão fiscal. A conta que recebe o Pix serve para conciliação do pagamento; a nota é emitida com os dados cadastrais e tributários da empresa.

Por que não integrar direto com a SEFAZ

A NF-e envolve assinatura digital de XML, validação contra schemas XSD, webservices fiscais, tratamento de rejeições, contingências e controle rigoroso de numeração. Implementar isso do zero em um Worker é reinventar uma roda cheia de arestas regulatórias.

A solução prática é uma API fiscal intermediária: o backend envia JSON, o provedor assina, transmite à SEFAZ e devolve o resultado por webhook.

Cliente


Loja (Astro)


Worker / API server-side
   ├── Banco de pedidos
   ├── Integração de pagamento
   └── API fiscal ──► SEFAZ

Escolhendo o provedor (sem casar com ele)

A avaliação de julho de 2026 mapeou quatro caminhos com perfis bem diferentes:

CenárioOpçãoCusto
Validação, pouca vendaEmissor gratuito do Sebrae (manual)R$ 0
Automação + ERPBling Cobalto (NF-e ilimitadas, API OAuth 2.0, estoque/pedidos)R$ 60/mês
API fiscal puraFocus NFe (Solo ~100 docs; Retail exige confirmar endpoints de NF-e)R$ 59,90–89,90/mês
Volume alto, controle totalNFePHP/SPED-NFe em servidor próprioR$ 0 + infra e manutenção

A Nuvem Fiscal foi descartada: anunciou desativação do serviço para 31 de julho de 2026 — um lembrete de que provedor fiscal também morre.

Exatamente por isso a integração precisa ser agnóstica ao provedor — o mesmo padrão de ports & adapters que se usa para PSPs de pagamento vale para o fiscal. Com uma porta única (FiscalProviderPort), a fase de validação roda com um adapter manual: o pagamento confirmado enfileira o pedido, o operador emite a nota no emissor gratuito do Sebrae e registra chave de acesso, número e XML no admin. Quando o volume justificar a mensalidade, entra um adapter automatizado (Bling ou Focus) — mesma tabela, mesmos estados, zero mudança no domínio. O caminho self-hosted (NFePHP exige PHP, criptografia e SOAP fora do alcance de um Worker) fica registrado como opção futura, não como ponto de partida: o custo nominal zero cobra caro em manutenção de schemas, contingência e responsabilidade fiscal.

Certificado digital

Emissão em nuvem exige certificado e-CNPJ A1 (arquivo). O A3 depende de token ou cartão físico e não serve para servidores. O certificado não vai para o repositório nem para o Worker: é cadastrado no cofre do próprio provedor fiscal.

O que o contador define antes de qualquer código

O maior risco do projeto não é a chamada HTTP — é o cadastro tributário. Cada produto precisa de:

CampoQuem define
NCMContador
CFOP (interno/interestadual)Contador
CST ou CSOSNContador (regime)
CEST (quando houver)Contador
Origem da mercadoriaContador
AlíquotasContador

Esses parâmetros afetam o cálculo do imposto e a autorização da nota. Não devem ser escolhidos pelo desenvolvedor por aproximação. O projeto só sai da fase de planejamento quando existir uma ficha tributária validada: razão social, IE habilitada, regime, CRT, série e numeração da NF-e, natureza da operação e o perfil de cada produto.

Fluxo de emissão

A nota não é emitida porque alguém abriu o checkout. O gatilho é a confirmação do pagamento (ou o momento fiscal definido pelo contador):

pedido_criado → aguardando_pagamento → pagamento_confirmado
      → emissao_fiscal_pendente → nfe_processando
            ├──► nfe_autorizada
            └──► nfe_rejeitada

A emissão é normalmente assíncrona: o backend envia a solicitação com uma referência única, o provedor processa e um webhook informa autorização ou rejeição. O sistema então armazena chave de acesso, XML e DANFE, envia o DANFE ao cliente e libera o pedido para produção/envio.

Estado fiscal não é um booleano

Um campo invoiceIssued = true não representa a realidade. O modelo precisa distinguir:

EstadoSignificado
not_requestedEmissão ainda não solicitada
pendingAguardando envio
processingEm análise (API ou SEFAZ)
authorizedNF-e autorizada
rejectedDados recusados
cancel_pendingCancelamento solicitado
cancelledNF-e cancelada
contingencyEmissão em contingência
manual_reviewPrecisa de intervenção humana

E o documento fiscal vive em tabela própria, separada do pedido:

create table fiscal_documents (
    id uuid primary key,
    order_id uuid not null references orders(id),
    provider text not null,
    provider_reference text not null unique,
    status text not null,
    access_key text,
    xml_url text,
    danfe_url text,
    rejection_code text,
    rejection_message text,
    request_payload jsonb,
    response_payload jsonb,
    created_at timestamptz not null default now()
);

O provider_reference, derivado do identificador interno do pedido, funciona como chave de idempotência: uma requisição repetida por falha de rede não pode gerar uma segunda nota para o mesmo pedido.

Segurança na borda

Regras não negociáveis para a integração em Cloudflare:

  • Token fiscal e segredo de webhook só existem como secrets do Worker — nunca em variável pública, HTML ou repositório.
  • O navegador nunca envia preço, NCM ou imposto para o endpoint de emissão. O payload fiscal é montado no servidor, a partir do pedido pago carregado do banco.
  • O webhook valida assinatura, identifica a nota pela referência, descarta eventos duplicados e só então atualiza o estado.
  • CPF/CNPJ do cliente vai apenas ao backend e não aparece em logs ou mensagens de erro.

Parte 2 — Split payment

O que muda

Hoje, o lojista recebe R$ 100,00 e recolhe os tributos depois. No split payment, a instituição financeira segrega os tributos durante a liquidação: uma parcela vai para a CBS, outra para o IBS, e só o líquido é creditado ao fornecedor. Não é um imposto novo — é um mecanismo de recolhimento automático embutido no pagamento.

Quem fala com a API do governo (spoiler: não é você)

A Plataforma Pública de Split Payment não é uma API para lojas ou SaaS. Ela é um hub entre PSPs e o fisco:

Cliente → Sua aplicação → Banco/PSP → Plataforma de Split Payment
                                          ├── Receita Federal (CBS)
                                          └── Comitê Gestor (IBS)

A documentação trata o cliente da API como PSP homologado, com mTLS, rate limiting, long polling e política de erros de infraestrutura financeira. Para o desenvolvedor de aplicação, a conclusão é direta:

Seu sistema não conversa com a API do CGIBS. Ele conversa com um PSP que ofereça Pix dinâmico, webhooks, dados de liquidação e, futuramente, a vinculação com o documento fiscal.

O elo que quase ninguém tem hoje

O split “superinteligente” — que usa a situação tributária real do documento fiscal em vez de um percentual fixo — depende de vincular documento fiscal ↔ transação financeira antes da liquidação. Isso conecta três objetos que a maioria dos sistemas trata separadamente:

pedido ↔ documento fiscal ↔ pagamento

Quem não fizer essa vinculação cai no procedimento alternativo: retenção estimada com devolução posterior do excesso. Ou seja: a Parte 1 deste artigo (NF-e bem modelada, ligada ao pedido e ao pagamento) é literalmente o pré-requisito da Parte 2.

Não há obrigação em 2026 — há dever de casa

A documentação técnica é explícita: a implantação efetiva está prevista a partir de 2027; os campos publicados em 2026 são preparatórios. Não se justifica reconstruir nada agora. O momento é de preparação arquitetural:

  1. Separar claramente pedido, documento fiscal e pagamento no modelo de dados.
  2. Usar Pix dinâmico como padrão em cobrança comercial (tem txId próprio e participa de todos os fluxos; o estático serve para pagamento informal).
  3. Guardar txId e e2eId de cada liquidação.
  4. Tratar webhooks com idempotência (chave única por evento, payload bruto armazenado, retries com backoff).
  5. Manter no modelo a distinção valor bruto ≠ tributos ≠ valor líquido e cobrança criada ≠ paga ≠ liquidada.
  6. Acessar todo PSP por uma porta abstrata com adapters:
export interface PaymentProviderPort {
  createPixCharge(input: CreateChargeInput): Promise<PaymentIntent>;
  getPaymentStatus(providerPaymentId: string): Promise<PaymentStatus>;
  verifyWebhook(headers: Record<string, string>, rawBody: Uint8Array): Promise<VerifiedPaymentEvent>;
  refundPayment(input: RefundInput): Promise<RefundResult>;
}

Quando o PSP publicar a implementação compatível com split payment, a mudança se resume a um novo adapter — o domínio, os pedidos e o frontend permanecem intactos.

Conclusão

O plano consolidado para as duas frentes:

Documento fiscal:  NF-e modelo 55, atrás de uma porta agnóstica de provedor
Fase 1 (validação): adapter manual — emissor gratuito do Sebrae + registro no banco
Fase 2 (automação): adapter Bling Cobalto (candidato) ou Focus NFe (alternativa)
Certificado:       e-CNPJ A1, no cofre do provedor
Gatilho:           pagamento confirmado
Retorno:           webhook idempotente → XML + DANFE + chave de acesso
Pagamentos:        Pix dinâmico, porta agnóstica de PSP, txId/e2eId persistidos
Split payment:     nada a implementar em 2026; arquitetura pronta para 2027

A parte difícil não é o código — é a disciplina de tratar NCM, CFOP, CSOSN e alíquotas como dados do contador, e de modelar pagamento e nota fiscal como entidades ligadas desde o primeiro dia.

Referências