Skip to main content
O Fire não emite comprovantes: ele os numera. Essa distinção explica quase todas as decisões de desenho, então vale começar por aí.

Quem faz o quê

Seu canal

Cobra, pede a numeração, imprime e injeta o pedido. Não conhece regras fiscais de nenhum país.

Fire

Resolve a loja, o emissor e o provedor. Grava a solicitação, pede os números e responde o que pode ser impresso.

O provedor fiscal

Traduz para os códigos do órgão, numera com o vocabulário do seu país, e envia o documento à autoridade.

O órgão tributário

Autoriza ou rejeita. O veredito chega depois de o cliente já ter ido embora com o comprovante.
Um único contrato, todos os países. O Fire resolve internamente qual provedor corresponde a cada país. Sua integração é a mesma no Equador, no Brasil ou na Venezuela: o que muda é quais campos vêm preenchidos na resposta, não a forma de pedir.

A linha do tempo

Os passos 1 a 5 acontecem com o cliente esperando no caixa: são segundos. Do 6 em diante o seu canal já não participa.

Onde aparecem os dados fiscais

A numeração não fica trancada neste endpoint. Ela percorre o ciclo de vida do pedido em dois momentos distintos, e convém não misturá-los.

1. O que compensamos na injeção

Quando você injeta o pedido, o Fire o enriquece com a numeração que já obteve. Esses dados viajam nos eventos do ciclo de vida normal: Aqui ainda não há veredito do órgão: há números impressos e uma venda registrada.

2. O que o callback fiscal compensa

Minutos depois, o provedor avisa ao Fire o que a autoridade resolveu. Esse callback é o que dispara os dois eventos do desfecho:
Essa é a separação que precisa ficar clara de ponta a ponta: a numeração você pede e ela compensa o pedido; a autorização chega sozinha e compensa o desfecho. Um documento numerado pode nunca chegar a order.invoiced se o órgão o rejeitar.
Se você já consome eventos de pedido, não precisa consultar nada: os dados fiscais chegam pelo mesmo caminho que o resto da venda. A consulta direta fica para suporte e para quando você perde a resposta síncrona.

O campo que precisa ser lido: data.fiscalRepresentation

A numeração chega nesse bloco, em todos os eventos do pedido — os cinco das duas tabelas acima. A chave viaja sempre. Chega em null quando não se tentou numerar — agregadores, países sem representação fiscal, ou comércios com a numeração desativada — e traz o bloco quando houve tentativa. Ramifique pelo valor, nunca pela presença da chave:
Trazer o bloco significa que se tentou numerar, não que foi numerado. Uma venda cobrada que ficou sem comprovante fiscal chega com os identificadores em null e o motivo em failure — esse caso precisa ser tratado, porque antes era invisível. E trazer o bloco também não significa que o comprovante esteja autorizado: isso quem diz é lastKnown.fiscal.status, o único dos dois que é atualizado.

O que o bloco traz

Três camadas, e convém não misturá-las:
O número que vai impresso é documentNumber. Não o componha você mesmo.Ele chega já montado pelo provedor, que é quem conhece a regra do seu país — no Equador, o art. 18 do Reglamento de Comprobantes de Venta: quinze dígitos em três trechos. No bloco do país viaja o mesmo valor com o nome que o órgão usa (numeroComprobante no Equador).Montá-lo à mão juntando establecimiento, puntoEmision e secuencial parece equivalente e não é: o Reglamento permite omitir os zeros à esquerda do sequencial, então 001-020-123 pode ser tão legal quanto 001-020-000000123. Se você o compõe, imprime um número na sua convenção, não na do comprovante que foi emitido.
Os três campos do provedor não são a mesma coisa, e por isso viajam separados:
  • providerCode é nosso identificador de adaptador (hio). Diz com qual integração se numerou.
  • providerIdentity é do provedor e tem forma: name, version e reference. Essa reference é a que você cita a ele quando um caso precisa ser escalado — não é a sua Idempotency-Key.
  • providerMetadata é uma bolsa opaca: sem forma garantida, as chaves são do provedor e podem mudar sem aviso. Serve para colar num ticket de suporte.
Não ramifique pelas chaves de providerMetadata. Programar contra elas amarra a sua integração ao provedor que numera hoje, e elas mudam sem versionar o contrato. Se um dado é importante o bastante para decidir com ele, estará na camada canônica ou em countryData.
Além disso, o bloco leva o documento vigente do pedido, não o primeiro: se houve um cancelamento, a nota de crédito está no topo, compensates aponta para a nota de venda que ela cancela, e a nota de venda inteira fica em history. Cada entrada de history tem exatamente as mesmas chaves que o bloco acima, então se leem igual. A referência completa do bloco, campo a campo, está em order.opened.

As três regras que é preciso entender

A resposta traz dois estados, e eles nunca se fundem:
  • requestStatus — consegui números para imprimir?
  • documentStatus — o órgão autorizou?
Na numeração, o segundo é sempre PENDING. Isso não é um problema: na maioria dos países o comprovante é entregue antes de a autoridade vê-lo. Se a sua integração juntar os dois num campo só, em algum momento você vai dizer a um cliente que a nota está autorizada quando ela só tem número.
A Fire nunca devolve um erro que te deixa sem saber o que fazer. Falhe o que falhar, a resposta traz uma decisão explícita em policy.numberingFailure.action.O que mudou: essa decisão nem sempre é seguir. A conta configura, por vendor, o que acontece quando não deu para numerar.
  • CONTINUE — o padrão, e o comportamento de sempre. Imprima conforme printing.mode —normalmente um ticket não fiscal— e injete o pedido do mesmo jeito. O comprovante se resolve depois.
  • REFUND — devolva a cobrança no balcão e não injete o pedido. Essa venda não aconteceu; tem que ser reportada ou não fica rastro de que houve dinheiro envolvido.
Nos dois casos: não retenha a venda nem retente em loop com o cliente na frente. O dinheiro já foi cobrado.
Com CONTINUE, nada completa sozinho. Para conseguir o comprovante é preciso chamar de novo com o mesmo orderCode — a Fire retoma a solicitação e pergunta de novo ao provedor. Um 202 que ninguém retenta fica assim para sempre.Com REFUND é o contrário: não retente. Numerar uma venda que você devolveu geraria um comprovante de algo que não aconteceu.
O bloco printing não é uma dedução de haver ou não documento: é uma regra legal do país. No Equador, em contingência, o comprovante existe e é impresso mesmo sem o órgão tê-lo visto; num país que proíba imprimir antes da autorização, printable viria false com o documento presente.Se cada canal deduzisse essa regra por conta própria, algum a implementaria errado — e esse erro só aparece numa auditoria.

Idempotência: três camadas

Uma venda cobrada duas vezes é um problema de dinheiro; uma venda numerada duas vezes é um problema fiscal, e não se corrige com um deploy. Por isso há três barreiras:
1

Sua Idempotency-Key

Você a gera, uma por venda, e a reutiliza em cada nova tentativa daquela mesma venta. É o que impede que uma queda de rede consuma um segundo sequencial.Se reutilizá-la com um corpo diferente, o Fire responde 409: são duas operações distintas.
2

A chave natural

país + orderCode + operação. Protege mesmo que o seu canal gere uma Idempotency-Key nova a cada tentativa — o erro de implementação mais comum.É também a razão pela qual o orderCode precisa ser único por conta e país: se duas lojas usarem o mesmo, o Fire corta antes de emitir.
3

A do provedor

A mesma trinca, do outro lado. As duas chaves serem idênticas é o que faz uma colisão aparecer nas duas pontas ao mesmo tempo, em vez de surgir meses depois como dois comprovantes para uma venda.

Cancelar

Pede-se com operation: "CANCEL" e o mesmo orderCode da venda original. Nada mais. Seu ponto de venda não precisa guardar nenhum identificador nosso: o Fire encontra o documento original pela chave natural. Isso é deliberado — um quiosque reinstalado ou um caixa substituído perderiam esse dado, e a venda nunca mais poderia ser cancelada. Já o orderCode está impresso no ticket. Com qual instrumento o cancelamento se materializa é decisão do país: no Equador é uma nota de crédito com sequencial próprio; no Brasil, um evento de cancelamento que não gera documento novo. E a partir daí o pedido leva a nota de crédito no topo. Os eventos seguintes trazem documentType: "CREDIT_NOTE" em fiscalRepresentation, com compensates apontando para a nota de venda cancelada e a nota de venda inteira em history.
Se a sua conciliação assume que documentNumber é sempre o da venda, ela quebra aqui. O número do topo passa a ser o da nota de crédito. O que o cliente levou impresso não se perde —está em history— mas é preciso ir buscá-lo lá.

Se você perder a resposta

Acontece: a rede cai logo depois de o Fire numerar. O comprovante existe e você não o tem.
Devolve items[] com todos os documentos daquele pedido — podem ser dois, a nota e o cancelamento. É por isso que o orderCode precisa ser a mesma string na numeração e na injeção: é a única coisa que sobra na sua mão.

Antes de ir para produção

Seu orderCode é único por conta e país, e é o mesmo na numeração e na injeção.
Você guarda a Idempotency-Key junto com o pedido e a reutiliza nas tentativas.
Cada dispositivo declara seu device.externalId — dois caixas da mesma loja não o compartilham.
Você ramifica por printing.mode, e não pelo código HTTP.
Você imprime documentNumber tal como chega, sem recompô-lo a partir de establecimiento, puntoEmision e secuencial.
Você percorre countryData em vez de indexar chaves fixas: quem as define é o país que numerou, e na Venezuela não há claveAcceso.
Você percorre as chaves de graphic em vez de procurar campos fixos.
Você não ramifica pelas chaves de providerMetadata: é a bolsa opaca do provedor e muda sem aviso.
Sua conciliação contempla que, após um cancelamento, o documento do topo é a nota de crédito e a nota de venda está em history.
Diante de 202 você imprime provisório e injeta assim mesmo, sem repetir em loop.

Referência do endpoint

Campos, respostas e exemplos por país.