Nfse para São Paulo e Foz do Iguaçu, funcionando perfeitamente com a sua classe. Hj estão separadas, mas estava pensando em juntá-las, depois ir acrescentando outro municípios. Pensei em usar o código do município como seletor e também os métodos (envio, cancelamento, consulta) poderia ser um unico método (pe executa) pasando somente o serviço, mas esbarrei na minha ignorância, Juntei os 2, neste arquivo abaixo, se puder dar a sua opinião de como posso proceder agradeço
Código: Selecionar todos
/*
ZE_SPEDSefazClass1 - Rotinas pra comunicação com SEFAZ
José Quintas
*/
#include "hbclass.ch"
*#define WS_NFE_STATUSSERVICO 17 /// não descobri onde usar
#define WS_CANCELAMENTONFE 1
#define WS_ENVIOLOTERPS 2
#define WS_ENVIORPS 3 /// acrescentei
#define WS_CONSULTARPS 4 /// acrescentei
#define WS_AMBIENTE_HOMOLOGACAO "2" /// sp, foz não tem mais o ambiente de homologação
#define WS_AMBIENTE_PRODUCAO "1"
#ifndef XML_UTF8
#define XML_UTF8 [<?xml version="1.0" encoding="UTF-8"?>]
#endif
CREATE CLASS NfseClasse //// mudei nome pois estava conflitando com a sefazclass
/* configuração */
VAR cAmbiente INIT WS_AMBIENTE_PRODUCAO
VAR cUF INIT "SP" // Modificada conforme método
VAR cCertificado INIT "" // Nome do certificado
VAR nTempoEspera INIT 7 // intervalo entre envia lote e consulta recibo
/* XMLs de cada etapa */
VAR cXmlDocumento INIT "" // O documento oficial, com ou sem assinatura, depende do documento
VAR cXmlEnvio INIT "" // usado pra criar/complementar XML do documento
VAR cXmlSoap INIT "" // XML completo enviado pra Sefaz, incluindo informações do envelope
VAR cXmlRetorno INIT "Erro Desconhecido" // Retorno do webservice e/ou rotina
VAR cXmlProtocolo INIT "" // XML protocolo (obtido no consulta recibo e/ou envio de outros docs)
VAR cXmlAutorizado INIT "" // XML autorizado, caso tudo ocorra sem problemas
VAR cStatus INIT Space(3) // Status obtido da resposta final da Fazenda
/* uso interno */
VAR cSoapService INIT "" // webservice Serviço
VAR cSoapAction INIT "" // webservice Action
VAR cSoapURL INIT "" // webservice Endereço
*** acrescentei
VAR cPassword INIT "" // Senha de arquivo PFX
VAR cMotivo INIT "" // Motivo constante no Recibo
VAR nCodigoMunicipio INIT 3550308 // São Paulo
METHOD EnvioLoteRPS( cXml, cCertificado, cAmbiente )
***** acrescentei
METHOD EnvioRPS( cXml, cCertificado, cAmbiente )
METHOD CancelamentoRPS( cXml, cCertificado, cAmbiente )
METHOD ConsultaRPS( cXml, cCertificado, cAmbiente )
/* Uso interno */
METHOD Setup( cCertificado, cAmbiente, nWsServico )
METHOD XmlSoapEnvelope()
METHOD XmlSoapPost()
METHOD MicrosoftXmlSoapPost()
***** acrescentei
METHOD AssinaXml(cXml, lComUri)
METHOD Gera_Chave_SHA1(cString)
ENDCLASS
** alterei foz máximo 20 rps por lote
METHOD EnvioLoteRPS( cXml, cCertificado, cAmbiente ) CLASS NfseClasse
::Setup( cCertificado, cAmbiente, WS_ENVIOLOTERPS )
::cXmlEnvio := ::AssinaXml( cXml, .F. )
::cXmlEnvio := ::cXmlDocumento
::XmlSoapPost()
RETURN ::cXmlRetorno
** acrescentei
METHOD EnvioRPS( cXml, cCertificado, cAmbiente ) CLASS NfseClasse
::Setup( cCertificado, cAmbiente, WS_ENVIORPS )
::cXmlEnvio := ::AssinaXml( cXml, .F. )
::cXmlEnvio := ::cXmlDocumento
::XmlSoapPost()
RETURN ::cXmlRetorno
** acrescentei
METHOD CancelamentoRPS( cXml, cCertificado, cAmbiente ) CLASS NfseClasse
::Setup( cCertificado, cAmbiente, WS_CANCELAMENTONFE )
::cXmlEnvio := ::AssinaXml( cXml, .F. )
::cXmlEnvio := ::cXmlDocumento
::XmlSoapPost()
RETURN ::cXmlRetorno
** acrescentei
METHOD ConsultaRPS( cXml, cCertificado, cAmbiente ) CLASS NfseClasse
::Setup( cCertificado, cAmbiente, WS_CONSULTARPS )
::cXmlEnvio := ::AssinaXml( cXml, .F. )
::cXmlEnvio := ::cXmlDocumento
::XmlSoapPost()
RETURN ::cXmlRetorno
METHOD Setup( cCertificado, cAmbiente, nWsServico ) CLASS NfseClasse
LOCAL nPos, aSoapList := { ;
{ WS_CANCELAMENTONFE, "CancelamentoNFe", "http://www.prefeitura.sp.gov.br/nfe/ws/cancelamentoNFe", "https://nfe.prefeitura.sp.gov.br/ws/lotenfe.asmx" }, ;
{ WS_ENVIOLOTERPS , "EnvioLoteRPS" , "http://www.prefeitura.sp.gov.br/nfe/ws/envioLoteRPS" , "https://nfe.prefeitura.sp.gov.br/ws/lotenfe.asmx" }, ;
{ WS_ENVIORPS , "EnvioRPS" , "http://www.prefeitura.sp.gov.br/nfe/ws/envioRPS" , "https://nfe.prefeitura.sp.gov.br/ws/lotenfe.asmx" } }
/* foz
LOCAL nPos, aSoapList := { ;
{ WS_CANCELAMENTONFE, "CancelamentoNFSE" , "http://tempuri.org/CancelamentoNFSE" , "http://nfse.pmfi.pr.gov.br/nfsews/nfse.asmx" }, ;
{ WS_ENVIOLOTERPS , "EnviaLotesParaProcessamento", "http://tempuri.org/EnviaLotesParaProcessamento", "http://nfse.pmfi.pr.gov.br/nfsews/nfse.asmx" }, ;
{ WS_ENVIORPS , "RecebeLoteRPS" , "http://tempuri.org/RecebeLoteRPS" , "http://nfse.pmfi.pr.gov.br/nfsews/nfse.asmx" }, ;
{ WS_CONSULTARPS , "ConsultarLoteRPS" , "http://tempuri.org/ConsultarLoteRPS" , "http://nfse.pmfi.pr.gov.br/nfsews/nfse.asmx" } }
*/
::cCertificado := iif( cCertificado == Nil, ::cCertificado, cCertificado )
::cAmbiente := iif( cAmbiente == Nil, ::cAmbiente, cAmbiente )
IF nWsServico == Nil
RETURN Nil
ENDIF
IF ( nPos := hb_AScan( aSoapList, { | oElement | oElement[ 1 ] == nWsServico } ) ) != 0
::cSoapService := aSoapList[ nPos, 2 ]
::cSoapAction := aSoapList[ nPos, 3 ]
::cSoapURL := aSoapList[ nPos, 4 ]
ENDIF
RETURN Nil
METHOD XmlSoapPost() CLASS NfseClasse
DO CASE
CASE Empty( ::cSoapURL )
::cXmlRetorno := "Erro SOAP: Não há endereço de webservice"
RETURN Nil
CASE Empty( ::cSoapService )
::cXmlRetorno := "Erro SOAP: Não há nome do serviço"
RETURN Nil
CASE Empty( ::cSoapAction )
::cXmlRetorno := "Erro SOAP: Não há endereço de SOAP Action"
RETURN Nil
ENDCASE
::XmlSoapEnvelope()
::MicrosoftXmlSoapPost()
IF Upper( Left( ::cXmlRetorno, 4 ) ) == "ERRO"
RETURN Nil
ENDIF
RETURN Nil
METHOD XmlsoapEnvelope() CLASS NfseClasse /// para sp
::cXmlsoap := XML_UTF8
::cXmlsoap += [<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ]
::cXmlsoap += [xmlns:xsd="http://www.w3.org/2001/XMLSchema" ]
::cXmlsoap += [xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">]
::cXmlSoap += [<soap12:Body>]
::cXmlSoap += [<] + ::cSoapService + [Request xmlns="http://www.prefeitura.sp.gov.br/nfe">]
::cXmlSoap += [<VersaoSchema>1</VersaoSchema>]
::cXmlSoap += [<MensagemXML>]
::cXmlSoap += "<![CDATA[ " + ::cXmlEnvio + " ]]>"
::cXmlSoap += [</MensagemXML>]
::cXmlSoap += [</] + ::cSoapService + [Request>]
::cXmlSoap += [</soap12:Body>]
::cXmlSoap += [</soap12:Envelope>]
RETURN Nil
/** alterei
METHOD XmlsoapEnvelope() CLASS NfseClasse /// proprio para foz
::cXmlsoap := XML_UTF8
::cXmlsoap += [<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ]
::cXmlsoap += [xmlns:xsd="http://www.w3.org/2001/XMLSchema" ]
::cXmlsoap += [xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">]
::cXmlSoap += [<soap12:Body>]
::cXmlSoap += [<] + ::cSoapService + [ xmlns="http://tempuri.org/">]
::cXmlSoap += [<xml>] + ::cXmlEnvio + [</xml>]
::cXmlSoap += [</] + ::cSoapService + [>]
::cXmlSoap += [</soap12:Body>]
::cXmlSoap += [</soap12:Envelope>]
RETURN Nil
*/
METHOD MicrosoftXmlSoapPost() CLASS NfseClasse
LOCAL oServer, nCont, cRetorno
LOCAL cSoapAction
cSoapAction := ::cSoapAction
BEGIN SEQUENCE WITH __BreakBlock()
::cXmlRetorno := "Erro: Criando objeto MSXML2.ServerXMLHTTP"
oServer := win_OleCreateObject( "MSXML2.ServerXMLHTTP" )
::cXmlRetorno := "Erro: No uso do objeto MSXML2.ServerXmlHTTP"
IF ::cCertificado != Nil
oServer:setOption( 3, "CURRENT_USER\MY\" + ::cCertificado )
ENDIF
::cXmlRetorno := "Erro: Na conexão com webservice " + ::cSoapURL
oServer:Open( "POST", ::cSoapURL, .F. )
oServer:SetRequestHeader( "SOAPAction", cSoapAction )
oServer:SetRequestHeader( "Content-Type", "application/soap+xml; charset=utf-8" )
oServer:Send( ::cXmlSoap )
oServer:WaitForResponse( 500 )
cRetorno := oServer:ResponseBody
IF ValType( cRetorno ) == "C"
::cXmlRetorno := cRetorno
ELSEIF cRetorno == Nil
::cXmlRetorno := "Erro: Sem retorno do webservice"
ELSE
::cXmlRetorno := ""
FOR nCont = 1 TO Len( cRetorno )
::cXmlRetorno += Chr( cRetorno[ nCont ] )
NEXT
ENDIF
ENDSEQUENCE
IF "<soap:Body>" $ ::cXmlRetorno .AND. "</soap:Body>" $ ::cXmlRetorno
::cXmlRetorno := XmlNode( ::cXmlRetorno, "soap:Body" ) // hb_UTF8ToStr()
ELSEIF "<soapenv:Body>" $ ::cXmlRetorno .AND. "</soapenv:Body>" $ ::cXmlRetorno
::cXmlRetorno := XmlNode( ::cXmlRetorno, "soapenv:Body" ) // hb_UTF8ToStr()
ELSE
::cXmlRetorno := "Erro SOAP: XML retorno não contém soapenv:Body " + ::cXmlRetorno
ENDIF
RETURN Nil
**************** acrescentei
METHOD AssinaXml(cXml, lComUri) CLASS NfseClasse
hb_Default( @lComURI, .F. )
::cXmlDocumento:= cXml
::cXmlRetorno := CapicomAssinaXml( @::cXmlDocumento, ::cCertificado,,::cPassword, lComUri )
IF ::cXmlRetorno != "OK"
::cStatus := "999"
::cMotivo := ::cXmlRetorno
::cXmlRetorno := [<erro text="] + "*erro* " + ::cXmlRetorno + ["</erro>]
ENDIF
RETURN ::cXmlRetorno
METHOD Gera_Chave_SHA1(cString) Class NfseClasse
Local nHandle:= Fcreate([StringParaAssinar.txt]), cRet:= []
* Fwrite(nHandle, ::ohbNFe:cSerialCert + hb_OsNewLine() + cString)
Fwrite(nHandle, Upper([4b8db3b9d22a50b5]) + hb_OsNewLine() + cString)
Fclose(nHandle)
ShellExecute(0, [open], [AssinaRPS.EXE],,, 1)
cRet:= Hb_Memoread([StringAssinada.txt])
cRet:= Strtran(cRet, CHR(13), [])
cRet:= Strtran(cRet, CHR(10), [])
Ferase([StringParaAssinar.txt])
Ferase([StringAssinada.txt])
Return(cRet)