Página 1 de 6

Acompanhando as mudanças da hbnfe

Enviado: 27 Nov 2014 21:12
por JoséQuintas
Conforme for alterando, vou postando aqui.

Algumas alterações talvez sejam odiadas se não houver uma explicação, ou talvez até mesmo com explicação.

Vou inverter: ao invés de fonte xHarbour com compatibilidade Harbour, vai ser fonte Harbour com compatibilidade xHarbour, ou talvez compatibilidade com qualquer um.

É desse jeito que trabalho:
Primeiro vou ajeitando os fontes, organizando, reduzindo código, e se possível já com alguma alteração.
Isso permite ir entendendo melhor as rotinas e vendo possibilidades.
Conforme o fonte vai sendo reduzido, dá pra enxergar melhor o próprio fonte, e encontrar mais coisa pra reduzir/melhorar.

Qualquer coisa... dá pra reverter todas as alterações no CVS....

E se for algo muito ruim, dá tempo de reverter sem perder novas alterações.

Alterações mais pesadas, só quando conseguir compilar aqui.

Acompanhando as mudanças da hbnfe

Enviado: 27 Nov 2014 21:18
por JoséQuintas
Comecei o tópico depois de já ter começado alterações.
A rotina de assinatura agora assina qualquer coisa.
Ficou menor que antes, porque muitos IFs foram eliminados, e tá fácil de acrescentar coisas novas.

Fica pendente aqui: assinar sem arquivo nenhum (igual a minha, mas mantendo a forma atual pra compatibilidade), usar a CN do certificado (razão social), deixá-la mais independente do restante. Isso pede mudanças na parte central da hbnfe, e sem poder compilar é perigoso.

Acompanhando as mudanças da hbnfe

Enviado: 27 Nov 2014 21:34
por JoséQuintas
Criei este fonte pra compabilidade xharbour:

Código: Selecionar todos

#ifdef __XHARBOUR__
FUNCTION win_OleCreateObject( cObjeto )
   RETURN xhb_CreateObject( cObjeto )
#endif
Motivo:
Algo parecido era feito em 50 locais diferentes que usavam OLE.
Destes, alguns não tinham isso, então não estavam compatíveis com Harbour.
Agora todos estão iguais.
fontes anterior: 830.713 bytes, 18.354 linhas
depois: 826.007 bytes, 18.249 linhas

100 linhas a menos pra atrapalhar.
Na prática foram mais, é que acrescentei linha em branco antes e depois de cada chamada dessa... Reduzir fonte sim, mas isso não significa sair espremendo o fonte e deixar ilegível.

Acompanhando as mudanças da hbnfe

Enviado: 28 Nov 2014 00:07
por sygecom
José,
Muito bom, visto que a maioria usa Harbour também acho que o caminho é esse mesmo, infelizmente ainda uso xHarbour, mas no que eu poder ajudar estou a disposição.
Vou arrumar um tempo para comitar os ajustes que tenho para CTe, e ver se consigo fazer alguns exemplos melhor para HBNFE.

Acompanhando as mudanças da hbnfe

Enviado: 28 Nov 2014 01:09
por JoséQuintas
Achei o motivo de muitos erros na lista: MemoWrit()
No xHarbour aceita um terceiro parâmetro.

Mais duas funções no módulo de compatibilidade:

Código: Selecionar todos

// Gravar sem o Fim de arquivo do DOS Chr(26)
FUNCTION hb_MemoWrit( cFileName, cText )
   RETURN MemoWrit( cFileName, cText, .F. )

// CRLF
FUNCTION HB_EOL()
   RETURN HB_OsNewLine()

Acompanhando as mudanças da hbnfe

Enviado: 28 Nov 2014 01:38
por JoséQuintas
Pra quem não conhece as vantagens da compilação -w3 -es2 do Harbour:
Os erros da compilação neste momento:

Código: Selecionar todos

d:\CVSFiles\hbnfe\source>hbmk2 hbnfe -xhb
hbmk2: Processing environment options: -comp=msvc
hbmk2: Compiling Harbour sources...
Harbour 3.4.0dev (a330318) (2014-11-19 11:30)
Copyright (c) 1999-2014, https://github.com/vszakats/harbour-core/
Compiling 'hbMDFe.prg'...
hbMDFe.prg(513) Warning W0032  Variable 'MI' is assigned but not used in function 'HBMDFE_XMLMODALRODOVIARIO(366)'
hbMDFe.prg(815) Warning W0032  Variable 'MI' is assigned but not used in function 'HBMDFE_XMLDOCUMENTOS(520)'
hbMDFe.prg(815) Warning W0032  Variable 'CI' is assigned but not used in function 'HBMDFE_XMLDOCUMENTOS(520)'
hbMDFe.prg(905) Warning W0032  Variable 'MI' is assigned but not used in function 'HBMDFE_XMLTOT(822)'
hbMDFe.prg(1117) Warning W0032  Variable 'CXMLSIG' is assigned but not used in function 'HBMDFE_ASSINA_XML(912)'
hbMDFe.prg(1117) Warning W0032  Variable 'POSINI' is assigned but not used in function 'HBMDFE_ASSINA_XML(913)'
hbMDFe.prg(1117) Warning W0032  Variable 'POSFIM' is assigned but not used in function 'HBMDFE_ASSINA_XML(913)'
hbMDFe.prg(1117) Warning W0032  Variable 'NP' is assigned but not used in function 'HBMDFE_ASSINA_XML(913)'
hbMDFe.prg(1117) Warning W0032  Variable 'NRESULT' is assigned but not used in function 'HBMDFE_ASSINA_XML(913)'
hbMDFe.prg(1305) Warning W0032  Variable 'CURLWS' is assigned but not used in function 'HBMDFE_COMUNICAWEBSERVICE(1219)'
hbMDFe.prg(1374) Warning W0003  Variable 'OSERVERWS' declared but not used in function 'HBMDFE_RECEPCAOMDFE(1310)'
hbMDFe.prg(1374) Warning W0003  Variable 'ODOMDOC' declared but not used in function 'HBMDFE_RECEPCAOMDFE(1310)'
hbMDFe.prg(1374) Warning W0032  Variable 'CCERT' is assigned but not used in function 'HBMDFE_RECEPCAOMDFE(1312)'
hbMDFe.prg(1374) Warning W0032  Variable 'CURLWS' is assigned but not used in function 'HBMDFE_RECEPCAOMDFE(1312)'
hbMDFe.prg(1374) Warning W0032  Variable 'CXMLRESP' is assigned but not used in function 'HBMDFE_RECEPCAOMDFE(1312)'
hbMDFe.prg(1462) Warning W0032  Variable 'CXMLRESP' is assigned but not used in function 'HBMDFE_RETRECEPCAOMDFE(1380)'
hbMDFe.prg(1574) Warning W0032  Variable 'CXMLRESP' is assigned but not used in function 'HBMDFE_CONSULTAMDF(1468)'
hbMDFe.prg(1574) Warning W0032  Variable 'CXMLINFPROT' is assigned but not used in function 'HBMDFE_CONSULTAMDF(1468)'
hbMDFe.prg(1574) Warning W0032  Variable 'CXMLEVENTOMDFE' is assigned but not used in function 'HBMDFE_CONSULTAMDF(1468)'
hbMDFe.prg(1574) Warning W0032  Variable 'CXMLEVCANCMDFE' is assigned but not used in function 'HBMDFE_CONSULTAMDF(1468)'
hbMDFe.prg(1574) Warning W0032  Variable 'CXMLRETEVENTOMDFE' is assigned but not used in function 'HBMDFE_CONSULTAMDF(1468)'
hbMDFe.prg(1628) Warning W0001  Method <MDFeEvento(cXMLeve)> not declared or declaration mismatch in class <hbMDFe>
hbMDFe.prg(1628) Warning W0032  Variable 'CXMLRESP' is assigned but not used in function 'HBMDFE_STATUSSERVICO(1580)'
hbMDFe.prg(1826) Warning W0032  Variable 'CXMLRESP' is assigned but not used in function 'HBMDFE_MDFECANCELA(1755)'
hbMDFe.prg(1984) Warning W0001  Ambiguous reference 'NSCAN'
hbMDFe.prg(1985) Warning W0001  Ambiguous reference 'NSCAN'
hbMDFe.prg(1986) Warning W0001  Ambiguous reference 'NSCAN'
2000
No code generated.
hbmk2 [hbnfe]: Error: Running Harbour compiler. 1
assigned but not used é atribuir um valor pra variável mas que não precisa.
tipo isto:

Código: Selecionar todos

x = 1
x = 2
A linha 1 dá erro, porque se for apagada não faz falta.
A linha 2 também poderia dar erro, porque atribuiu x e não usou pra nada depois.
Essa vantagem adicional é do Harbour 3.2/3.4 ao compilar usando -w3 -es2.
Faz com que o fonte não contenha coisas que não precisa.

Acompanhando as mudanças da hbnfe

Enviado: 28 Nov 2014 01:40
por JoséQuintas
Agora complicou....
Deu erro numa rotina em C.

Código: Selecionar todos

hbNFeIniToXML.prg(2409) : warning C4090: 'initializing' : different 'const' qualifiers
hbNFeIniToXML.prg(2410) : warning C4090: 'initializing' : different 'const' qualifiers
hbNFeIniToXML.prg(2411) : warning C4090: 'initializing' : different 'const' qualifiers
hbNFeIniToXML.prg(2412) : warning C4090: 'initializing' : different 'const' qualifiers
seriam estas linhas:

Código: Selecionar todos

   char * lpSection = hb_parc( 1 );
   char * lpEntry = HB_ISCHAR(2) ? hb_parc( 2 ) : NULL ;
   char * lpDefault = hb_parc( 3 );
   char * lpFileName = hb_parc( 4 );

Acompanhando as mudanças da hbnfe

Enviado: 28 Nov 2014 01:53
por JoséQuintas
Resolvido pra compilar... movi pro módulo de compatibilidade.
Mas agora não entendi o porquê deste erro, e sinceramente não sei como resolver.
Não faço idéia porque está reclamando de uma lib que não existe.

Código: Selecionar todos

d:\CVSFiles\hbnfe\source>hbmk2 hbnfe -xhb
hbmk2: Processing environment options: -comp=msvc
hbmk2: Linking... hbini.exe
LINK : fatal error LNK1181: cannot open input file 'debug.lib'
hbmk2 [hbnfe]: Error: Running linker. 1181
link.exe @d:\temp\yi2l91.lnk

Acompanhando as mudanças da hbnfe

Enviado: 28 Nov 2014 06:24
por JoséQuintas
Fiquei com uma dúvida agora....
Afinal, alguém está usando a hbnfe?

Encontrei erros nos fontes, também gerei erros nas minhas alterações, e não vi nenhum comentário.
E simplesmente parece que não dava pra compilar com Harbour.

Acompanhando as mudanças da hbnfe

Enviado: 28 Nov 2014 10:04
por Jairo Maia
Olá José,

Não uso Hbnfe, mas em Harbour essa lib é hbdebug.

Acompanhando as mudanças da hbnfe

Enviado: 28 Nov 2014 11:16
por JoséQuintas
Mesmo acrescentando hbdebug.lib continua pedindo a debug.lib
Vou continuando. Talvez o modo compatiblidade use alguma função de debug e precise ajuste no hbmk2.

Acompanhando as mudanças da hbnfe

Enviado: 28 Nov 2014 12:20
por Jairo Maia
José,

Até que resolva, então faça uma cópia da hbdebug.a (ou .Lib se bcc ou msvc) para debug.(?) na sua pasta lib. Pelo menos acho que dá pra continuar.

Acompanhando as mudanças da hbnfe

Enviado: 01 Dez 2014 11:56
por JoséQuintas
Terminei os ajustes para compilar com -w3 -es2 no Harbour.
Durante a compilação com Harbour no esquema -w3 -es2 encontrei erros, por exemplo, de variável que não existe, ou que está com nome errado.
Suponho que estejam apenas usando os fontes como referência.

Aproveitando pra mostrar outra vantagem no -w3 -es2... um dos erros que mostrou foi um "unreachable code" num FOR/NEXT

Código: Selecionar todos

FOR ...
      ...
      EXIT
NEXT
Deu erro porque uma vez que faz o EXIT sempre, o FOR/NEXT é inútil.

Repassando como funcionam as coisas com a Fazenda:

Código: Selecionar todos

// Voce cria um xml

cXml := "<meuxml>conteudo</meuxml>"

// na maioria dos casos assina o XML

cXmlAssinado := AssinaXml( cXml )

// no caso da lote, pra enviar precisa de um lote

cXmlLote := "<lote>blablabla" + cXmlAssinado + "</lote>"

// e na comunicação da fazenda (com SOAP Microsoft) precisa do envelope

cXmlEnvelope := <envelope>blablabla" + cXmlLote + "blablabla</envelope>"

// Então envia e pega o retorno

cXmlRetorno := EnviaEnvelope( cXmlEnvelope )

// E olha o retorno pra ver que decisão tomar

lOk := ( "<status>101</status>" $ cXmlRetorno  )
Basicamente é isso, mas o conteúdo acima foi só pra exemplo.
Não precisa de nenhum arquivo temporário, talvez seja aí onde muitos prefiram apenas se basear na hbnfe e não usá-la diretamente.
No Windows não precisa instalar nada pra comunicação, mas a opção lbcurl é interessante se usar Linux.

Acompanhando as mudanças da hbnfe

Enviado: 01 Dez 2014 12:40
por JoséQuintas
Agora decidindo a próxima etapa.
Por enquanto a opção que vejo é incluir diretamente minha classe na hbnfe.
Dependendo do aplicativo, é só usar a classe e mais nada da hbnfe.

Abaixo a consulta que faço de NFE, CTE e MDFE usando minha classe:

Código: Selecionar todos

      IF Substr( notas->Chave, 21, 2 ) == "55" // nfe
         oSefaz := SefazClass():New()
         cXmlRet := oSefaz:NfeConsulta( notas->Chave, NomeCertificado( notas->Certif ) )
      ELSEIF Substr( notas->Chave, 21, 2 ) == "57" // cte
         oSefaz := SefazClass():New()
         oSefaz:cProjeto := "cte"
         cXmlRet := oSefaz:CteConsulta( notas->Chave, NomeCertificado( notas->Certif ) )
      ELSEIF Substr( notas->Chave, 21, 2 ) == "58" // mdfe
         oSefaz := SefazClass():New()
         oSefaz:cProjeto := "mdfe"
         cXmlRet := oSefaz:MDFEConsulta( notas->Chave, NomeCertificado( notas->Certif ) )
      ENDIF
Acho que qualquer tentativa de integração com a classe da hbnfe só vai complicar, então será melhor deixar separada.
Pra consultar a nota só precisa da chave e do certificado.
::cProjeto - pra identificar se é nfe, cte, mdfe
::cAmbiente - o default é produção. Só precisa alterar se for diferente
::cScan - idem, o default é normal

o método da consulta nfe:

Código: Selecionar todos

METHOD NFEConsulta( cChave, cCertificado ) CLASS SefazClass
   ::cCertificado:= iif( cCertificado == NIL, ::cCertificado, cCertificado )
   ::cVersao     := "2.01"
   ::cUf         := Substr( cChave, 1, 2 )
   ::cServico    := "http://www.portalfiscal.inf.br/nfe/wsdl/NfeConsulta2"
   ::cSoapAction := "http://www.portalfiscal.inf.br/nfe/wsdl/NfeConsulta2"
   ::cWebService := ::GetWebService( UfCodigo( ::cUf ), WSNFECONSULTAPROTOCOLO )
   ::cXmlDados   := ""
   ::cXmlDados   += [<consSitNFe versao="] + ::cVersao + [" xmlns="http://www.portalfiscal.inf.br/nfe">]
   ::cXmlDados   += [<tpAmb>] + ::cAmbiente + [</tpAmb>]
   ::cXmlDados   += [<xServ>CONSULTAR</xServ>]
   ::cXmlDados   += [<chNFe>] + cChave + [</chNFe>]
   ::cXmlDados   += [</consSitNFe>]
   ::XmlSoapPost()
   RETURN ::cXmlRetorno
Explicando:
::cCertificado - se não for recebido certificado, usa o default
::cVersao - é a versão da consulta, não da NFE. Isso na hbnfe é confuso
::cUf - isso faz parte da chave da chave de acesso
::cServico - precisa pro SOAP, detalhe sobre como consultar
::cSoapAction - precisa pro SOAP - detalhe sobre como consultar
::cWebService - precisa pro SOAP - endereço do WebService de consulta
::cXmlDados - é o XML no formato do governo, gerado aqui.

A partir daí, faz a consulta usando ::cXmlSoapPost() e o retorno fica em ::cXmlRetorno
É igual pra tudo.

Código: Selecionar todos

METHOD XmlSoapPost() CLASS SefazClass
   ::XmlSoapEnvelope()
   ::MicrosoftXmlSoapPost()
   RETURN NIL
Como eu disse antes, precisa do envelope ( ::XmlSoapEvenlope() ) pra comunicação SOAP Microsoft ).
Aqui chama a rotina de fazer o envelope, e depois se comunica usando ::MicrosoftXmlSoapPost()

Envelope pra tudo, usando o que foi configurado em NfeConsulta().
Note que o XML da consulta é inserido no meio dele:

Código: Selecionar todos

METHOD XmlSoapEnvelope() CLASS SefazClass
   ::cXmlSoap := ""
   ::cXmlSoap += [<?xml version="1.0" encoding="UTF-8"?>]
   ::cXmlSoap += [<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ]
   ::cXmlSoap +=    [xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">]
   ::cXmlSoap +=    [<soap12:Header>]
   ::cXmlSoap +=       [<] + ::cProjeto + [CabecMsg xmlns="] + ::cServico + [">]
   ::cXmlSoap +=          [<cUF>] + ::cUf + [</cUF>]
   ::cXmlSoap +=          [<versaoDados>] + ::cVersao + [</versaoDados>]
   ::cXmlSoap +=       [</] + ::cProjeto + [CabecMsg>]
   ::cXmlSoap +=    [</soap12:Header>]
   ::cXmlSoap +=    [<soap12:Body>]
   ::cXmlSoap +=       [<] + ::cProjeto + [DadosMsg xmlns="] + ::cServico + [">]
   ::cXmlSoap += ::cXmlDados
   ::cXmlSoap +=    [</] + ::cProjeto + [DadosMsg>]
   ::cXmlSoap +=    [</soap12:Body>]
   ::cXmlSoap += [</soap12:Envelope>]
   RETURN ::cXmlSoap
E finalmente a comunicação com a sefaz pra tudo usando microsoft XML:

Código: Selecionar todos

METHOD MicrosoftXmlSoapPost() CLASS SefazClass
   LOCAL oServer, nCont, cRetorno := "*ERRO*"
   BEGIN SEQUENCE WITH { |e| Break(e) }
      oServer := win_OleCreateObject( "MSXML2.ServerXMLHTTP")
      IF ::cCertificado != NIL
         oServer:setOption( 3, "CURRENT_USER\MY\" + ::cCertificado )
      ENDIF
      oServer:Open( "POST", ::cWebService, .F. )
      oServer:SetRequestHeader( "SOAPAction", ::cSoapAction )
      oServer:SetRequestHeader( "Content-Type", "application/soap+xml; charset=utf-8" )
      oServer:Send( ::cXmlSoap )
      oServer:WaitForResponse( 500 )
      cRetorno := oServer:ResponseBody
   ENDSEQUENCE
   IF ValType( cRetorno ) == "C"
      ::cXmlRetorno := cRetorno
   ELSEIF cRetorno == NIL
      ::cXmlRetorno := "*ERRO*"
   ELSE
      ::cXmlRetorno := ""
      FOR nCont = 1 TO Len( cRetorno )
         ::cXmlRetorno += Chr( cRetorno[ nCont ] )
      NEXT
   ENDIF
   RETURN NIL
Isto confunde muito, precisa ou não precisa no XML?

[<?xml version="1.0" encoding="UTF-8"?>]

Na prática isso não faz parte do XML, mas indica a "codepage" do arquivo.
Para o projeto, ao colocar no início do envelope já vale pra tudo que tem dentro.
Talvez o problema de muitas assinaturas seja porque o pessoal tem mania de incluir isso no XML mesmo quando não é UTF8.

Então... por enquanto não vejo vantagem em embutir isto dentro da classe hbnfe, porque pode complicar.
Mas dá pra ajustar a hbnfe pra usar a classe.

Se considerar todas as comunicações que tem dentro da hbnfe, no minimo vai eliminar todas as montagens dos XMLs de SOAP.
O método acima de consulta, elimina a montagem do XML de consulta.
E os webservices na classe, eliminam os webservices da hbnfe.

Não comparei com a NFE 3.10, mas acho que não houve alteração na consulta.
Uma opção seria criar a nova como NfeConsulta310() até que fique por definitivo, caso altere.
Ou seja, a classe pra pronta pra os projetos atuais, e para os próximos.

Ao integrar com a hbnfe vou fazer gradativo, pra comparar/acrescentar webservices/métodos que faltam, e pra hbnfe continuar funcionando como sempre foi.

Acredito que, por mais que façam diferente da hbnfe nos aplicativos, pelo menos essa classe vão usar sem alterações.

Aqui uso essa classe, e os temporários deixo no MySql do meu servidor.
O cliente faz lá, e qualquer coisa vejo aqui no meu servidor se deu algo errado.

Acompanhando as mudanças da hbnfe

Enviado: 02 Dez 2014 10:10
por Itamar M. Lins Jr.
Parabéns José Quintas, pela iniciativa, agora quem sabe eu possa ajudar e ou usar essa lib, já que vc usa o Harbour como padrão.
O Fernando, é muito inteligente, fez essa lib há algum tempo, mas eu não tinha retorno de algumas perguntas. Veja que é só vc por enquanto que está usando ela com o Harbour, assim que der um sinal verde testarei ela novamente, por enquanto eu uso as coisas do projeto ACBr.

Eu conversei com o Stanis via email, e ele tem também alguns exemplos da HBQT, show de bola os exemplos de uso da HBQT ele fez em 2011 +- agora é que estou chegando a entender a lógica dele... lendo muito para entender melhor, mas eu sou uma pessoa muito ocupada, casa, filhos etc..., as vezes o tempo que tenho é só para atualizar alguma coisa, não dá tempo de colocar mais coisas para ajudar a comunidade [x]Harbour.

A mesma coisa vc poderá fazer com o MRBoleto, caso precise de atualizações, que é um bom projeto também.

Chega de projetos com códigos privativos, veja que até a M$ está mudando a forma de pensar.

Saudações,
Itamar M. Lins Jr.