- v1.1 · atual
- v1 · anterior
Você está lendo o contrato atual (v1.1) de
order.opened. v1.1 adiciona data.fiscalRepresentation: a numeração fiscal que o ponto de venda obteve antes de injetar o pedido. Viaja sempre: em null quando não se tentou numerar, e preenchido quando sim — numberingStatus diz como terminou. Trazer conteúdo não significa que o comprovante esteja autorizado. Apenas aditivo — nada do que você já lia mudou.O bloco carrega o documento fiscal vigente do pedido: os campos que significam o mesmo em qualquer país no topo, os identificadores do órgão dentro de countryData no vocabulário do seu país, e os documentos anteriores em history. Quando um cancelamento numera, a nota de crédito passa ao topo e a de venda desce para o histórico — com compensates apontando para ela.order.opened dispara quando um pedido é injetado já aberto: ele existe no Fire, a cozinha pode começar, mas nenhum pagamento foi confirmado. Carrega o mesmo snapshot V4 que order.completed, então tudo o que você faz com um pedido completado também pode fazer aqui.
Este é o evento que torna o pagamento diferido possível. Sem ele, um pedido não pago seria invisível para suas integrações até o dinheiro chegar.
Condição de disparo
O Fire emiteorder.opened uma vez, na injeção, quando:
order.status === "OPEN"
order.completed, não há guarda de pagamento — paymentStatus normalmente vem como "PENDING" e isso é o esperado.
A vida do pedido depois deste evento
order.opened é o primeiro de até três eventos do mesmo pedido. Conhecer a sequência importa, porque esse pedido vai chegar ao seu endpoint mais de uma vez:
order.cancelled em vez de order.completed.
Se o seu fluxo emite um documento fiscal em
order.opened, o mesmo pedido vai passar de novo pelo seu nó fiscal em order.completed. Essa segunda passagem é esperada e inofensiva: o Fire detecta o documento existente e devolve um resultado idempotente de “já faturado” em vez de emitir outro. Veja Política de pagamento diferido abaixo.O que vem em trigger.data
trigger.data é o snapshot V4 — exatamente a mesma estrutura que order.completed carrega, com duas diferenças que você deve esperar:
Essa última linha é a que surpreende os integradores. Leia com atenção.
O meio declarado não é o meio cobrado
Emorder.opened ninguém pagou, então payments.paymentMethods[] carrega o meio que o PDV anunciou ao criar o pedido — frequentemente o marketplace (IFOOD, RAPPI) ou um placeholder. transactionStatus vem como "PENDING" e transactionId geralmente vazio.
Quando a cobrança entra, o Fire sobrescreve esse array com os tenders reais e emite order.completed. Mesmo pedido, mesmo campo, significado diferente:
order.opened — declarado
order.completed — realmente cobrado
Política de pagamento diferido
data.policy.deferredPayment é a razão de existir deste evento. Ele diz se o pedido pode ser trabalhado antes do pagamento: cozinhado, faturado, despachado.
A política é resolvida uma única vez, na injeção, a partir da combinação canal × serviço × meio de pagamento declarado. Depois é carimbada de forma imutável no pedido, e todos os eventos seguintes a repetem sem recalcular. Dois eventos do mesmo pedido sempre carregam uma policy idêntica.
Por que imutável? Porque a decisão precisa ficar auditável. Se a configuração da loja mudar uma hora depois, um pedido já em voo deve continuar se comportando como foi instruído — e você precisa poder provar por quê. Mesmo padrão de
store.storeFiscalConfig.
policy está presente em todos os eventos de pedido (order.opened, order.completed, order.invoiced, order.cancelled), não só neste. Um pedido com eligible: false também carrega o bloco — ele apenas diz que a resposta foi não.Último estado conhecido
data.lastKnown é uma foto orientativa do que o Fire sabia sobre o estado de cozinha e fiscal do pedido no momento da emissão do evento.
Valores possíveis de
fiscal.status: pending, processing, authorized, contingency, cancelling, cancelled, rejected, denied, error. O Fire ainda mantém dois estados internos para pedidos sem documento — esses são reportados aqui como null, para não vazar contabilidade interna dentro do seu contrato.
Todo o resto
Os blocos restantes —store, client, channel, orderLines, fulfillment, kds, device, operator, marketing, metadata, payments.totals — são idênticos a order.completed. Em vez de duplicá-los, veja a referência de campos de order.completed.
Erros comuns
Tratar order.opened como uma venda
Tratar order.opened como uma venda
Não é. Ninguém pagou. Contar
order.opened em relatórios de faturamento infla os números e duplica quando order.completed chegar para o mesmo orderId.Esperar order.opened para todo pedido
Esperar order.opened para todo pedido
Pedidos pré-pagos (quiosque, checkout web) são injetados já
COMPLETED e nunca o emitem. Se sua integração depende de order.opened chegar primeiro, ela vai pular esses pedidos em silêncio. Assine os dois.Ler o meio de pagamento como definitivo
Ler o meio de pagamento como definitivo
Veja acima. Em
order.opened é o que o PDV declarou, não o que foi cobrado.Processar o mesmo pedido duas vezes
Processar o mesmo pedido duas vezes
O mesmo
orderId chega em order.opened e de novo em order.completed. É por design. Faça seu handler idempotente por (orderId, ação), não por orderId.Próximo
order.completed— o mesmo pedido, quando o dinheiro entraorder.cancelled— se ele morre antes do pagamento- Confirmar pagamento — o endpoint que quita um pedido aberto
- Get order — leia
settlementpara ver quanto foi realmente arrecadado
data.fiscalRepresentation
A numeração fiscal que o ponto de venda obteve antes de injetar o pedido:
cobra, pede os identificadores, imprime o comprovante e só então injeta. Por isso
viaja no pedido e não em um evento fiscal separado — quando o pedido nasce, isso
já aconteceu.
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.
Trazer o bloco significa que se tentou numerar, não que foi numerado:
numberingStatus diz como a tentativa terminou, e failure por quê quando não
terminou bem.
Ramifique pelo valor, não pela presença da chave:
lastKnown.fiscal,
que é o que de fato se move.
O que o substitui é um documento novo. O bloco carrega o documento fiscal
vigente do pedido. Enquanto houve apenas um, era sempre a nota de venda;
quando um cancelamento produz uma nota de crédito, é ela que fica no topo —
documentType diz qual é — e a nota de venda desce para history, inteira e
com seus próprios identificadores do órgão. Não se perde: se move. compensates
aponta para ela pelo número, então a relação fica explícita.
Quando a numeração falha
Uma venda pode ser cobrada e ficar sem comprovante fiscal. Esse caso também viaja, e precisa ser tratado: os identificadores vêmnull e o motivo em
failure.
failure.scope:
TECHNICAL— imprima “em trâmite” e siga. Pode se resolver sozinho.FUNCTIONAL— há um dado errado e repetir não resolve. Precisa correção. O que muda élastKnown.fiscal.
lastKnown.fiscal.sourceEvent agora informa a procedência real. Antes era
deduzida do status, e um processing semeado na injeção era reportado como
fiscal.callback sem que nenhum callback tivesse ocorrido. Esse caso agora diz
order.injected. Se você ramifica por este campo, contemple o valor novo.
