FinOpenPOS
Fiscal Module

SEFAZ Communication

Communication with Brazil's SEFAZ tax authority uses SOAP 1.2 over HTTPS with mutual TLS, with each state having its own SEFAZ or delegating to SVRS, supporting authorization, cancellation, events, and more.

Overview

SEFAZ (Secretaria da Fazenda) is Brazil's tax authority web service. Communication uses SOAP 1.2 over HTTPS with mutual TLS (client certificate). Each state has its own SEFAZ or delegates to SVRS (Sefaz Virtual do Rio Grande do Sul).

Files: sefaz-transport.ts, sefaz-request-builders.ts, sefaz-response-parsers.ts, sefaz-urls.ts, sefaz-event-types.ts, sefaz-reform-events.ts, sefaz-client.ts (barrel)

Architecture

invoice-service


sefaz-client.ts (barrel re-export)
    ├── sefaz-request-builders.ts  → builds XML request body
    ├── sefaz-transport.ts         → SOAP envelope + curl mTLS
    ├── sefaz-response-parsers.ts  → parses XML response
    └── sefaz-urls.ts              → resolves endpoint URLs

Transport (sefaz-transport.ts)

Why curl?

Bun's node:https Agent does not support PFX for mTLS (ECONNREFUSED). The workaround: extract PEM cert/key from PFX using certificate.ts, write to temp files, and call curl.

sefazRequest()

async function sefazRequest(options: {
  url: string;
  service: SefazService;
  xmlContent: string;
  pfx: Buffer;
  passphrase: string;
  timeout?: number;  // default 30s
}): Promise<{ httpStatus: number; body: string; content: string }>

Flow:

  1. Build SOAP 1.2 envelope wrapping the XML content
  2. Extract PEM cert/key from PFX via extractCertFromPfx() / extractKeyFromPfx()
  3. Write cert, key, and SOAP body to temp files
  4. curl -s -k --cert ... --key ... -H "Content-Type: application/soap+xml" -d @body url
  5. Parse HTTP status from curl -w output
  6. Extract SOAP body content via regex
  7. Clean up temp files in finally block

SOAP envelope structure

<?xml version="1.0" encoding="UTF-8"?>
<soap12:Envelope xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Header/>
  <soap12:Body>
    <nfeDadosMsg xmlns="http://www.portalfiscal.inf.br/wsdl/.../{service}">
      {xmlContent}
    </nfeDadosMsg>
  </soap12:Body>
</soap12:Envelope>

URLs (sefaz-urls.ts)

State authorizer mapping

Each Brazilian state either has its own SEFAZ or delegates to SVRS:

Own authorizerStates
AMAmazonas
BABahia
GOGoias
MGMinas Gerais
MSMato Grosso do Sul
MTMato Grosso
PEPernambuco
PRParana
RSRio Grande do Sul
SPSao Paulo
SVRSAll other 17 states

Services

Each authorizer exposes 6 web services:

ServicePurpose
NfeStatusServicoCheck if SEFAZ is online
NfeAutorizacaoSubmit NF-e for authorization
NfeRetAutorizacaoRetrieve async authorization result
NfeConsultaProtocoloQuery invoice by access key
NfeInutilizacaoVoid unused number ranges
RecepcaoEventoSend events (cancellation, CCe, etc.)

getSefazUrl()

getSefazUrl(stateCode: string, service: SefazService, environment: SefazEnvironment): string

Resolves the correct URL considering state, service, and environment (production vs homologation).

Request Builders (sefaz-request-builders.ts)

Status check

buildStatusRequestXml(stateCode, environment)
// → <consStatServ xmlns="..." versao="4.00"><tpAmb>2</tpAmb><cUF>35</cUF><xServ>STATUS</xServ></consStatServ>

Authorization

buildAuthorizationRequestXml(signedNfeXml, environment, stateCode)
// → <enviNFe xmlns="..." versao="4.00"><idLote>...</idLote><indSinc>1</indSinc>{nfe}</enviNFe>

Cancellation

buildCancellationXml(accessKey, protocolNumber, reason, taxId, environment)
// Delegates to buildEventXml() with EVENT_TYPES.CANCELLATION

Generic event builder

buildEventXml(options: {
  accessKey, eventType, sequenceNumber, taxId, orgCode,
  environment, eventDateTime, additionalTags?, lotId?
})
// → <envEvento>...<evento>...<infEvento>...<detEvento>...</detEvento></infEvento></evento></envEvento>

Higher-level builders delegate to buildEventXml: CCe, Interested Actor, Extension Request, Delivery Proof, etc.

Batch builders

  • buildBatchManifestationXml() — multiple manifestation events in one envelope
  • buildBatchEventXml() — generic batch events

Shared primitives (sefaz-event-types.ts)

buildEventId(eventType, accessKey, seqNum)  //"ID110111{chNFe}01"
defaultLotId(lotId?)                         // → lotId ?? Date.now().toString()
getEventDescription(eventType)               //"Cancelamento", "EPEC", etc.

Response Parsers (sefaz-response-parsers.ts)

parseStatusResponse(xml)         // → { statusCode, statusMessage, averageTime }
parseAuthorizationResponse(xml)  // → { statusCode, protocolNumber, accessKey, ... }
parseCancellationResponse(xml)   // → { statusCode, protocolNumber, ... }

Uses fast-xml-parser and findNested() to locate response elements regardless of nesting depth.

Event Types (sefaz-event-types.ts)

Standard NF-e event codes:

CodeConstantDescription
110110CCECarta de Correcao
110111CANCELLATIONCancelamento
110112CANCELLATION_BY_SUBSTITUTIONCancelamento por substituicao
110140EPECEvento Previo de Emissao em Contingencia
110150INTERESTED_ACTORAtor interessado na NF-e
210200CONFIRMATIONConfirmacao da Operacao
210210AWARENESSCiencia da Operacao
210220UNKNOWN_OPERATIONDesconhecimento da Operacao
210240OPERATION_NOT_PERFORMEDOperacao nao Realizada

Reform Events (sefaz-reform-events.ts)

IBS/CBS tax reform events (PL_010). These are distinct from standard NF-e events.

Template pattern (DRY)

All 14 reform events follow the same structure:

function buildXxx(config, chNFe, nSeqEvento, ...params, verAplic?) {
  const va = resolveVerAplic(verAplic, config.verAplic);
  let tagAdic = reformEventHeader(config, va, tpAutor);  // <cOrgaoAutor>+<tpAutor>+<verAplic>
  // ... event-specific content added to tagAdic ...
  return wrapReformEvent(config, tpEvento, chNFe, nSeqEvento, tagAdic, va);
}

Event types

tpEventoFunctionDescription
110001buildCancelaEventoCancel a previous event
112110buildInfoPagtoIntegralFull payment information
112120buildImportacaoZFMALC/ZFM import not converted
112130buildRouboPerdaTransporteFornecedorLoss/theft by supplier (CIF)
112140buildFornecimentoNaoRealizadoSupply not fulfilled
112150buildAtualizacaoDataEntregaDelivery date update
211110buildSolApropCredPresumidoPresumed credit appropriation
211120buildDestinoConsumoPessoalPersonal consumption
211124buildRouboPerdaTransporteAdquirenteLoss/theft by buyer (FOB)
211128buildAceiteDebitoDebit acceptance
211130buildImobilizacaoItemItem immobilization
211140buildApropriacaoCreditoCombFuel credit appropriation
211150buildApropriacaoCreditoBensGoods/services credit
212110buildManifestacaoTransfCredIBSIBS credit transfer manifestation
212120buildManifestacaoTransfCredCBSCBS credit transfer manifestation

On this page