Skip to content

Como Funciona o Monitoramento SEFAZ

Este documento explica detalhadamente como o sistema Monitor SEFAZ verifica a saúde dos provedores SEFAZ em todos os estados brasileiros.

📋 Visão Geral

O Monitor SEFAZ utiliza o serviço oficial de StatusServico fornecido pela SEFAZ para verificar a disponibilidade e tempo de resposta dos serviços fiscais eletrônicos (NFe, NFCe, CTe, DCe).

🔄 Ciclo de Monitoramento

Frequência

O sistema executa ciclos de monitoramento a cada 30 segundos, processando todas as UFs e serviços configurados.

Fluxo do Ciclo

┌─────────────────────────────────────────┐
│   MonitorWorker (Background Service)     │
│   Ciclo a cada 30 segundos               │
└─────────────────┬───────────────────────┘
        ┌─────────▼─────────┐
        │  Warmup Certificado│
        │  (Inicialização)   │
        └─────────┬─────────┘
        ┌─────────▼─────────────────────────┐
        │  Filtrar UFs Habilitadas           │
        │  (NFe, NFCe, CTe, DCe)            │
        └─────────┬─────────────────────────┘
        ┌─────────▼─────────────────────────┐
        │  Separar DCe das Outras Consultas │
        └─────────┬─────────────────────────┘
      ┌───────────┴───────────┐
      │                       │
┌─────▼─────┐         ┌──────▼──────┐
│  Processar│         │  Processar  │
│  DCe      │         │  NFe/NFCe/  │
│  (Único)  │         │  CTe        │
│           │         │  (Paralelo) │
└───────────┘         └─────────────┘

🔍 Processo de Verificação de Saúde

1. Requisição SOAP ao StatusServico

Para cada UF e serviço, o sistema envia uma requisição SOAP (Web Service) ao endpoint oficial da SEFAZ.

Estrutura da Requisição SOAP

Endpoint: URL específica por UF e tipo de serviço (ex: https://nfe.sefaz.es.gov.br/ws/NFeStatusServico4/NFeStatusServico4.asmx)

Método: POST

Content-Type: - application/soap+xml; charset=utf-8 (SOAP 1.2 - Padrão) - text/xml; charset=utf-8 (SOAP 1.1 - Fallback)

Headers:

Content-Type: application/soap+xml; charset=utf-8; action="http://www.portalfiscal.inf.br/nfe/wsdl/NFeStatusServico4/nfeStatusServicoNF"
SOAPAction: "http://www.portalfiscal.inf.br/nfe/wsdl/NFeStatusServico4/nfeStatusServicoNF"

Envelope SOAP (Exemplo NFe):

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <nfeDadosMsg xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/NFeStatusServico4">
      <consStatServ versao="4.00" xmlns="http://www.portalfiscal.inf.br/nfe">
        <tpAmb>1</tpAmb>          <!-- 1=Produção, 2=Homologação -->
        <cUF>32</cUF>              <!-- Código da UF (32=ES) -->
        <xServ>STATUS</xServ>      <!-- Serviço: STATUS -->
      </consStatServ>
    </nfeDadosMsg>
  </soap12:Body>
</soap12:Envelope>

Parâmetros da Requisição

  • tpAmb: Ambiente (1=Produção, 2=Homologação)
  • cUF: Código numérico da UF (ex: 32=ES, 35=SP, 31=MG)
  • xServ: Sempre "STATUS" para consulta de status
  • versao: Versão do layout (4.00 para NFe, NFCe, CTe)

Certificado Digital

Todas as requisições utilizam certificado digital A1 ou A3 para autenticação SSL/TLS:

var certificado = await certificateService.GetCertificateAsync();
// Certificado é usado para autenticação SSL na requisição HTTPS

2. Resposta SOAP da SEFAZ

A SEFAZ responde com um envelope SOAP contendo o status do serviço:

Exemplo de Resposta (Serviço Operacional):

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Body>
    <nfeResultMsg xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/NFeStatusServico4">
      <retConsStatServ versao="4.00" xmlns="http://www.portalfiscal.inf.br/nfe">
        <tpAmb>1</tpAmb>
        <verAplic>SP_NFE_PL_009h</verAplic>
        <cStat>107</cStat>
        <xMotivo>Serviço em Operação</xMotivo>
        <cUF>35</cUF>
        <dhRecbto>2025-12-26T10:00:00-03:00</dhRecbto>
        <tMed>1000</tMed>
      </retConsStatServ>
    </nfeResultMsg>
  </soap:Body>
</soap:Envelope>

Campos Importantes da Resposta

Campo Descrição Exemplo
cStat Código de Status 107 = Serviço em Operação
xMotivo Motivo/Descrição Serviço em Operação
tMed Tempo Médio de Resposta (ms) 1000 = 1 segundo
dhRecbto Data/Hora de Recebimento 2025-12-26T10:00:00-03:00
verAplic Versão da Aplicação SP_NFE_PL_009h

3. Códigos de Status (cStat)

O campo cStat indica o status operacional do serviço:

Código Significado Status do Monitor
107 Serviço em Operação ✅ Operacional
108 Serviço Paralisado Momentaneamente ⚠️ Degradado
109 Serviço Paralisado sem Previsão ❌ Indisponível
110 Serviço Paralisado em Curto Prazo ❌ Indisponível
111 Serviço Paralisado em Médio Prazo ❌ Indisponível
112 Serviço Paralisado em Longo Prazo ❌ Indisponível
113 Serviço em Contingência ⚠️ Contingência
114 SVC Desabilitado ❌ Indisponível
999 Erro/Timeout/Exceção ❌ Indisponível

4. Medição de Latência

O sistema mede o tempo de resposta completo:

var stopwatch = Stopwatch.StartNew();
var resultado = await soapService.ConsultarStatusAsync(url, certificado, ambiente, codigoUf, ct);
stopwatch.Stop();
var latencyMs = stopwatch.ElapsedMilliseconds; // Tempo total em milissegundos

Classificação de Latência:

  • Normal: ≤ 2 segundos
  • Lento: 2 a 5 segundos
  • Muito Lento: 5 a 30 segundos
  • Timeout: ≥ 30 segundos ou sem resposta

5. Sistema de Contingência (SVC)

Quando o servidor principal retorna erro ou aviso de contingência, o sistema automaticamente tenta o Servidor de Contingência (SVC):

// Condições para tentar SVC:
bool deveTentarSvc = 
    (falhaConexao || avisoContingencia)  // cStat = "999" ou "113"
    && !IsSvcDisabled(resultado)          // SVC não está desabilitado (cStat != "114")
    && _options.TentarContingencia        // Configuração permite
    && helper.UsaServidorContingencia(uf); // UF suporta SVC

if (deveTentarSvc) {
    // Tenta servidor de contingência
    var resultadoSvc = await soapService.ConsultarStatusAsync(urlSvc, ...);
}

Fluxo de Contingência:

1. Consulta Servidor Principal
2. Verifica cStat:
   - "999" (erro/timeout) → Tenta SVC
   - "113" (contingência) → Tenta SVC
   - "107" (operacional) → Retorna resultado
3. Se necessário, consulta Servidor de Contingência (SVC)
4. Retorna melhor resultado disponível

🔧 Implementação Técnica

Arquitetura do Monitoramento

MonitorWorker (Background Service)
CheckStatusWithRetryAsync (para cada UF)
1. Verificar Cache (evita consultas desnecessárias)
2. Consultar Status SEFAZ
    ├── SefazStatusService.ConsultarStatusAsync()
    │   ├── Determina tipo de serviço (NFe, NFCe, CTe, DCe)
    │   ├── Obtém URL do endpoint
    │   └── Executa consulta com contingência
    │       ├── ExecutarConsultaComContingenciaAsync()
    │       │   ├── Consulta servidor principal
    │       │   └── Tenta SVC se necessário
    │       └── Retorna SefazStatusResult
3. Medir Latência (Stopwatch)
4. Mapear Resultado (SefazResultMapper)
5. Persistir no Redis (MonitorSefazUseCase)
    └── RedisStatusService.InsertResultAsync()

Código Principal

MonitorWorker.cs:

private async Task CheckStatusWithRetryAsync(UfConfig config, CancellationToken token)
{
    // 1. Verificar cache (evita chamadas desnecessárias)
    if (await redis.HasRecentUpdateAsync(config.UF, serviceName))
        return;

    // 2. Executar consulta à SEFAZ
    var stopwatch = Stopwatch.StartNew();
    var sefazResult = await sefazStatusService.ConsultarStatusAsync(
        config.UF,
        ServiceTypeMapper.ToSefazServiceType(config.ServiceType),
        token);
    stopwatch.Stop();

    // 3. Mapear e persistir resultado
    var result = SefazResultMapper.ToMonitorResult(
        sefazResult,
        config.UF,
        serviceName,
        stopwatch.ElapsedMilliseconds);

    await monitorUseCase.ExecuteAsync(result);
}

NfeStatusServicoSoapService.cs:

public async Task<SefazStatusResult> ConsultarStatusAsync(...)
{
    // 1. Criar envelope SOAP
    var envelope = CriarSoapEnvelope(ambiente, codigoUf, isSoap12);

    // 2. Enviar requisição HTTP POST
    using var request = new HttpRequestMessage(HttpMethod.Post, url);
    request.Content = new StringContent(envelope, Encoding.UTF8, "application/soap+xml");

    // 3. Executar requisição com certificado
    using var response = await httpClient.SendAsync(request, ct);
    var responseXml = await response.Content.ReadAsStringAsync(ct);

    // 4. Parsear resposta XML
    return ParsearRespostaSoap(responseXml);
}

⚡ Otimizações

1. Cache Inteligente

O sistema verifica se já existe uma atualização recente (30 segundos) antes de consultar a SEFAZ:

if (await redis.HasRecentUpdateAsync(config.UF, serviceName))
    return; // Pula consulta desnecessária

2. Paralelismo Controlado

Máximo de 5 consultas simultâneas para evitar sobrecarga:

await Parallel.ForEachAsync(otherConfigs, new ParallelOptions 
{ 
    MaxDegreeOfParallelism = 5,  // Limite de concorrência
    CancellationToken = stoppingToken 
}, async (config, token) =>
{
    await CheckStatusWithRetryAsync(config, token);
});

3. Otimização DCe

DCe usa o mesmo servidor (Paraná) para todos os estados, então fazemos apenas 1 consulta e replicamos o resultado:

// Consulta única para todos os estados
var sefazResult = await sefazStatusService.ConsultarStatusAsync(
    firstConfig.UF, // Qualquer UF serve
    ServiceType.DCe,
    token);

// Replica resultado para todos os estados
await Task.WhenAll(dceConfigs.Select(config => 
    monitorUseCase.ExecuteAsync(mappedResult)));

4. Fallback SOAP 1.1/1.2

Se a requisição SOAP 1.2 falhar, o sistema automaticamente tenta SOAP 1.1:

// Tenta SOAP 1.2 primeiro (padrão NF-e 4.0)
var resultado = await ExecutarRequestAsync(url, ambiente, codigoUf, httpClient, true, ct);

// Se falhar por incompatibilidade, tenta SOAP 1.1
if (resultado.CStat == "999" && resultado.XMotivo?.Contains("VersionMismatch"))
    resultado = await ExecutarRequestAsync(url, ambiente, codigoUf, httpClient, false, ct);

📊 Dados Coletados

Para cada verificação, o sistema armazena:

MonitorResult {
    UF: "SP",                    // Unidade Federativa
    Service: "NFeStatusServico", // Tipo de serviço
    Status: "Operacional",       // Status legível
    CStat: "107",                // Código de status SEFAZ
    XMotivo: "Serviço em Operação", // Motivo
    LatencyMs: 1234,             // Latência em milissegundos
    Success: true,               // Sucesso na consulta
    Timestamp: DateTime.UtcNow,  // Quando foi consultado
    ContingencyInfo: {...}       // Info de contingência (se aplicável)
}

🚨 Tratamento de Erros

Erros de Conexão

  • Timeout: Requisição excede 30 segundos → cStat = "999"
  • DNS: Endpoint não encontrado → cStat = "999"
  • SSL/TLS: Erro de certificado → cStat = "999"

Erros de Resposta

  • SOAP Fault: Resposta contém erro SOAP → cStat = "999"
  • XML Inválido: Resposta não é XML válido → cStat = "999"
  • Elemento Ausente: Campo obrigatório não encontrado → cStat = "999"

Erros de Certificado

  • Certificado Não Configurado: → cStat = "999", XMotivo = "Certificado digital não configurado"
  • Certificado Expirado: → Erro SSL/TLS → cStat = "999"

🔐 Segurança

Autenticação

  • Certificado Digital A1/A3: Autenticação SSL/TLS obrigatória
  • HTTPS: Todas as requisições são feitas via HTTPS
  • Validação de Certificado: Validação automática do certificado SSL da SEFAZ

Validação

  • Validação de UF: Verifica se a UF é válida antes de consultar
  • Validação de Resposta: Parse e validação do XML de resposta
  • Sanitização: Tratamento seguro de dados recebidos

📈 Métricas e Analytics

O sistema coleta métricas para análise:

  • Latência (P50, P95, P99): Percentis de tempo de resposta
  • Taxa de Sucesso: Percentual de consultas bem-sucedidas
  • Histórico: Dados das últimas 24 horas armazenados no Redis
  • Tendências: Análise de padrões de disponibilidade

🔄 Frequência de Atualização

  • Ciclo Base: A cada 30 segundos
  • Cache: 30 segundos (proteção contra consultas simultâneas)
  • Retenção: Histórico de 24 horas mantido no Redis
  • Latest TTL: Cache do status mais recente por 2 horas

Última Atualização: 26 de Dezembro de 2025

Documentação Relacionada: - Arquitetura.md - Tecnologico.md