Projeto - Rejeição 656 (Consumo Indevido)
Tratamento de auditoria das consultas SEFAZ para evitar bloqueio por consumo indevido
Dados do projeto
Analista responsável: Jonathan Torioni Data de criação das funções principais: 03/06/2026 a 09/06/2026
Contexto da rejeição 656
A SEFAZ retorna o código 656 - Rejeição: Consumo Indevido quando o emissor realiza consultas excessivas em curto intervalo de tempo a um mesmo recurso (consulta de chave NF-e, status de serviço, etc.). Como medida de proteção a sefaz temporariamente bloqueia o emissor, o que impacta diretamente:
- O monitor de XML / NF-e (
U_SCOMA040), onde o usuário consulta o status da SEFAZ pela chave. - O monitor de NF-e SEFAZ (
nfesefaznativo), que reaproveita o ponto de entradaU_FISMNTNFEpara auditar as consultas.
O projeto implementa um buffer/auditória cliente-side mantido na tabela LEGBRANCA em SQL direto, capaz de:
- Identificar se a chave/nota já foi consultada recentemente.
- Bloquear novas consultas em intervalo inferior a 10 segundos.
- Persistir o último retorno da SEFAZ (código + mensagem) para auditoria.
- Limpar diariamente os registros mais antigos.
Tabela LEGBRANCA
Tabela em SQL direto (não está no dicionário Protheus). Estrutura inferida pelo código:
| Coluna | Tipo | Descrição |
|---|---|---|
| IDENT | VARCHAR2 | ID_ENT da SPED001 (entidade TSS) |
| CHVNFE | VARCHAR2(44) | Chave de acesso da NF-e (consultas de entrada) |
| DOC | VARCHAR2(9) | Número do documento (consultas de saída) |
| SERIE | VARCHAR2(3) | Série do documento |
| CODRET | VARCHAR2 | Código de retorno SEFAZ |
| RETSEFAZ | VARCHAR2 | Mensagem do retorno SEFAZ |
| S_T_A_M_P_ | TIMESTAMP | Timestamp da inserção / última atualização |
Parâmetro de controle
- ES_AUDLEG - Parâmetro lógico (default
.F.). Quando.T.habilita toda a integração com aLEGBRANCA. Quando.F., o comportamento do monitor permanece igual ao original.
Componentes e onde são utilizados
Funções principais (definidas em sharkxfun.prw)
| Função | Linha (sharkxfun) | Tipo de operação | Tabela | Finalidade |
|---|---|---|---|---|
U_INS656 | L9063 | INSERT + COMMIT | LEGBRANCA | Persiste o registro da consulta + retorno SEFAZ |
U_CON656 | L9118 | SELECT | LEGBRANCA | Verifica se a chave/doc já está em auditoria |
U_STMPLEG | L9166 | SELECT (delta tempo) | LEGBRANCA | Retorna .T. se a última consulta foi há 10s ou mais (libera nova) |
U_STMPUPD | L9224 | UPDATE + COMMIT | LEGBRANCA | Atualiza timestamp e (opcionalmente) o retorno SEFAZ |
U_CLRLGBR | L9269 | DELETE + COMMIT | LEGBRANCA | Job de limpeza — apaga registros com S_T_A_M_P_ superior a 2 dias |
Onde são consumidas
Em scoma040.prw — função U_SCNewConsSe (linhas 9287–9395)
Contextualização: rotina de consulta SEFAZ pela chave NF-e, executada quando o usuário aciona "Consultar SEFAZ" no monitor U_SC030Sef.
Fluxo com auditoria habilitada (ES_AUDLEG = .T.):
+--------------------+
| U_SCNewConsSe |
| (cChave, cCNPJ) |
+---------+----------+
|
v
cIdEnt := U_SCGetIdEnt(cCNPJ)
|
v
ES_AUDLEG = .T. ?
|
+-------+-------+
| NAO | SIM
| v
| CON656 retorna registro?
| |
| +-------+-------+
| | NAO | SIM
| | v
| | STMPLEG (>= 10s)?
| | |
| | +-------+-------+
| | | SIM | NAO
| | v v
+-------+-------+ STMPUPD (so stamp)
| + RETORNA "Aguarde..."
v
Consulta WebService SEFAZ
|
v
Retornou sucesso (xRet == .T.) ?
|
+-------+-------+
| NAO | SIM
v v
retorna erro CON656 já existe?
|
+-------+-------+
| NAO | SIM
v v
INS656 STMPUPD
(codret, (codret,
retsefaz) retsefaz)
- L9298 -
Local lAudLeg := SuperGetMv("ES_AUDLEG",,.F.) - L9313–9321 - Pré-consulta:
CON656verifica se há registro. Se houver,STMPLEGgarante intervalo mínimo de 10 segundos. Se ainda não passaram 10s,STMPUPDatualiza o stamp e a função aborta com a mensagem "Muitas consultas em um intervalo curto de tempo para a mesma nota fiscal. Aguarde." - L9380–9386 - Pós-consulta: após o
WebServiceretornar com sucesso, seCON656indicar que não existe registro, oINS656cria; caso contrário,STMPUPDatualiza com o código e mensagem da SEFAZ.
Em fismntnfe.prw — ponto de entrada U_FISMNTNFE (linhas 20–67)
Contextualização: ponto de entrada do monitor nativo nfesefaz. Disparado quando uma nota tem seu status verificado/refrescado no monitor padrão.
- L32 -
lAudLeg := SuperGetMv("ES_AUDLEG",,.F.). Retorna se desabilitado. - L38–42 - Decide entre
INS656(primeiro registro) ouSTMPUPD(atualização) sempre comcTipo = "2"(saída por DOC+SÉRIE). - Em paralelo controla o refresh manual com cooldown de 60 segundos via
Static cUltTempo.
Job de limpeza — U_CLRLGBR
Contextualização: rotina de schedule diária. Deve ser cadastrada via SmartClient no agendador (Schedule) com parâmetros {cEmpAnt, cFilAnt} (default {"01","01"}). Realiza RpcSetEnv, executa DELETE FROM LEGBRANCA WHERE S_T_A_M_P_ <= SYSTIMESTAMP - INTERVAL '2' DAY e dispara RpcClearEnv.
Mapa de tipos de operação (cTipo)
cTipo = "1"- Entrada (chave da NF-e): filtraWHERE CHVNFE = cChave. Utilizado emU_SCNewConsSe.cTipo = "2"- Saída (doc + série): filtraWHERE DOC = cDoc AND SERIE = cSeri. Utilizado emU_FISMNTNFE.
Casos de teste
A seguir os cenários de teste recomendados para validação do projeto.
CT01 — Parâmetro desabilitado (ES_AUDLEG = .F.)
Pré-condição: Parâmetro ES_AUDLEG com valor .F..
Passos:
- Acessar o monitor SCOMA040 (Monitor de Recebimento XML).
- Selecionar uma NF-e válida e acionar "Consultar SEFAZ" várias vezes seguidas.
- Acessar o monitor nativo NFeSefaz e acionar o Refresh em uma NF de saída.
Resultado esperado:
- Nenhum registro inserido em
LEGBRANCA. - Funcionamento original mantido (consulta direta no TSS sem auditoria).
CT02 — Primeira consulta de entrada (U_SCNewConsSe)
Pré-condição: ES_AUDLEG = .T.. Tabela LEGBRANCA sem registros para a chave a ser testada.
Passos:
- Acessar o monitor SCOMA040.
- Selecionar uma NF-e nunca consultada.
- Acionar "Consultar SEFAZ".
Resultado esperado:
CON656retorna.F.(não existe).- Consulta ao WebService SEFAZ é realizada normalmente.
INS656insere o registro comCHVNFE,IDENT,CODRET,RETSEFAZeS_T_A_M_P_=CURRENT_TIMESTAMP.- Mensagem na
SZGé atualizada com o retorno (U_SCUpdZgSefaz).
Validação SQL:
SELECT * FROM LEGBRANCA WHERE IDENT = '<id_ent>' AND CHVNFE = '<chave>';
CT03 — Consulta de entrada repetida dentro de 10s
Pré-condição: Registro do CT02 já gravado há menos de 10 segundos.
Passos:
- Acionar "Consultar SEFAZ" para a mesma chave usada no CT02.
Resultado esperado:
CON656retorna.T.(existe).STMPLEGretorna.F.(delta < 10s).STMPUPDatualiza somente o stamp (sem alterarCODRET/RETSEFAZ).- Função retorna
aRet[2] = "Muitas consultas em um intervalo curto de tempo para a mesma nota fiscal. Aguarde.". - Nenhuma chamada ao WebService da SEFAZ é realizada.
CT04 — Consulta de entrada repetida após 10s
Pré-condição: Registro do CT02 já gravado há mais de 10 segundos.
Passos:
- Aguardar > 10 segundos.
- Acionar "Consultar SEFAZ" para a mesma chave.
Resultado esperado:
CON656retorna.T..STMPLEGretorna.T.(delta >= 10s).- Consulta WebService SEFAZ é realizada.
STMPUPDatualiza o stamp com o novoCODRET/RETSEFAZ.
CT05 — Auditoria de consulta de saída (U_FISMNTNFE) primeira vez
Pré-condição: ES_AUDLEG = .T.. Sem registro prévio em LEGBRANCA para o par DOC+SERIE.
Passos:
- Acessar o monitor NFeSefaz nativo.
- Selecionar uma NF de saída sem registro prévio.
- Acionar o Refresh no monitor.
Resultado esperado:
CON656(cTipo "2") retorna.F..INS656insere registro comDOC,SERIE,IDENT,CODRET,RETSEFAZ.
CT06 — Auditoria de consulta de saída repetida
Pré-condição: Registro existente para o par DOC+SERIE.
Passos:
- Acionar Refresh novamente em uma NF já consultada.
Resultado esperado:
CON656retorna.T..STMPUPDatualiza stamp + retorno SEFAZ.- O bloqueio temporal não se aplica ao FISMNTNFE (não usa STMPLEG).
CT07 — Cooldown do botão Refresh (60s) - FISMNTNFE
Pré-condição: O monitor de NF-e SEFAZ aberto.
Passos:
- Clicar no botão Refresh.
- Logo em seguida (< 60s) clicar no Refresh novamente.
Resultado esperado:
- Primeiro clique: processa normalmente.
- Segundo clique dentro do intervalo: dispara o diálogo modal de aguardo (
fismntmg) por 60 segundos com mensagem "Já foi clicado no Refresh nos últimos 60 segundos! Aguarde mais 60 segundos para tentar novamente!".
CT08 — Job de limpeza U_CLRLGBR
Pré-condição: Tabela LEGBRANCA com registros com S_T_A_M_P_ há mais de 2 dias e outros com menos de 2 dias.
Passos:
- Executar
U_CLRLGBR({"01","01"})via Schedule ou job manual.
Resultado esperado:
- Todos os registros com
S_T_A_M_P_ <= SYSTIMESTAMP - INTERVAL '2' DAYsão excluídos. - Registros mais recentes permanecem intactos.
- Função retorna
.T.e executa COMMIT.
Validação SQL antes do job:
SELECT COUNT(*) FROM LEGBRANCA WHERE S_T_A_M_P_ <= SYSTIMESTAMP - INTERVAL '2' DAY;
Validação SQL após o job:
SELECT COUNT(*) FROM LEGBRANCA WHERE S_T_A_M_P_ <= SYSTIMESTAMP - INTERVAL '2' DAY;
-- deve retornar 0
CT09 — CNPJ sem ID_ENT (cenário de erro de integração)
Pré-condição: CNPJ informado não possui vínculo em SPED001 x SZP.
Passos:
- Acionar "Consultar SEFAZ" para uma NF com CNPJ sem ID_ENT vinculado.
Resultado esperado:
U_SCGetIdEntretorna"".U_SCNewConsSeretornaaRet[2] = "Não foi possível encontrar o ID_ENT. Favor informar suporte Protheus!".- Nenhuma interação com
LEGBRANCAocorre (a verificação do CON656 ainda ocorre, porém comcIdEnt = ""não retorna registro).
CT10 — Diferenciação entre entrada e saída (cTipo)
Pré-condição: Mesma chave/doc auditados em operações de entrada e saída.
Passos:
- Realizar uma consulta de entrada (
cTipo = "1") através do SCOMA040. - Realizar uma consulta de saída (
cTipo = "2") através do FISMNTNFE para o mesmo registro.
Resultado esperado:
- Os filtros das funções
CON656,STMPLEGeSTMPUPDconsideram colunas distintas (CHVNFExDOC + SERIE), portanto o registro de entrada e o registro de saída são tratados de forma independente.
CT11 — Concorrência
Pré-condição: Duas sessões simultâneas tentando consultar a mesma chave.
Passos:
- Em duas sessões diferentes acionar a "Consultar SEFAZ" para a mesma chave dentro de 10 segundos.
Resultado esperado:
- Apenas a primeira efetua a consulta ao WebService.
- A segunda recebe o bloqueio do
STMPLEG. - Apenas um registro permanece em
LEGBRANCApara a chave (INSERTda primeira;UPDATEda segunda).
CT12 — Auditoria do retorno SEFAZ
Pré-condição: Cenário com diversas notas com diferentes códigos de retorno SEFAZ (100, 217, 656).
Passos:
- Realizar consultas que retornem cada um dos códigos.
Resultado esperado:
- Para cada consulta, o campo
CODRETeRETSEFAZé registrado corretamente. - A auditoria permite, através de uma query SQL, levantar todas as NFs com código
656retornado pela SEFAZ:
SELECT * FROM LEGBRANCA WHERE CODRET = '656' ORDER BY S_T_A_M_P_ DESC;
Configurações e instalações necessárias
- Criar a tabela
LEGBRANCAno schema utilizado porSIGA_PRODUCAO12(verificar o schema referenciado noINS656, linha 9073). - Liberar permissão de DML para o usuário do Protheus na tabela.
- Cadastrar o parâmetro
ES_AUDLEG(tipo lógico, default.F.). - Compilar
sharkxfun.prw,scoma040.prwefismntnfe.prw. - Configurar o ponto de entrada
FISMNTNFEno Configurador. - Agendar a rotina
U_CLRLGBRno Schedule (recomendado: 1x ao dia, fora do horário comercial).
O parâmetro ES_AUDLEG é "kill switch" da solução: desabilitando-o todo o fluxo retorna ao comportamento original sem qualquer impacto em performance.