Página 1 de 2

Manifestação NFe e Download XML via ACBrMonitorPlus

Enviado: 29 Mai 2018 10:19
por fladimir
Olá pessoal, tudo bem...

A pedido do meu amigo Rubens aki do fórum em outro tópico estou compartilhando a maneira q estou fazendo, primeiramente tb quero dedicar agradecimentos ao Daniel q tão solidariamente cedeu a comunidade a rotina de montagem do XML a partir da consulta da chave, q tanto nos foi útil, mas de um tempo pra cá parou de funcionar, pode ser q com ajustes volte a funcionar, mas uma coisa é fato, o governo pode alterar isso a qualquer momento tendo q ter muita manutenção a rotina.

Agora existe uma forma de baixar o XML via webservices do governo através do certificado digital, isto é feito manifestando a NFe e posteriormente efetuando-se o download.

Resolvi adotar essa metodologia devido a maioria dos clientes já trabalhar com NFe ou NFCe ou seja, tem o certificado então basta configurar para manifestar e fazer o download.

A lógica q montei foi a seguinte, na entrada de notas, informou a chave da NFe sinal q quero dar entrada na mesma e estou de posse dela, então logicamente a operação foi confirmada.

O q eu faço é tentar baixar o XML, caso não de certo e o retorno dessa tentativa seja q existe NFe pra chave informada e a situação dessa nota é AUTORIZADA e o tipo é SAIDA (ou seja, saiu do emitente e será efetuada entrada no destinatario), eu manifesto ela como Confirmação da Operação e após isso já é possível o Download após algum tempo.

A rotina então ficou desta forma:

Código: Selecionar todos

********************************************************************************
STATIC FUNCTION Entrada_Aux_DFe( cChave )
	LOCAL cChave_CNPJ, cChave_AnoMes, cArqXML, cPathDown

	cArqXML       := cChave + '-nfe.xml'
	cChave_CNPJ   := SUBSTR(cChave,07,14)
	cChave_AnoMes := '20'+SUBSTR(cChave,03,04)
	cPathDown     := oACBrNFe:cDirDoMonitor + 'RESPOSTA\' +cChave_CNPJ+ '\NFe\' +cChave_AnoMes+ '\Down\'
	IF DFe_BaixaXML( cChave ) 
		IF File( cPathDown+cArqXML )  // BAIXOU
			FileMove( cPathDown+cArqXML, CurDirSys()+'XML\'+cArqXML)
		ELSE 	// NAO BAIXOU // MANIFESTA COMO CONFIRMACAO DA OPERACAO
			IF DFe_Manifestar(cChave, 2) // 1 Ciencia 2 Confirmação 3 Desconhecimento 4 Operacao nao realizada
				Alert('NFe nao havia sido manifestada!;Aguardar pelo menos 5 min para baixar XML;Em caso de duvida entrar em contato com o suporte', aOk, vcamarelo)
			ELSE
				Alert('NFe nao havia sido manifestada!;Falha ao manifestar NFe;Solicite XML ao fornecedor ou em caso de duvida contactar o suporte', aOk, vcamarelo)
			ENDIF			
		ENDIF
	ENDIF
RETURN NIL
********************************************************************************
STATIC FUNCTION DFe_BaixaXML( cChave )
	LOCAl aParametros, lRet := .F.
	aParametros := {}
	aadd( aParametros, xUFTocUF( cUserUF ) )
	aadd( aParametros, cCNPJUser           )
	aadd( aParametros, cChave              )
	oACBrNFe:CriaReq( 'NFe.DistribuicaoDFePorChaveNFe', aParametros ) // NFe.DistribuicaoDFePorChaveNFe("50", "03891241000166", "41100300903403000170550100000780201030797370")
	lRet := (oACBrNFe:cStatus == '138') // tem NFe pra chave em questao
	IF lRet ; lRet := (ASCAN(oACBrNFe:aRetorno, 'TPAMB=1')>0)  ; ENDIF // Emitida em Ambiente de Autorizacao
	IF lRet ; lRet := (ASCAN(oACBrNFe:aRetorno, 'TPNF=1')>0)   ; ENDIF // Tipo da Nota de Saida do Emitente
	IF lRet ; lRet := (ASCAN(oACBrNFe:aRetorno, 'CSITNFE=1')>0); ENDIF // Situação AUTORIZADA
RETURN lRet	
********************************************************************************
STATIC FUNCTION DFe_Manifestar(cChave, nTipo) // 1 Ciencia 2 Confirmação 3 Desconhecimento 4 Operacao nao realizada
	LOCAL cLin := '', lOk := .F.
	IF nTipo >0 .and. nTipo <=4
		cLin += '[EVENTO]'    + CRLF
		cLin += 'idLote=1'    + CRLF
		cLin += '[EVENTO001]' + CRLF
		cLin += 'chNFe='      + cChave    + CRLF
		cLin += 'cOrgao=91'   + CRLF
		cLin += 'CNPJ='       + cCNPJUser + CRLF
		cLin += 'dhEvento=' + DTOC(date())+' '+Time()+ CRLF
		cLin += 'tpEvento=' + IIF( nTipo == 1, '210210', IIF( nTipo == 2, '210200', IIF( nTipo == 3, '210220', '210240')))+CRLF
		cLin += 'nSeqEvento=1'                       + CRLF
		cLin += 'versaoEvento=' + pub_NFeVersao      + CRLF
		cLin += 'descEvento=' + IIF( nTipo == 1, 'Ciencia da Operacao', ;
                                                     IIF( nTipo == 2, 'Confirmacao da Operacao', ;     
                                                       IIF( nTipo == 3, 'Desconhecimento da Operacao', 'Operacao nao realizada')))+CRLF
	ENDIF
	IF !EMPTY(cLin)
		oACBrNFe:CriaReq( 'NFe.EnviarEvento', cLin)
		lOk := (ASCAN(oACBrNFe:aRetorno, 'CSTAT=135')>0) // ok
	ENDIF
RETURN lOk
Observações: O comando NFe.DistribuicaoDFePorChaveNFe, verifica a situação da NFe e caso ela tenha sido manifestada faz automaticamente o download do XML, caso não traz o resumo da NFe apenas, sendo necessário manifestar para posterior download.
Qdo é feito o download o ACBr cria o XML dentro da pasta de resposta das solicitações criando uma SUBPASTa com o nome igual ao CNPJ do emitente da NFe, dentro dessa pasta tem outra chamada NFe e depois outra com o Ano e Mes da emissao dessa NFe, depois outra chamada Down e ai sim vem o XML

Manifestação NFe e Download XML via ACBrMonitorPlus

Enviado: 29 Mai 2018 10:25
por rubens
Obrigado Fladimir...

Muito bem explicado...

Valeu...

Rubens

Manifestação NFe e Download XML via ACBrMonitorPlus

Enviado: 29 Mai 2018 11:33
por janio
Fladimir,

Após a manifestação o DOWNLOAD não esta automaticamente LIBERADO?

Janio

Manifestação NFe e Download XML via ACBrMonitorPlus

Enviado: 29 Mai 2018 11:41
por fladimir
Sim e não.

Na rotina falei pra aguardar uns 5 min, mas pode tentar em seguida, esse tempo para liberar o download é do servidor da SEFAZ.
Conforme pesquisei há relatos q pode ser instantaneo ou demorar uns minutos.
Então eu coloquei a mensagem, mas se o usuário já quiser ir na sequencia pode tentar.

Manifestação NFe e Download XML via ACBrMonitorPlus

Enviado: 24 Abr 2019 15:36
por hudson
Boa tarde. Eu sei que o post é antigo, mas gostaria de saber sobre as varíaveis que deram erro prá mim, no caso, oACBrNFE e a função CriaReq(), que aparecem no fonte mas não tem as funções. Essas e mais algumas que estariam faltando para poder fazer a Manifestação.
Desde já obrigado.

Manifestação NFe e Download XML via ACBrMonitorPlus

Enviado: 25 Abr 2019 00:50
por fladimir
oACBr é uma variável q carrega uma classe q criei pra uso meu aki
CriaReq é um método dessa classe q recebe os parâmetros e cria o arquivo q o ACBr lê no path etc com o comando recebido, posso postar o método aki, mas como ele é dependente da minha classe e lógica não sei se resolveria muito pra vc, em todo caso segue abaixo.

Código: Selecionar todos

//------------------------------------------------------------------------------

method CriaReq(cComando, xPar, lFechaASPAS, nTimeOut, lEsperaPraVerRet) CLASS TACBr
   local lOk := .F.
   // nTimeOut uso no processaretorno q ‚ chamado pelo MandaReq
	DEFAULT lEsperaPraVerRet TO .F. // Uso isso aki no CTe
   
	*-- Apaga o arquivo de comando
	ferase( ::cArqCMD )
	ferase( ::cArqTXT )

	*-- Requisicao
   printON()
   SET PRINTER TO ( ::cArqCMD )

	if valtype(xPar) == 'A'
		cComando += '(' 
		for nI:=1 To len(xPar)
			default xPar[nI] To '' && se for NIL faz empty
			if !empty(xPar[nI])
				cComando += ASPAS + xPar[nI] + ASPAS + if(len(xPar)>nI , ',', ')')
			else
				cComando += xPar[nI] + if(len(xPar)>nI , ',', ')')
			endif				
		next 
	   @ 0,0 say cComando
	else
		default xPar        to ''
		default lFechaASPAS to .T.
	   @ 0,0 say cComando + '(' + chr(34) + xPar + if( lFechaASPAS, chr(34), '') + ')'
	endif
   SET PRINTER TO
	printOFF()
   if File( ::cArqCMD )
      ::MandaReq( ::cArqCMD, NIL, nTimeOut, lEsperaPraVerRet)
      lOk := .T.
   Endif
return lOk


//------------------------------------------------------------------------------

method MandaReq(cArqReq, cTexto, nTimeOut, lEsperaPraVerRet) CLASS TACBr
 //--> Envia Arq Gerado para ACBrNFeMonitor

	default cTexto           to ''
	default lEsperaPraVerRet to .F.
	
	*-- Apaga retorno do ACBr
	FERASE( ::cDirDoMonitor +  'SAINFE' + cTerminal + '.TXT' )
	if ::lMostraProcess .and. !empty(cTexto)
   	Mensag(cTexto)
	endif
	*-- Cria Arq para ACBr Ler
   FILECOPY( cArqReq,  ::cDirdoMonitor+cArqReq )
	FILEDELETE( cArqReq )																																			
	*-- Renomeia arq de comando para TXT ACBr ler
	while !file( ::cDirDoMonitor + ::cArqCMD )
	end
	FRENAME( ::cDirDoMonitor+cArqReq,   ::cDirDoMonitor + ::cArqTXT )
	IF lEsperaPraVerRet // Transportadora Olivette
		INKEY(1) // vou esperar 0,5s depois de Enviar comando/XML
	ENDIF
	::cStatus  := ::cRetorno := ''
	::ProcessaRetorno(nTimeOut) // Le retorno e processa pegando status
	*-- Apaga Arquivos
	FILEDELETE( cArqReq ) // Arquivo Comando local																																			
	FERASE(   ::cArqTXT ) // Arquivo ACBr
	FERASE(   ::cArqCMD ) // Arquivo Comando pasta ACBr
return nil

********************************************************************************
method ProcessaRetorno(nTimeOut) CLASS TACBr
	local REQ, RESP, nTent, nHoraInicio := Seconds(), lTentaAbrir := .T.
   local cTela := savescreen(23,1,23,78)
	DEFAULT nTimeOut To 120 // era 300 mas 300 ‚ igual 5 min muito tempo

	::cRetorno := ''
   REQ  := ::cDirDoMonitor + ::cArqTXT // ENT.TXT
	RESP := ::cDirDoMonitor + 'SAINFe' + cTerminal + '.TXT'

	*-- Fa‡a enquanto o ACBr nÆo ler o arquivo // Qdo ele le ele apaga 
	while file(REQ)
		IF Seconds() - nHoraInicio > nTimeOut // se arquivo nÆo apaga entÆo nÆo ta lendo
		   ::cRetorno := 'ERRO: Protocolo nao esta ativo'
			::cStatus  := ::cRetorno
			return nil
      endif
      inkey(0.1)
   end
   restscreen(23,1,23,78, cTela)

   ///------------  Lendo a resposta  ------------------//
   nTent    := 1
   while empty(::cRetorno)
      inkey(0.1)
		if ::lMostraProcess
         Mensag( 'Lendo retorno do Protocolo ACBr...' + {'/', '\'}[nTent%2+1], {'N+/W', 'N/W*'}[nTent%2+1] )
         Mensag( 'Lendo retorno do Protocolo ACBr...' + {'-', '|'}[nTent%2+1], {'N+/W', 'N/W*'}[nTent%2+1] )
		endif
	
		*-- Se tem RETORNO... avalia se esta crescendo 
		if file(RESP)  
      	nSize := len(hb_memoread(RESP))
			while nSize <> len(hb_memoread(RESP)) // sinal q arquivo esta crescendo
				NextKey() // coloquei devido uma dica pra liberar o processador
				inkey(0.1)
				nSize := len(hb_memoread(RESP))
			end
         ::cRetorno := alltrim(hb_memoread( RESP ))
      endif
      if empty(::cRetorno) // SE VAZIO ESPERA PRA PEGAR O RETORNO DURANTE 5 SEGUNDOS
         if nTent == 100 
				RESP := ::cDirDoMonitor + 'SAINFe.TXT'
         elseif nTent > 600
            ::cRetorno := 'ERRO: Sem resposta do Protocolo em ' + alltrim(str(INT(nTent/2)))+ ' segundos (TimeOut)'
			endif
			NextKey() // coloquei devido uma dica pra liberar o processador
         millisec(60)
         nTent++
      endif
   end
	while right(::cRetorno,1) $ CRLF   // Remove sinalizadores do final
	   ::cRetorno := left(::cRetorno, len(::cRetorno)-1)
	end
	::cRetorno := UPPER(ACENT2(::cRetorno))
	::aRetorno := Split(::cRetorno, CRLF) // criei pra usar na analise de todas as linhas do retorno via Array

	*-- Analisa cStat caso haja
	::cStatus :=  alltrim(str( ::PegaCSTAT( ::cRetorno ) ))	//SUBSTR( cRetorno, AT("CSTAT=", cRetorno)+6, 3 )
	if val(::cStatus) > 0 .and. val(::cStatus) == 100 // Ok
		::cStatus := '100'
	elseif val(::cStatus) >0 
		::cStatus := alltrim(::cStatus)
	else // se cStatus = 0 ou diferente de n£meros pega o RetACBr
		::cStatus := ::cRetorno
	endif
	if ::lMostraProcess 
		limpa()
	endif
  return nil
********************************************************************************
method MostraRetorno() CLASS TACBr
   LOCAL cRetcStat, aCSTAT := {}, aRetorno, cLinha, nI
	LOCAL cCorOLD := SETCOLOR()
   local cTelaMsg := SaveScreen(s_geral)
	*-- Mostra o Retorno baseado no cStat	
   if !empty( ::cStatus )
		cRetcStat := ::VerifyCSTAT()
		if empty( cRetcStat )
			cRetcStat := 'RETORNO INDEFINIDO'
		else
		   cRetcStat := WIN_OemToAnsi( HB_UTF8ToStr(cRetcStat) )      
			IF 'XMOTIVO' $ upper(cRetcStat)
				aRetorno := HB_aTokens( STRTRAN(cRetcStat, CHR(13)), CHR(10))
				cRetcStat := '' + CRLF
				FOR nI:=1 TO LEN(aRetorno)
					cLinha := UPPER(aRetorno[nI] )
					if 'CSTAT'   $ left(cLinha, 10) 
						nCSTAT := VAL( SUBSTR(cLinha, AT('CSTAT=', upper(cLinha) )+6, 4))
						IF ASCAN(aCSTAT, { |x| x=nCSTAT} ) == 0 
							aadd( aCSTAT, nCSTAT)
						ELSE
							nI++
							LOOP
						ENDIF
					endif
					if 'CSTAT'   $ left( cLinha, 10) .or. 'XMOTIVO' $ left( cLinha, 10) 
						cRetcStat += cLinha + CRLF 
					endif
				NEXT
			endif
			cRetcStat := upper(WIN_ANSITOOEM(Upper(cRetcStat)))
		endif
	   SETCOLOR('N*/N,W*/RB,W+/GB,W+/R,W+/R') //'N/W,N/W,,,W+/R')
	   Caixa(01,12,20,67,,,'Retorno SEFAZ','W+/GB',,.F.) 
		Quebra(3, '54', substr(cRetcStat, AT('[RETORNO]', upper(cRetcStat))), .T., .T., 3, 13,,,,,'W+/R') ;	inkey(0)
	   SETCOLOR(cCorOld)
   endif
   RestScreen(s_geral, cTelaMsg)
return nil

Uma dica q te dou é onde esta o CriaReq vc pensa assim criar um TXT pro monitor ler contendo o parametro q eu passo para o CriaReq, depois vc lê o retorno q o ACBr vai criar.

Manifestação NFe e Download XML via ACBrMonitorPlus

Enviado: 25 Abr 2019 07:51
por JoséQuintas
Tem usuário fazendo isso pela Sefazclass.
Talvez até simplifique.

Manifestação NFe e Download XML via ACBrMonitorPlus

Enviado: 26 Abr 2019 06:50
por hudson
Obrigado a todos.
Vou tentar ajustar suas funções para meu uso e vou estudar a SefazClass.

Manifestação NFe e Download XML via ACBrMonitorPlus

Enviado: 30 Abr 2019 16:20
por Fernando queiroz
na SEFAZCLASS tem

METHOD NFeEventoManifestacao( cChave, cCnpj, cCodigoEvento, xJust, cCertificado, cAmbiente )

agora so falta a opção de download :)) :)) :))

Manifestação NFe e Download XML via ACBrMonitorPlus

Enviado: 30 Abr 2019 18:40
por JoséQuintas
Pra mim já tinha isso.... me enganei.

Manifestação NFe e Download XML via ACBrMonitorPlus

Enviado: 30 Abr 2019 18:58
por JoséQuintas
Não encontro em qual manual tem a última versão de download.
Aquele NFEDistribuição é pra download, ou pra consultar apenas?

Manifestação NFe e Download XML via ACBrMonitorPlus

Enviado: 30 Abr 2019 19:04
por JoséQuintas
É que não se chama mais NfeDownloadNfe....
Faz tanto tempo que já tinha esquecido...
É que não uso isso, e é de 2014...
nfe.png

Manifestação NFe e Download XML via ACBrMonitorPlus

Enviado: 01 Mai 2019 15:36
por Fernando queiroz

Código: Selecionar todos

METHOD NFeDistribuicaoDFe( cCnpj, cUltNSU, cNSU, cUF, cCertificado, cAmbiente ) CLASS SefazClass

   hb_Default( @::cProjeto, WS_PROJETO_NFE )
   hb_Default( @::cVersao, WS_NFE_DEFAULT )
   hb_Default( @cUltNSU, "0" )
   hb_Default( @cNSU, "" )

   ::aSoapUrlList := WS_NFE_DISTRIBUICAO
   ::Setup( cUF, cCertificado, cAmbiente )
   ::cSoapAction  := "nfeDistDFeInteresse"
   ::cSoapService := "http://www.portalfiscal.inf.br/nfe/wsdl/NFeDistribuicaoDFe"

   ::cXmlEnvio    := [<distDFeInt versao="] + ::cVersao + [" ] + WS_XMLNS_NFE + [>]
   ::cXmlEnvio    +=    XmlTag( "tpAmb", ::cAmbiente )
   ::cXmlEnvio    +=    XmlTag( "cUFAutor", ::UFCodigo( ::cUF ) )
   ::cXmlEnvio    +=    XmlTag( "CNPJ", cCnpj ) // ou CPF
   IF Empty( cNSU )
      ::cXmlEnvio +=   [<distNSU>]
      ::cXmlEnvio +=      XmlTag( "ultNSU", cUltNSU )
      ::cXmlEnvio +=   [</distNSU>]
   ELSE
      ::cXmlEnvio +=   [<consNSU>]
      ::cXmlEnvio +=      XmlTag( "NSU", cNSU )
      ::cXmlEnvio +=   [</consNSU>]
   ENDIF
   ::cXmlEnvio   += [</distDFeInt>]
   ::XmlSoapPost()

   RETURN ::cXmlRetorno
Aguem já usou ou usa esta rotina , ela faz ou não a baixa do xml da NF-e

ela consta na sefazclass mas não sei o objetivo dela

quintas da uma dica ai

Manifestação NFe e Download XML via ACBrMonitorPlus

Enviado: 01 Mai 2019 17:32
por JoséQuintas
Vou ter que olhar melhor o manual, dá a impressão de que só fiz a parte de consultar documentos.

Mas o que faz também é interessante:
Saber quais notas fora emitidas, antes mesmo do fornecedor avisar.

Manifestação NFe e Download XML via ACBrMonitorPlus

Enviado: 01 Mai 2019 23:26
por JoséQuintas
METHOD NFeDistribuicaoDFe( cCnpj, cUltNSU, cNSU, cChave, cUF, cCertificado, cAmbiente ) CLASS SefazClass
pegou versão anterior.
O parâmetro chave é justamente pra download.
Agora é dar uma olhada na NT 2014.002 pra tirar dúvidas.