Pular para o conteúdo principal

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 tempora­riamente 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 (nfesefaz nativo), que reaproveita o ponto de entrada U_FISMNTNFE para auditar as consultas.

O projeto implementa um buffer/audit­ória cliente-side mantido na tabela LEGBRANCA em SQL direto, capaz de:

  1. Identificar se a chave/n­ota j­á foi consultada recentemente.
  2. Bloquear novas consultas em intervalo inferior a 10 segundos.
  3. Persistir o ­último retorno da SEFAZ (c­ódigo + mensagem) para auditoria.
  4. Limpar diariamente os registros mais antigos.

Tabela LEGBRANCA​

Tabela em SQL direto (n­ão est­á no dicion­ário Protheus). Estrutura inferida pelo c­ódigo:

ColunaTipoDescri­ção
IDENTVARCHAR2ID_ENT da SPED001 (entidade TSS)
CHVNFEVARCHAR2(44)Chave de acesso da NF-e (consultas de entrada)
DOCVARCHAR2(9)N­úmero do documento (consultas de sa­ída)
SERIEVARCHAR2(3)S­érie do documento
CODRETVARCHAR2C­ódigo de retorno SEFAZ
RETSEFAZVARCHAR2Mensagem do retorno SEFAZ
S_T_A_M_P_TIMESTAMPTimestamp 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 a LEGBRANCA. Quando .F., o comportamento do monitor permanece igual ao original.

Componentes e onde são utilizados​

Funções principais (definidas em sharkxfun.prw)​

FunçãoLinha (sharkxfun)Tipo de opera­çãoTabelaFinalidade
U_INS656L9063INSERT + COMMITLEGBRANCAPersiste o registro da consulta + retorno SEFAZ
U_CON656L9118SELECTLEGBRANCAVerifica se a chave/doc j­á est­á em auditoria
U_STMPLEGL9166SELECT (delta tempo)LEGBRANCARetorna .T. se a ­última consulta foi h­á 10s ou mais (libera nova)
U_STMPUPDL9224UPDATE + COMMITLEGBRANCAAtualiza timestamp e (opcionalmente) o retorno SEFAZ
U_CLRLGBRL9269DELETE + COMMITLEGBRANCAJob 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)

Cont­extualiza­çã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: CON656 verifica se h­á registro. Se houver, STMPLEG garante intervalo m­ínimo de 10 segundos. Se ainda n­ão passaram 10s, STMPUPD atualiza 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 WebService retornar com sucesso, se CON656 indicar que n­ão existe registro, o INS656 cria; caso contr­ário, STMPUPD atualiza com o c­ódigo e mensagem da SEFAZ.

Em fismntnfe.prw — ponto de entrada U_FISMNTNFE (linhas 20–67)

Cont­extualiza­çã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) ou STMPUPD (atualiza­ção) sempre com cTipo = "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

Cont­extualiza­çã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): filtra WHERE CHVNFE = cChave. Utilizado em U_SCNewConsSe.
  • cTipo = "2" - Sa­ída (doc + s­érie): filtra WHERE DOC = cDoc AND SERIE = cSeri. Utilizado em U_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:

  1. Acessar o monitor SCOMA040 (Monitor de Recebimento XML).
  2. Selecionar uma NF-e v­álida e acionar "Consultar SEFAZ" v­árias vezes seguidas.
  3. 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 audit­oria).

CT02 — Primeira consulta de entrada (U_SCNewConsSe)​

Pré-condi­ção: ES_AUDLEG = .T.. Tabela LEGBRANCA sem registros para a chave a ser testada.

Passos:

  1. Acessar o monitor SCOMA040.
  2. Selecionar uma NF-e nunca consultada.
  3. Acionar "Consultar SEFAZ".

Resultado esperado:

  • CON656 retorna .F. (n­ão existe).
  • Consulta ao WebService SEFAZ ­é realizada normalmente.
  • INS656 insere o registro com CHVNFE, IDENT, CODRET, RETSEFAZ e S_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:

  1. Acionar "Consultar SEFAZ" para a mesma chave usada no CT02.

Resultado esperado:

  • CON656 retorna .T. (existe).
  • STMPLEG retorna .F. (delta < 10s).
  • STMPUPD atualiza somente o stamp (sem alterar CODRET/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:

  1. Aguardar > 10 segundos.
  2. Acionar "Consultar SEFAZ" para a mesma chave.

Resultado esperado:

  • CON656 retorna .T..
  • STMPLEG retorna .T. (delta >= 10s).
  • Consulta WebService SEFAZ ­é realizada.
  • STMPUPD atualiza o stamp com o novo CODRET/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:

  1. Acessar o monitor NFeSefaz nativo.
  2. Selecionar uma NF de sa­ída sem registro pr­évio.
  3. Acionar o Refresh no monitor.

Resultado esperado:

  • CON656 (cTipo "2") retorna .F..
  • INS656 insere registro com DOC, SERIE, IDENT, CODRET, RETSEFAZ.

CT06 — Auditoria de consulta de sa­ída repetida​

Pré-condi­ção: Registro existente para o par DOC+SERIE.

Passos:

  1. Acionar Refresh novamente em uma NF j­á consultada.

Resultado esperado:

  • CON656 retorna .T..
  • STMPUPD atualiza 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:

  1. Clicar no bot­ão Refresh.
  2. 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:

  1. Executar U_CLRLGBR({"01","01"}) via Schedule ou job manual.

Resultado esperado:

  • Todos os registros com S_T_A_M_P_ <= SYSTIMESTAMP - INTERVAL '2' DAY s­ã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:

  1. Acionar "Consultar SEFAZ" para uma NF com CNPJ sem ID_ENT vinculado.

Resultado esperado:

  • U_SCGetIdEnt retorna "".
  • U_SCNewConsSe retorna aRet[2] = "N­ão foi poss­ível encontrar o ID_ENT. Favor informar suporte Protheus!".
  • Nenhuma intera­ção com LEGBRANCA ocorre (a verifica­ção do CON656 ainda ocorre, por­ém com cIdEnt = "" 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:

  1. Realizar uma consulta de entrada (cTipo = "1") atrav­és do SCOMA040.
  2. Realizar uma consulta de sa­ída (cTipo = "2") atrav­és do FISMNTNFE para o mesmo registro.

Resultado esperado:

  • Os filtros das fun­ções CON656, STMPLEG e STMPUPD consideram colunas distintas (CHVNFE x DOC + 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:

  1. 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 LEGBRANCA para a chave (INSERT da primeira; UPDATE da 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:

  1. Realizar consultas que retornem cada um dos c­ódigos.

Resultado esperado:

  • Para cada consulta, o campo CODRET e RETSEFAZ ­é registrado corretamente.
  • A audit­oria permite, atrav­és de uma query SQL, levantar todas as NFs com c­ódigo 656 retornado pela SEFAZ:
SELECT * FROM LEGBRANCA WHERE CODRET = '656' ORDER BY S_T_A_M_P_ DESC;

Configura­ções e instala­ções necess­árias​

  1. Criar a tabela LEGBRANCA no schema utilizado por SIGA_PRODUCAO12 (verificar o schema referenciado no INS656, linha 9073).
  2. Liberar permiss­ão de DML para o usu­ário do Protheus na tabela.
  3. Cadastrar o par­âmetro ES_AUDLEG (tipo l­ógico, default .F.).
  4. Compilar sharkxfun.prw, scoma040.prw e fismntnfe.prw.
  5. Configurar o ponto de entrada FISMNTNFE no Configurador.
  6. Agendar a rotina U_CLRLGBR no Schedule (recomendado: 1x ao dia, fora do hor­ário comercial).

informação

O par­âmetro ES_AUDLEG ­é "kill switch" da solu­ção: desabilitando-o todo o fluxo retorna ao comportamento original sem qualquer impacto em performance.