NFSE.prg
// ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
// ³ NFSE.PRG ³
// ³ NFS-e Gera Nota Fiscal de Servi‡o Eletr“nica ³
// ³ VIA PROGRAMA WSOFT ³
// ³ 29/04/2016 ³
// ³ EMC ³
// ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
#include "common.ch"
#include "hbclass.ch"
#include "hbnfe.ch"
#include "wsmode.ch"
#include "wsnatop.ch"
#include "wscalc_f.ch"
#include "wsfile.ch"
#include "wsecf.ch"
#include "wsged.ch"
#include "inkey.ch"
#include "fileio.ch"
#include "directry.ch"
#include "dll.ch"
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//////////
CLASS NFSE
//////////
DATA oFuncoes INIT hbNFeFuncoes()
// DATA oCTe_GERAIS INIT oCTe_GERAIS()
DATA ohbNFe
DATA oSigner
DATA Xml
// Cabecalho
DATA cab_CodCidade
DATA cab_CPFCNPJRemetente
DATA cab_RazaoSocialRemetente
DATA cab_dtInicio
DATA cab_dtFim
DATA cab_QtdRPS
DATA cab_ValorTotalServicos
DATA cab_ValorTotalDeducoes
DATA cab_Versao Init 1
DATA cab_MetodoEnvio Init 'WS'
DATA cab_VersaoComponente Init '6.0004'
// Rps
DATA rps_InscricaoMunicipalPrestador
DATA rps_RazaoSocialPrestador
DATA rps_TipoRPS Init 'RPS'
DATA rps_SerieRPS Init 'NF'
DATA rps_NumeroRPS
DATA rps_DataEmissaoRPS
DATA rps_SituacaoRPS
DATA rps_SerieRPSSubstituido
DATA rps_NumeroRPSSubstituido
DATA rps_NumeroNFSeSubstituida
DATA rps_DataEmissaoNFSeSubstituida Init CTOD('01/01/1900')
DATA rps_SeriePrestacao Init '99'
DATA rps_InscricaoMunicipalTomador
DATA rps_CPFCNPJTomador
DATA rps_RazaoSocialTomador
DATA rps_DocTomadorEstrangeiro
DATA rps_TipoLogradouroTomador
DATA rps_LogradouroTomador
DATA rps_NumeroEnderecoTomador
DATA rps_ComplementoEnderecoTomador
DATA rps_TipoBairroTomador
DATA rps_BairroTomador
DATA rps_CidadeTomador
DATA rps_CidadeTomadorDescricao
DATA rps_CEPTomador
DATA rps_EmailTomador
DATA rps_CodigoAtividade
DATA rps_AliquotaAtividade
DATA rps_TipoRecolhimento
DATA rps_MunicipioPrestacao
DATA rps_MunicipioPrestacaoDescricao
DATA rps_Operacao
DATA rps_Tributacao
DATA rps_ValorPIS
DATA rps_ValorCOFINS
DATA rps_ValorINSS
DATA rps_ValorIR
DATA rps_ValorCSLL
DATA rps_AliquotaPIS
DATA rps_AliquotaCOFINS
DATA rps_AliquotaINSS
DATA rps_AliquotaIR
DATA rps_AliquotaCSLL
DATA rps_DescricaoRPS
DATA rps_DDDPrestador
DATA rps_TelefonePrestador
DATA rps_DDDTomador
DATA rps_TelefoneTomador
DATA rps_MotCancelamento
DATA rps_CPFCNPJIntermediario
// V10.0.K1292
DATA cValorCargaTributaria
DATA cPercentualCargaTributaria
// V10.0.K1292
// Registros de Itens da RPS
DATA Itens_DiscriminacaoServico
DATA Itens_Quantidade
DATA Itens_ValorUnitario
DATA Itens_ValorTotal
DATA Itens_Tributavel
// Registro das Deducoes
DATA Deducao_DeducaoPor
DATA Deducao_TipoDeducao
DATA Deducao_CPFCNPJReferencia
DATA Deducao_NumeroNFReferencia
DATA Deducao_ValorTotalReferencia
DATA Deducao_PercentualDeduzir
DATA Deducao_ValorDeduzir
DATA numero_nota
DATA codigo_verificacao
DATA motivo
METHOD Registro_Cabecalho()
METHOD Registro_RPS()
METHOD Registro_Itens_RPS(lABRE,lFECHA)
METHOD Registro_Deducao_RPS(lABRE,lFECHA)
METHOD Assina_XML()
METHOD Finaliza_RPS()
METHOD Gera_Chave_SHA1()
METHOD Gera_Chave_SHA1_Cancelamento()
METHOD DataToYYYY_MM_DD(dDAT,lTIME)
METHOD DataToYYYYMMDD(dDAT)
METHOD LinkWebService(cServ)
METHOD ComunicaWebService(cMETHOD)
METHOD ctPegaCNCertificado()
METHOD LeRetorno(cRET)
METHOD CancelaNFSe()
METHOD ValidaXML()
ENDCLASS
////////
// EOC NFSE()
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//////////////////////////////////////
METHOD Registro_Cabecalho() Class NFSE
//////////////////////////////////////
LOCAL aRETORNO:=HASH()
LOCAL cXML:='', cARQ:=''
LOCAL nHandle
aRETORNO['STATUS']:=.F.
aRETORNO['MSG']:=''
IF ::cab_CodCidade=NIL .OR. ::cab_CodCidade<=0
aRETORNO['MSG']:='Favor informar o código do município'
ENDIF
IF ::cab_CPFCNPJRemetente=NIL .OR. EMPTY(::cab_CPFCNPJRemetente)
aRETORNO['MSG']:='Favor informar o CPF / CNPJ do Remetente'
ENDIF
IF ::cab_RazaoSocialRemetente=NIL .OR. EMPTY(::cab_RazaoSocialRemetente)
aRETORNO['MSG']:='Favor informar a razão social do Remetente'
ENDIF
IF ::cab_dtInicio=NIL .OR. DAY(::cab_dtInicio)<=0
aRETORNO['MSG']:='Favor informar a data inicial da remessa'
ENDIF
IF ::cab_dtFim=NIL .OR. DAY(::cab_dtFim)<=0
aRETORNO['MSG']:='Favor informar a data final da remessa'
ENDIF
IF ::cab_ValorTotalServicos=NIL
::cab_ValorTotalServicos:=0
ENDIF
IF ::cab_ValorTotalDeducoes=NIL
::cab_ValorTotalDeducoes:=0
ENDIF
IF !EMPTY(aRETORNO['MSG'])
RETURN(aRETORNO)
ENDIF
cXML+='<PedidoEnvioLoteRPS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.prefeitura.sp.gov.br/nfe">'
cXML+= '<Cabecalho Versao="1" xmlns="">'
cXML+= '<CPFCNPJRemetente><CNPJ>'+ALLTRIM(::cab_CPFCNPJRemetente)+'</CNPJ></CPFCNPJRemetente>'
cXML+= '<transacao>false</transacao>'
cXML+= '<dtInicio>'+::DataToYYYY_MM_DD(::cab_dtInicio)+'</dtInicio>'
cXML+= '<dtFim>'+::DataToYYYY_MM_DD(::cab_dtFim)+'</dtFim>'
cXML+= '<QtdRPS>'+ALLTRIM(STR(::cab_QtdRPS))+'</QtdRPS>'
cXML+= '<ValorTotalServicos>'+ALLTRIM(STR(::cab_ValorTotalServicos))+'</ValorTotalServicos>'
cXML+= '<ValorTotalDeducoes>'+ALLTRIM(STR(::cab_ValorTotalDeducoes))+'</ValorTotalDeducoes>'
cXML+= '</Cabecalho>'
cARQ:=::ohbNFe:pastaEnvRes+'\NFSe'+ALLTRIM(::cab_CPFCNPJRemetente)+DTOS(DATE())+STRTRAN(LEFT(TIME(),8),':')+'.xml'
nHandle := FCREATE(cARQ)
FWRITE(nHandle, cXML)
FCLOSE( nHandle )
::XML := cARQ
aRETORNO['STATUS']:=.T.
aRETORNO['XML']:=cARQ
aRETORNO['MSG']:='XML criado em '+cARQ
RETURN(aRETORNO)
////////////////
// EOM Registro_Cabecalho()
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
////////////////////////////////
METHOD Registro_RPS() Class NFSE
////////////////////////////////
LOCAL aRETORNO:=HASH()
LOCAL cXML:='', cARQ:=''
LOCAL nHandle
aRETORNO['STATUS']:=.F.
aRETORNO['MSG']:=''
IF ::Xml=NIL .OR. EMPTY(::Xml)
aRETORNO['MSG']:='Arquivo XML com o registro do cabeçalho não informado.'
ENDIF
IF ::rps_InscricaoMunicipalPrestador=NIL .OR. EMPTY(::rps_InscricaoMunicipalPrestador)
aRETORNO['MSG']:='Favor Informar a Inscrição Municipal do Prestador. Verificar regra de preenchimento do campo no Anexo 03.'
ENDIF
IF ::rps_RazaoSocialPrestador=NIL .OR. EMPTY(::rps_RazaoSocialPrestador)
aRETORNO['MSG']:='Favor Informar a Razão Social do Prestador.'
ENDIF
IF ::rps_TipoRPS=NIL .OR. EMPTY(::rps_TipoRPS)
aRETORNO['MSG']:='Favor Informar o Tipo de RPS Padrão "RPS".'
ENDIF
IF ::rps_SerieRPS=NIL .OR. EMPTY(::rps_SerieRPS)
aRETORNO['MSG']:='Favor Informar a Série do RPS - Padrão "NF".'
ENDIF
IF ::rps_NumeroRPS=NIL .OR. ::rps_NumeroRPS<=0
aRETORNO['MSG']:='Favor Informar o Número da RPS.'
ENDIF
IF ::rps_NumeroRPS=NIL .OR. ::rps_NumeroRPS<=0
aRETORNO['MSG']:='Favor Informar o Número da RPS.'
ENDIF
IF ::rps_DataEmissaoRPS=NIL .OR. DAY(::rps_DataEmissaoRPS)<=0
aRETORNO['MSG']:='Favor Informar o Data de Emissão da RPS.'
ENDIF
IF ::rps_SituacaoRPS=NIL .OR. EMPTY(::rps_SituacaoRPS)
aRETORNO['MSG']:='Favor Informar a Situação da RPS - "N"-Normal, "C"-Cancelada.'
ENDIF
IF ::rps_SerieRPSSubstituido=NIL
::rps_SerieRPSSubstituido:=''
ENDIF
IF ::rps_SituacaoRPS=NIL .OR. EMPTY(::rps_SituacaoRPS)
aRETORNO['MSG']:='Favor Informar a Situação da RPS - "N"-Normal, "C"-Cancelada.'
ENDIF
IF ::rps_NumeroRPSSubstituido=NIL
::rps_NumeroRPSSubstituido:=0
ENDIF
IF ::rps_NumeroNFSeSubstituida=NIL
::rps_NumeroNFSeSubstituida:=0
ENDIF
IF ::rps_DataEmissaoNFSeSubstituida=NIL .OR. DAY(::rps_DataEmissaoNFSeSubstituida)<=0
aRETORNO['MSG']:='Favor Informar a Data de emissão da NFSe Formato= AAAA-MM-DD. Se não for substituto preencher com "01/01/1900".'
ENDIF
IF ::rps_SeriePrestacao=NIL .OR. EMPTY(::rps_SeriePrestacao)
aRETORNO['MSG']:='Favor Informar o Número do equipamento emissor do RPS ou série de prestação. Caso não utilize a série, preencha o campo com o valor ‘99’ que indica modelo único. Caso queira utilizar o campo série para indicar o número do equipamento emissor do RPS deve-se solicitar liberação da prefeitura.'
ENDIF
IF ::rps_InscricaoMunicipalTomador=NIL .OR. EMPTY(::rps_InscricaoMunicipalTomador)
aRETORNO['MSG']:='Favor Informar a Inscrição Municipal do Tomador. Caso o tomador não for do municipio não preencher, caso o tomador for do município preencher com a Inscrição Municipal formatada Seguindo Anexo 03.'
ENDIF
IF ::rps_CPFCNPJTomador=NIL .OR. EMPTY(::rps_CPFCNPJTomador)
aRETORNO['MSG']:='Favor Informar o CPF ou CNPJ do Tomador. Ex: "00000000000191"'
ENDIF
IF ::rps_RazaoSocialTomador=NIL .OR. EMPTY(::rps_RazaoSocialTomador)
aRETORNO['MSG']:='Favor Informar a Razão Social do Tomador'
ENDIF
IF ::rps_DocTomadorEstrangeiro=NIL
::rps_DocTomadorEstrangeiro:=''
ENDIF
IF ::rps_TipoLogradouroTomador=NIL .OR. EMPTY(::rps_TipoLogradouroTomador)
aRETORNO['MSG']:='Favor Informar o Tipo de Logradouro do Tomador. Campo de preenchimento livre. Verificar exemplos no anexo 04.'
ENDIF
IF ::rps_LogradouroTomador=NIL .OR. EMPTY(::rps_LogradouroTomador)
aRETORNO['MSG']:='Favor Informar o Logradouro do Tomador.'
ENDIF
IF ::rps_NumeroEnderecoTomador=NIL .OR. EMPTY(::rps_NumeroEnderecoTomador)
aRETORNO['MSG']:='Favor Informar o Numero de Endereço do Tomador.'
ENDIF
IF ::rps_ComplementoEnderecoTomador=NIL
::rps_ComplementoEnderecoTomador:=''
ENDIF
IF ::rps_TipoBairroTomador=NIL .OR. EMPTY(::rps_TipoBairroTomador)
aRETORNO['MSG']:='Favor Informar o Tipo de Bairro do Tomador . Campo de preenchimento livre. Verificar exemplos no Anexo 05.'
ENDIF
IF ::rps_BairroTomador=NIL .OR. EMPTY(::rps_BairroTomador)
aRETORNO['MSG']:='Favor Informar o Bairro do Tomador.'
ENDIF
IF ::rps_CidadeTomador=NIL .OR. ::rps_CidadeTomador<=0
aRETORNO['MSG']:='Favor Informar o Código da Cidade do Tomador padrão SIAFI. (Confira o nome da cidade no cadastro do cliente)'
ENDIF
IF ::rps_CidadeTomadorDescricao=NIL .OR. EMPTY(::rps_CidadeTomadorDescricao)
aRETORNO['MSG']:='Favor Informar o Nome da Cidade do Tomador.'
ENDIF
IF ::rps_CEPTomador=NIL .OR. EMPTY(::rps_CEPTomador)
aRETORNO['MSG']:='Favor Informar o CEP do Tomador Ex: "37900000".'
ENDIF
IF ::rps_EmailTomador=NIL .OR. EMPTY(::rps_EmailTomador)
::rps_EmailTomador:='-'
ENDIF
IF ::rps_CodigoAtividade=NIL .OR. EMPTY(::rps_CodigoAtividade)
aRETORNO['MSG']:='Favor Informar o Código da Atividade da RPS. (Confira o codigo CNAE no cadastro do cliente)'
ENDIF
IF ::rps_AliquotaAtividade=NIL
::rps_AliquotaAtividade:=0
ENDIF
IF ::rps_TipoRecolhimento=NIL .OR. EMPTY(::rps_TipoRecolhimento)
aRETORNO['MSG']:='Favor Informar o Tipo de Recolhimento - "A" – A Receber, "R" - Retido na Fonte.'
ENDIF
IF ::rps_MunicipioPrestacao=NIL .OR. ::rps_MunicipioPrestacao<=0
aRETORNO['MSG']:='Favor Informar o Código do Município de Prestação – Padrão SIAFI.'
ENDIF
IF ::rps_MunicipioPrestacao=NIL .OR. ::rps_MunicipioPrestacao<=0
aRETORNO['MSG']:='Favor Informar o Código do Município de Prestação – Padrão SIAFI.'
ENDIF
IF ::rps_MunicipioPrestacaoDescricao=NIL .OR. EMPTY(::rps_MunicipioPrestacaoDescricao)
aRETORNO['MSG']:='Favor Informar o Município de Prestação do Serviço.'
ENDIF
IF ::rps_Operacao=NIL .OR. EMPTY(::rps_Operacao)
aRETORNO['MSG']:='Favor Informar a Operação - "A"-Sem Dedução, "B"-Com Dedução/Materiais, "C" - Imune/Isenta de ISSQN, "D" - Devolução/Simples Remessa, "J" - Intemediação.'
ENDIF
IF ::rps_Tributacao=NIL .OR. EMPTY(::rps_Tributacao)
aRETORNO['MSG']:='Favor Informar a Tributação: C - Isenta de ISS, E - Não Incidência no Município, F - Imune, K - Exigibilidd Susp.Dec.J/Proc.A, N - Não Tributável, T – Tributável, G - Tributável Fixo, H - Tributável S.N., M - Micro Empreendedor Individual (MEI).'
ENDIF
IF ::rps_ValorPIS=NIL
::rps_ValorPIS:=0.00
ENDIF
IF ::rps_ValorCOFINS=NIL
::rps_ValorCOFINS:=0.00
ENDIF
IF ::rps_ValorINSS=NIL
::rps_ValorINSS:=0.00
ENDIF
IF ::rps_ValorIR=NIL
::rps_ValorIR:=0.00
ENDIF
IF ::rps_ValorCSLL=NIL
::rps_ValorCSLL:=0.00
ENDIF
IF ::rps_AliquotaPIS=NIL
::rps_AliquotaPIS:=0.00
ENDIF
IF ::rps_AliquotaCOFINS=NIL
::rps_AliquotaCOFINS:=0.00
ENDIF
IF ::rps_AliquotaINSS=NIL
::rps_AliquotaINSS:=0.00
ENDIF
IF ::rps_AliquotaIR=NIL
::rps_AliquotaIR:=0.00
ENDIF
IF ::rps_AliquotaCSLL=NIL
::rps_AliquotaCSLL:=0.00
ENDIF
IF ::rps_DescricaoRPS=NIL
::rps_DescricaoRPS:=''
ENDIF
IF ::rps_DDDPrestador=NIL
::rps_DDDPrestador:=''
ENDIF
IF ::rps_TelefonePrestador=NIL
::rps_TelefonePrestador:=''
ENDIF
IF ::rps_DDDTomador=NIL
::rps_DDDTomador:=''
ENDIF
IF ::rps_TelefoneTomador=NIL
::rps_TelefoneTomador:=''
ENDIF
IF ::rps_MotCancelamento=NIL
::rps_MotCancelamento:=''
ENDIF
IF ::rps_CPFCNPJIntermediario=NIL
::rps_CPFCNPJIntermediario:=''
ENDIF
IF !EMPTY(aRETORNO['MSG'])
RETURN(aRETORNO)
ENDIF
cXML:=MEMOREAD(::Xml)
FERASE(::Xml)
cAssinatura:=::Gera_Chave_SHA1()
cXML+= '<RPS xmlns="">' //'<RPS Id="rps:2">'
cXML+= '<Assinatura>'+cAssinatura+'</Assinatura>'
cXML+= '<ChaveRPS>'
cXML+= '<InscricaoPrestador>'+ALLTRIM(::rps_InscricaoMunicipalPrestador)+'</InscricaoPrestador>'
cXML+= '<SerieRPS>'+ALLTRIM(::rps_SerieRPS)+'</SerieRPS>'
cXML+= '<NumeroRPS>'+ALLTRIM(STR(::rps_NumeroRPS))+'</NumeroRPS>'
cXML+= '</ChaveRPS>'
cXML+= '<TipoRPS>'+ALLTRIM(::rps_TipoRPS)+'</TipoRPS>'
cXML+= '<DataEmissao>'+::DataToYYYY_MM_DD(::rps_DataEmissaoRPS,.F.)+'</DataEmissao>'
cXML+= '<StatusRPS>'+ALLTRIM(::rps_SituacaoRPS)+'</StatusRPS>'
cXML+= '<TributacaoRPS>'+ALLTRIM(::rps_Tributacao)+'</TributacaoRPS>'
cXML+= '<ValorServicos>'+ALLTRIM(STR(::cab_ValorTotalServicos))+'</ValorServicos>'
cXML+= '<ValorDeducoes>'+ALLTRIM(STR(::cab_ValorTotalDeducoes))+'</ValorDeducoes>'
cXML+= '<CodigoServico>'+::rps_CodigoAtividade+'</CodigoServico>'
cXML+= '<AliquotaServicos>'+ALLTRIM(STR(::rps_AliquotaAtividade))+'</AliquotaServicos>'
cXML+= '<ISSRetido>false</ISSRetido>'
// V10.0.K1608
// cXML+= '<CPFCNPJTomador><CPF>'+ALLTRIM(::rps_CPFCNPJTomador)+'</CPF></CPFCNPJTomador>'
IF LEN( ALLTRIM(::rps_CPFCNPJTomador) ) == 14
cXML+= '<CPFCNPJTomador><CNPJ>'+ALLTRIM(::rps_CPFCNPJTomador)+'</CNPJ></CPFCNPJTomador>'
ELSE
cXML+= '<CPFCNPJTomador><CPF>'+ALLTRIM(::rps_CPFCNPJTomador)+'</CPF></CPFCNPJTomador>'
ENDIF
// V10.0.K1608
cXML+= '<RazaoSocialTomador>'+ALLTRIM(::rps_RazaoSocialTomador)+'</RazaoSocialTomador>'
cXML+= '<EnderecoTomador>'
cXML+= '<TipoLogradouro>'+ALLTRIM(::rps_TipoLogradouroTomador)+'</TipoLogradouro>'
cXML+= '<Logradouro>'+ALLTRIM(::oFuncoes:parseEncode(::rps_LogradouroTomador))+'</Logradouro>'
cXML+= '<NumeroEndereco>'+ALLTRIM(::rps_NumeroEnderecoTomador)+'</NumeroEndereco>'
cXML+= '<ComplementoEndereco>'+ALLTRIM(::oFuncoes:parseEncode(::rps_ComplementoEnderecoTomador))+'</ComplementoEndereco>'
cXML+= '<Bairro>'+ALLTRIM(::oFuncoes:parseEncode(::rps_BairroTomador))+'</Bairro>'
cXML+= '<Cidade>'+ALLTRIM(STR(::rps_CidadeTomador))+'</Cidade>'
cXML+= '<UF>'+ALLTRIM("SP")+'</UF>'
cXML+= '<CEP>'+ALLTRIM(::rps_CEPTomador)+'</CEP>'
cXML+= '</EnderecoTomador>'
cXML+= '<EmailTomador>'+ALLTRIM(::oFuncoes:parseEncode(::rps_EmailTomador))+'</EmailTomador>'
cXML+= '<Discriminacao>'+ALLTRIM(::Itens_DiscriminacaoServico)+'</Discriminacao>'
// V10.0.K1292
cXML+= '<ValorCargaTributaria>'+::cValorCargaTributaria+'</ValorCargaTributaria>'
cXML+= '<PercentualCargaTributaria>'+::cPercentualCargaTributaria+'</PercentualCargaTributaria>'
cXML+= '<FonteCargaTributaria>P.I.085/14</FonteCargaTributaria>'
// V10.0.K1292
cXML+= '</RPS>'
cXML:=::oFuncoes:RemoveAcentuacao(cXML)
nHandle := FCREATE(::XML)
FWRITE(nHandle, cXML)
FCLOSE( nHandle )
aRETORNO['STATUS']:=.T.
aRETORNO['XML']:=::XML
aRETORNO['MSG']:='XML criado em '+::XML
RETURN(aRETORNO)
////////////////
// EOM Registro_RPS()
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//////////////////////////////////////////////////
METHOD Registro_Itens_RPS(lABRE,lFECHA) Class NFSE
//////////////////////////////////////////////////
LOCAL aRETORNO:=HASH()
LOCAL cXML:=''
LOCAL nHandle
aRETORNO['STATUS']:=.F.
aRETORNO['MSG']:=''
IF ::Xml=NIL .OR. EMPTY(::Xml)
aRETORNO['MSG']:='Arquivo XML com o registro do cabeçalho e RPS não informado.'
ENDIF
IF ::Itens_DiscriminacaoServico=NIL .OR. EMPTY(::Itens_DiscriminacaoServico)
aRETORNO['MSG']:='Favor informar a Discriminação do Serviço.'
ENDIF
IF ::Itens_Quantidade=NIL .OR. ::Itens_Quantidade<=0
aRETORNO['MSG']:='Favor informar a Quantidade do serviço tomado.'
ENDIF
IF ::Itens_ValorUnitario=NIL .OR. ::Itens_ValorUnitario<=0
aRETORNO['MSG']:='Favor informar o Valor Unitário do serviço tomado.'
ENDIF
IF ::Itens_ValorTotal=NIL .OR. ::Itens_ValorTotal<=0
aRETORNO['MSG']:='Favor informar o Valor total do serviço tomado.'
ENDIF
IF ::Itens_Tributavel=NIL
::Itens_Tributavel:=''
ENDIF
IF !EMPTY(aRETORNO['MSG'])
RETURN(aRETORNO)
ENDIF
cXML:=MEMOREAD(::Xml)
FERASE(::Xml)
IF lABRE
cXML+='<Itens>'
ENDIF
IF lFECHA
cXML+='</Itens>'
ENDIF
nHandle := FCREATE(::Xml)
FWRITE(nHandle, cXML)
FCLOSE( nHandle )
aRETORNO['STATUS']:=.T.
aRETORNO['XML']:=::Xml
aRETORNO['MSG']:='XML criado em '+::Xml
RETURN(aRETORNO)
////////////////
// EOM Registro_Itens_RPS()
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
/////////////////////////////////////////
METHOD Registro_Deducao_RPS(lABRE,lFECHA)
/////////////////////////////////////////
LOCAL aRETORNO:=HASH()
LOCAL cXML:=''
LOCAL nHandle
aRETORNO['STATUS']:=.F.
aRETORNO['MSG']:=''
IF ::Xml=NIL .OR. EMPTY(::Xml)
aRETORNO['MSG']:='Arquivo XML com o registro do cabeçalho e RPS não informado.'
ENDIF
IF !EMPTY(aRETORNO['MSG'])
RETURN(aRETORNO)
ENDIF
cXML:=MEMOREAD(::Xml)
FERASE(::Xml)
nHandle := FCREATE(::Xml)
FWRITE(nHandle, cXML)
FCLOSE( nHandle )
aRETORNO['STATUS']:=.T.
aRETORNO['XML']:=::Xml
aRETORNO['MSG']:='XML criado em '+::Xml
RETURN(aRETORNO)
////////////////
// EOM Registro_Deducao_RPS()
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
////////////////////////////////
METHOD Finaliza_RPS() Class NFSE
////////////////////////////////
LOCAL aRETORNO:=HASH()
LOCAL cXML:=''
LOCAL nHandle
aRETORNO['STATUS']:=.F.
aRETORNO['MSG']:=''
IF ::Xml=NIL .OR. EMPTY(::Xml)
aRETORNO['MSG']:='Arquivo XML com o registro do cabeçalho e RPS não informado.'
ENDIF
cXML:=MEMOREAD(::Xml)
FERASE(::Xml)
cXML+='<Signature></Signature>'
cXML+='</PedidoEnvioLoteRPS>'
nHandle := FCREATE(::Xml)
FWRITE(nHandle, cXML)
FCLOSE( nHandle )
aRETORNO['STATUS']:=.T.
aRETORNO['XML']:=::Xml
aRETORNO['MSG']:='XML criado em '+::Xml
RETURN(aRETORNO)
////////////////
// EOM Finaliza_RPS()
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//////////////////////////////
METHOD Assina_XML() Class NFSE
//////////////////////////////
LOCAL oDOMDoc, oXmldsig, oCert, oStoreMem, dsigKey, signedKey
LOCAL aRETORNO:=HASH()
LOCAL cXML:='', cXMLSig:=''
LOCAL PosIni:=0, PosFim:=0, nP:=0, nResult:=0
LOCAL nHandle
aRETORNO['STATUS']:=.F.
aRETORNO['MSG']:=''
IF ::Xml=NIL .OR. EMPTY(::Xml)
aRETORNO['MSG']:='Arquivo XML com o registro do cabeçalho e RPS não informado.'
ENDIF
cXML:=MEMOREAD(::Xml)
FERASE(::Xml)
cXML:=STRTRAN(cXML,'<Signature></Signature>','<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">'+;
'<SignedInfo>'+;
'<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />'+;
'<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />'+;
'<Reference URI="">'+;
'<Transforms>'+;
'<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />'+;
'<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />'+;
'</Transforms>'+;
'<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />'+;
'<DigestValue>'+;
'</DigestValue>'+;
'</Reference>'+;
'</SignedInfo>'+;
'<SignatureValue>'+;
'</SignatureValue>'+;
'<KeyInfo>'+;
'<X509Data>'+;
'<X509Certificate>'+;
'</X509Certificate>'+;
'</X509Data>'+;
'</KeyInfo>'+;
'</Signature>')
// Inicializa o objeto do DOMDocument
TRY
oDOMDoc := win_oleCreateObject(_MSXML2_DOMDocument)
CATCH
aRETORNO['MSG']:='Nao foi possível carregar ' + _MSXML2_DOMDocument
RETURN(aRETORNO)
END
oDOMDoc:async = .F.
oDOMDoc:resolveExternals := .F.
oDOMDoc:validateOnParse = .T.
oDOMDoc:preserveWhiteSpace = .T.
// inicializa o objeto do MXDigitalSignature
TRY
oXmldsig := win_oleCreateObject( _MSXML2_MXDigitalSignature )
CATCH
aRETORNO['MSG']:='Nao foi possível carregar ' +_MSXML2_MXDigitalSignature
RETURN(aRETORNO)
END
nHandle := FCREATE(::ohbNFe:pastaEnvRes+"\edunfs.xml")
FWRITE( nHandle, cXML )
FCLOSE( nHandle )
// carrega o arquivo XML para o DOM
oDOMDoc:LoadXML(cXML)
IF oDOMDoc:parseError:errorCode<>0
aRETORNO['MSG']:=' Assinar: Não foi possível carregar o documento pois ele não corresponde ao seu Schema'+HB_OsNewLine()+;
' Linha: ' + STR(oDOMDoc:parseError:line)+HB_OsNewLine()+;
' Caractere na linha: ' + STR(oDOMDoc:parseError:linepos)+HB_OsNewLine()+;
' Causa do erro: ' + oDOMDoc:parseError:reason+HB_OsNewLine()+;
' code: ' + STR(oDOMDoc:parseError:errorCode)
RETURN(aRETORNO)
ENDIF
// Localiza as assinaturas no XML
oDOMDoc:setProperty('SelectionNamespaces',"xmlns:ds='http://www.w3.org/2000/09/xmldsig#'")
oXmldsig:signature := oDOMDoc:selectSingleNode('.//ds:Signature')
IF (oXmldsig:signature = nil)
aRETORNO['MSG'] := 'É preciso carregar o template antes de assinar.'
RETURN(aRETORNO)
ENDIF
// carrega o objeto do certificado digital
oCert:=::ohbNFe:pegaObjetoCertificado(::ohbNFe:cSerialCert)
IF oCert == Nil
aRETORNO['MSG'] := 'Certificado não encontrado, Favor revisar a instalação do Certificado'
RETURN(aRETORNO)
ENDIF
// cria o objeto de Store da capicom
oStoreMem := win_oleCreateObject('CAPICOM.Store')
// Aloca o certificado na memoria
TRY
oStoreMem:open(_CAPICOM_MEMORY_STORE,'Memoria',_CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED)
CATCH oError
aRETORNO['MSG']:='Falha ao alocar o certificado na memoria '+HB_OsNewLine()+ ;
'Error: ' + Transform(oError:GenCode, nil) + ';' +HB_OsNewLine()+ ;
'SubC: ' + Transform(oError:SubCode, nil) + ';' +HB_OsNewLine()+ ;
'OSCode: ' + Transform(oError:OsCode, nil) + ';' +HB_OsNewLine()+ ;
'SubSystem: ' + Transform(oError:SubSystem, nil) + ';' +HB_OsNewLine()+ ;
'Mensangem: ' + oError:Description
RETURN(aRETORNO)
END
// Aloca o certificado na Capicom
TRY
oStoreMem:Add(oCert)
CATCH oError
aRETORNO['MSG']:='Falha ao aloca o certificado na memoria da Capicom '+HB_OsNewLine()+;
'Error: ' + Transform(oError:GenCode, nil) + ';' +HB_OsNewLine()+;
'SubC: ' + Transform(oError:SubCode, nil) + ';' +HB_OsNewLine()+;
'OSCode: ' + Transform(oError:OsCode, nil) + ';' +HB_OsNewLine()+;
'SubSystem: ' + Transform(oError:SubSystem, nil) + ';' +HB_OsNewLine()+;
'Mensangem: ' + oError:Description
RETURN(aRETORNO)
END
oXmldsig:store:=oStoreMem
// Cria chave CSP
TRY
dsigKey:=oXmldsig:createKeyFromCSP(oCert:PrivateKey:ProviderType, oCert:PrivateKey:ProviderName, oCert:PrivateKey:ContainerName, 0)
CATCH
aRETORNO['MSG']:='Erro ao criar a chave do CSP, talvez o certificado não esteja instalado corretamente.'
RETURN(aRETORNO)
END
IF (dsigKey = nil)
aRETORNO['MSG']:='Erro ao criar a chave do CSP.'
RETURN(aRETORNO)
ENDIF
// Assina a chave do CSP
TRY
signedKey:=oXmldsig:sign(dsigKey, 2)
CATCH
aRETORNO['MSG']:='Erro ao assinar a chave do CSP, talvez o certificado não esteja instalado corretamente.'
RETURN(aRETORNO)
END
IF signedKey=NIL
aRETORNO['MSG']:='Assinatura Falhou.'
RETURN(aRetorno)
ENDIF
// Trata o formato da estrutura do XML
cXMLSig := STRTRAN(STRTRAN(oDOMDoc:xml,CHR(10)),CHR(13))
PosIni := AT('<SignatureValue>',cXMLSig)+len('<SignatureValue>')
cXMLSig := SUBS(cXMLSig,1,PosIni-1)+STRTRAN( SUBS(cXMLSig,PosIni,len(cXMLSig)), ' ', '' )
PosIni := AT('<X509Certificate>',cXMLSig)-1
nP := AT('<X509Certificate>',cXMLSig)
nResult := 0
DO WHILE nP<>0
nResult := nP
nP = WAT('<X509Certificate>',cXMLSig,nP+1)
ENDDO
PosFim := nResult
cXMLSig := SUBS(cXMLSig,1,PosIni)+SUBS(cXMLSig,PosFim,len(cXMLSig))
cXMLsig := STRTRAN( cXMLsig, 'Id="rps:1"', '' )
// grava o arquivo no disco
nHandle := FCREATE(::Xml)
FWRITE(nHandle, cXMLSig)
FCLOSE( nHandle )
aRETORNO['STATUS']:=.T.
aRETORNO['XML']:=::Xml
aRETORNO['MSG']:='XML assinado com sucesso em '+::Xml
RETURN(aRETORNO)
////////////////
// EOM Assina_XML()
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//////////////////////////////////
METHOD LinkWebService() Class NFSE
//////////////////////////////////
LOCAL cWeb:=''
IF ::cab_CodCidade=3550308 // SÆo Paulo-SP
cWeb:='https://nfe.prefeitura.sp.gov.br/ws/lotenfe.asmx'
ENDIF
RETURN(cWeb)
////////////
// EOM LinkWebService()
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
///////////////////////////////////////
METHOD ctPegaCNCertificado() Class NFSE
///////////////////////////////////////
LOCAL oStore, oResult, oCertificados
LOCAL cSubjectName:='', cCN:=''
LOCAL mI:=0
TRY
oStore := win_oleCreateObject( "CAPICOM.Store" )
CATCH
END
IF oStore = Nil
RETURN('')
ENDIF
oStore:open(_CAPICOM_CURRENT_USER_STORE,'My',_CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED)
oCertificados:=oStore:Certificates()
FOR mI=1 TO oCertificados:Count()
IF oCertificados:Item(mI):SerialNumber = ::ohbNFe:cSerialCert
cSubjectName := oCertificados:Item(mI):SubjectName
ENDIF
NEXT
cCN:=''
FOR mI:=AT("CN=",cSubjectName)+3 TO LEN(cSubjectName)
IF SUBS(cSubjectName,mI,1) == ","
EXIT
ENDIF
cCN += SUBS(cSubjectName,mI,1)
NEXT
oCertificados := Nil
oStore := Nil
RETURN(cCN)
///////////
// EOM ctPegaCNCertificado()
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
/////////////////////////////////////////////
METHOD ComunicaWebService(cMethod) Class NFSE
/////////////////////////////////////////////
LOCAL oServerWS
LOCAL oDOMDoc
LOCAL aRETORNO := HASH()
LOCAL cCERT := ''
LOCAL cUrlWS := ''
LOCAL cXML := {}
LOCAL cNameSpace := ""
LOCAL cRetXml
aRETORNO['STATUS']:=.F.
aRETORNO['MSG']:=''
IF ::Xml=NIL .OR. EMPTY(::Xml)
aRETORNO['MSG']:='Arquivo XML assinado de RPS não informado.'
ENDIF
cXML := MEMOREAD(::Xml)
// FERASE(::Xml)
IF EMPTY(cXML)
aRETORNO['MSG']:='Favor informar o arquivo de XML.'
RETURN(aRETORNO)
ENDIF
IF cMethod == 'cancelar'
cNameSpace := "CancelamentoNFeRequest"
ELSE
IF .f. // WSet( LPK_B_PC_TEC ) // NÆo est funcionando
cNameSpace := "TesteEnvioLoteRPSRequest"
ELSE
cNameSpace := "EnvioLoteRPSRequest"
ENDIF
ENDIF
cXML := '<?xml version="1.0" encoding="utf-8"?>' +;
'<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' +;
'xmlns:xsd="http://www.w3.org/2001/XMLSchema" ' +;
'xmlns:soap12="http://schemas.xmlsoap.org/soap/envelope/">' +;
'<soap12:Body>' +;
'<'+cNameSpace+' xmlns="http://www.prefeitura.sp.gov.br/nfe">' +;
'<VersaoSchema>1</VersaoSchema>' +;
'<MensagemXML> ' +;
'<![CDATA[ ' + cXML +' ]]>'+;
'</MensagemXML>' +;
'</'+cNameSpace+'>'+;
'</soap12:Body>' +;
'</soap12:Envelope>'
nHandle := FCREATE(::ohbNFe:pastaEnvRes+"\edunfs.xml")
FWRITE( nHandle, cXML )
FCLOSE( nHandle )
TRY
// cCERT := ::ctPegaCNCertificado()
cCERT := ::ohbNFe:pegaCNCertificado(SetaCros( GC_NFE_NS_CERTIF ))
CATCH
END
IF EMPTY(cCERT)
aRETORNO['MSG']:='Não foi possível carregar as informações do certificado.'
RETURN(aRETORNO)
ENDIF
cUrlWS:=::LinkWebService()
IF EMPTY(cUrlWS)
aRETORNO['MSG']:='Webservice não localizado'
RETURN(aRETORNO)
ENDIF
TRY
oServerWS:=win_oleCreateObject( _MSXML2_ServerXMLHTTP )
oServerWS:setOption( 3, 'CURRENT_USER\MY\'+cCERT )
oServerWS:open('POST', cUrlWS, .F.)
IF .F. // WSet( LPK_B_PC_TEC ) // NÆo est funcionando
oServerWS:setRequestHeader('SOAPAction', 'http://www.prefeitura.sp.gov.br/nfe/ws/testeenvio' )
ELSE
IF cMethod == 'cancelar'
oServerWS:setRequestHeader('SOAPAction', 'http://www.prefeitura.sp.gov.br/nfe/ws/cancelamentoNFe' )
ELSE
oServerWS:setRequestHeader('SOAPAction', 'http://www.prefeitura.sp.gov.br/nfe/ws/envioLoteRPS' )
ENDIF
ENDIF
oServerWS:setRequestHeader('Content-Type','text/xml; charset=utf-8')
CATCH
aRETORNO['MSG']:='Não foi possível inicializar a conexão do webservice'
RETURN(aRETORNO)
END
IF oServerWS=NIL
aRETORNO['MSG']:='Não foi possível inicializar o objeto de conexão do webservice'
RETURN(aRETORNO)
ENDIF
TRY
oDOMDoc:=win_oleCreateObject(_MSXML2_DOMDocument)
oDOMDoc:async = .F.
oDOMDoc:validateOnParse = .T.
oDOMDoc:resolveExternals := .F.
oDOMDoc:preserveWhiteSpace = .T.
oDOMDoc:LoadXML(cXML)
CATCH
aRETORNO['MSG']:='Não foi possível carregar o documento XML'
RETURN(aRETORNO)
END
IF oDOMDoc:parseError:errorCode <> 0
aRETORNO['MSG']:='Não foi possível carregar o documento pois ele não corresponde ao seu Schema'+HB_OsNewLine()+;
' Linha: '+STR(oDOMDoc:parseError:line) +HB_OsNewLine()+;
' Caractere na linha: '+STR(oDOMDoc:parseError:linepos) +HB_OsNewLine()+;
' Causa do erro: '+oDOMDoc:parseError:reason +HB_OsNewLine()+;
' Code: '+STR(oDOMDoc:parseError:errorCode)
RETURN(aRETORNO)
ENDIF
TRY
oServerWS:send( oDOMDoc:xml )
CATCH e
aRETORNO['MSG']:='Falha: Não foi possível conectar-se ao servidor do SEFAZ, Servidor inativo ou inoperante.'+HB_OsNewLine()+;
'Error: '+Transform(e:GenCode,nil) +';'+HB_OsNewLine()+;
'SubC: '+Transform(e:SubCode,nil) +';'+HB_OsNewLine()+;
'OSCode: '+Transform(e:OsCode,nil) +';'+HB_OsNewLine()+;
'SubSystem: '+Transform(e:SubSystem,nil) +';'+HB_OsNewLine()+;
'Mensangem: '+e:Description
Wint(aRETORNO['MSG'])
RETURN(aRETORNO)
END
DO WHILE oServerWS:readyState <> 4
millisec(500)
ENDDO
aRETORNO['MSG']:='Comunicação com o webservice finalizada com sucesso.'
aRETORNO['STATUS']:=.T.
aRETORNO['XML']:=oServerWS:responseText
nHandle := FCREATE(::ohbNFe:pastaEnvRes+"\eduret.xml")
FWRITE( nHandle, AlteraCaracteres(oServerWS:responseText, .T.) )
FCLOSE( nHandle )
oDOMDoc :=Nil
oServerWS :=Nil
RETURN(aRETORNO)
////////////////
// EOM ComunicaWebService()
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
///////////////////////////////
METHOD CancelaNFSe() Class NFSE
///////////////////////////////
LOCAL cXML:=''
LOCAL aRETORNO:=HASH()
LOCAL nHandle
aRETORNO['STATUS']:=.F.
aRETORNO['MSG']:=''
IF ::cab_CodCidade=NIL .OR. ::cab_CodCidade<=0
aRETORNO['MSG']:='Favor informar o código do município'
ENDIF
IF ::cab_CPFCNPJRemetente=NIL .OR. EMPTY(::cab_CPFCNPJRemetente)
aRETORNO['MSG']:='Favor informar o CPF / CNPJ do Remetente'
ENDIF
IF ::rps_InscricaoMunicipalPrestador=NIL .OR. EMPTY(::rps_InscricaoMunicipalPrestador)
aRETORNO['MSG']:='Favor Informar a Inscrição Municipal do Prestador. Verificar regra de preenchimento do campo no Anexo 03.'
ENDIF
IF ::numero_nota=NIL .OR. ::numero_nota<=0
aRETORNO['MSG']:='Favor Informar o número da nota a ser cancelada.'
ENDIF
// IF ::codigo_verificacao=NIL .OR. EMPTY(::codigo_verificacao)
// aRETORNO['MSG']:='Favor Informar o código verificador.'
// ENDIF
IF !EMPTY(aRETORNO['MSG'])
aRETORNO["STATUS"] := .F.
RETURN(aRETORNO)
ENDIF
cXML += '<PedidoCancelamentoNFe xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.prefeitura.sp.gov.br/nfe">'
cXML+= '<Cabecalho Versao="1" xmlns="">'
cXML+= '<CPFCNPJRemetente>'
cXML+= '<CNPJ>'+ALLTRIM(::cab_CPFCNPJRemetente)+'</CNPJ>'
cXML+= '</CPFCNPJRemetente>'
cXML+= '<transacao>true</transacao>'
cXML+= '</Cabecalho>'
cXML+= '<Detalhe xmlns="">'
cXML+= '<ChaveNFe>'
cXML+= '<InscricaoPrestador>'+ALLTRIM(::rps_InscricaoMunicipalPrestador)+'</InscricaoPrestador>'
cXML+= '<NumeroNFe>'+ALLTRIM(STR(::numero_nota))+'</NumeroNFe>'
cXML+= '</ChaveNFe>'
cXML+= '<AssinaturaCancelamento>'+::Gera_Chave_SHA1_Cancelamento()+'</AssinaturaCancelamento>'
cXML+= '</Detalhe>'
cXML+= '<Signature></Signature>'
cXML+= '</PedidoCancelamentoNFe>'
::Xml:=::ohbNFe:pastaEnvRes+'\NFSe_canc'+ALLTRIM(::cab_CPFCNPJRemetente)+DTOS(DATE())+STRTRAN(LEFT(TIME(),8),':')+'.xml'
nHandle := FCREATE(::Xml)
FWRITE(nHandle, cXML)
FCLOSE( nHandle )
aRETORNO:=::Assina_XML()
IF !aRETORNO['STATUS']
RETURN(aRETORNO)
ENDIF
// aRETORNO:=::ValidaXML()
// IF !aRETORNO['STATUS']
// RETURN(aRETORNO)
// ENDIF
aRETORNO:=::ComunicaWebService('cancelar')
IF !aRETORNO['STATUS']
RETURN(aRETORNO)
ENDIF
aRETORNO:=::LeRetorno(aRETORNO['XML'])
IF !aRETORNO['STATUS']
RETURN(aRETORNO)
ENDIF
RETURN(aRETORNO)
// EOM CancelaNFSe()
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
/////////////////////////////////
METHOD LeRetorno(cRET) Class NFSE
/////////////////////////////////
LOCAL aRETORNO:=HASH()
aRETORNO['STATUS']:=.F.
aRETORNO['MSG']:=''
cRET:=STRTRAN(cRET,'<','<')
cRET:=STRTRAN(cRET,'>','>')
cRET:=STRTRAN(cRET,'"','"')
IF '<Erros>' $ cRET
cRET:=::oFuncoes:pegaTag(cRET,'Erro')
aRETORNO['CODIGO']:=::oFuncoes:pegaTag(cRET,'Codigo')
aRETORNO['DESCRICAO']:=::oFuncoes:pegaTag(cRET,'Descricao')
aRETORNO['MSG']:=aRETORNO['CODIGO']+'-'+aRETORNO['DESCRICAO']
ELSEIF '<Alertas>' $ cRET
cRET:=::oFuncoes:pegaTag(cRET,'Alerta')
aRETORNO['CODIGO']:=::oFuncoes:pegaTag(cRET,'Codigo')
aRETORNO['DESCRICAO']:=::oFuncoes:pegaTag(cRET,'Descricao')
aRETORNO['MSG']:=aRETORNO['CODIGO']+'-'+aRETORNO['DESCRICAO']
ELSEIF '>false<' $ cRET
aRETORNO['STATUS'] := .F.
aRETORNO['CODIGO'] := ::oFuncoes:pegaTag(cRET,'Codigo')
aRETORNO['DESCRICAO'] := ::oFuncoes:pegaTag(cRET,'Descricao')
aRETORNO['MSG'] := aRETORNO['DESCRICAO']
ELSE
aRETORNO['STATUS']:=.T.
ENDIF
RETURN(aRETORNO)
////////////////
// EOM LeRetorno()
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
/////////////////////////////
METHOD ValidaXML() Class NFSE
/////////////////////////////
LOCAL oDOMDoc, oSchema, ParseError
LOCAL aRETORNO:=HASH()
LOCAL cSchemaFilename:=''
aRETORNO['STATUS']:=.F.
aRETORNO['MSG']:=''
IF ::Xml=NIL .OR. EMPTY(::Xml)
aRETORNO['MSG']:='Arquivo XML assinado de RPS não informado.'
ENDIF
cXML:=MEMOREAD(::Xml)
wint("VALIDA")
IF 'ReqEnvioLoteRPS' $ cXML // Envio de lote
cXML:=STRTRAN(cXML,' xmlns:tipos="http://localhost:8080/WsNFe2/tp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://localhost:8080/WsNFe2/lote http://localhost:8080/WsNFe2/xsd/ReqEnvioLoteRPS.xsd"')
cSchemaFilename := ::ohbNFe:cPastaSchemas+'\ReqEnvioLoteRPS.xsd'
ELSEIF 'ReqCancelamentoNFSe' $ cXML // Cancelamento de NFSe
cXML:=STRTRAN(cXML,' xmlns:tipos="http://localhost:8080/WsNFe2/tp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://localhost:8080/WsNFe2/lote http://localhost:8080/WsNFe2/xsd/ReqCancelamentoNFSe.xsd"')
cSchemaFilename := ::ohbNFe:cPastaSchemas+'\ReqCancelamentoNFSe.xsd'
ENDIF
TRY
oDOMDoc := CreateObject( _MSXML2_DOMDocument )
CATCH
aRETORNO['MSG']:='Não foi possível carregar o MSXML para validação do XML.'
RETURN(aRETORNO)
END
TRY
oDOMDoc:async = .F.
oDOMDoc:resolveExternals := .F.
oDOMDoc:validateOnParse = .T.
oDOMDoc:LoadXML(cXML)
CATCH
aRETORNO['MSG']:='Não foi possível carregar o arquivo XML para a validação.'
RETURN(aRETORNO)
END
IF oDOMDoc:parseError:errorCode <> 0 // XML não carregado
aRETORNO['MSG']:='Não foi possível carregar o documento pois ele não corresponde ao seu Schema'+HB_OsNewLine()+;
'Linha: '+STR(oDOMDoc:parseError:line) +HB_OsNewLine()+;
'Caractere na linha: '+STR(oDOMDoc:parseError:linepos) +HB_OsNewLine()+;
'Causa do erro: '+oDOMDoc:parseError:reason +HB_OsNewLine()+;
'Code: '+STR(oDOMDoc:parseError:errorCode)
RETURN(aRETORNO)
ENDIF
TRY
oSchema := CreateObject( _MSXML2_XMLSchemaCache )
CATCH
aRETORNO['MSG']:='Não foi possível carregar o MSXML para o schema do XML.'
RETURN(aRETORNO)
END
IF !FILE(cSchemaFilename)
aRETORNO['MSG']:='Arquivo do schema não encontrado '+cSchemaFilename
RETURN(aRETORNO)
ENDIF
TRY
oSchema:add( 'http://localhost:8080/WsNFe2/lote', cSchemaFilename )
CATCH oError
aRETORNO['MSG']:='Falha '+HB_OsNewLine()+ ;
'Error: '+Transform(oError:GenCode, nil) + ';' +HB_OsNewLine()+;
'SubC: '+Transform(oError:SubCode, nil) + ';' +HB_OsNewLine()+;
'OSCode: '+Transform(oError:OsCode, nil) + ';' +HB_OsNewLine()+;
'SubSystem: '+Transform(oError:SubSystem, nil) + ';' +HB_OsNewLine()+;
'Mensangem: '+oError:Description
RETURN(aRETORNO)
END
oDOMDoc:Schemas := oSchema
ParseError := oDOMDoc:validate
IF ParseError:errorCode <> 0
aRetorno['nResult'] := ParseError:errorCode
aRETORNO['MSG'] := ParseError:reason
RETURN(aRetorno)
ENDIF
oDOMDoc := nil
ParseError := nil
oSchema := nil
aRETORNO['XML']:=::Xml
aRETORNO['STATUS']:=.T.
RETURN(aRETORNO)
////////////////
// EOM ValidaXML()
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
///////////////////////////////////
METHOD Gera_Chave_SHA1() Class NFSE
///////////////////////////////////
LOCAL cRET:=''
LOCAL cCHA := PADL(ALLTRIM(::rps_InscricaoMunicipalPrestador),8,'0')
LOCAL aRetorno
LOCAL oDll
LOCAL oFuncoes := hbNFeFuncoes()
cCHA += PADR(ALLTRIM(::rps_SerieRPS),5,' ')
cCHA += STRZERO(::rps_NumeroRPS,12)
cCHA += ::DataToYYYYMMDD(::rps_DataEmissaoRPS)
cCHA += ALLTRIM(::rps_Tributacao)
cCHA += LEFT(ALLTRIM(::rps_SituacaoRPS),1)
cCHA += IF(ALLTRIM(LEFT(::rps_TipoRecolhimento,1))='A','N','S')
// V10.0.K1608
// cCHA += STRZERO(VAL(STRTRAN(STR((::cab_ValorTotalServicos-::cab_ValorTotalDeducoes)*100),'.')),15) //STRZERO((::cab_ValorTotalServicos-::cab_ValorTotalDeducoes),15)
cCHA += STRZERO(VAL(STRTRAN(STR(INT((::cab_ValorTotalServicos-::cab_ValorTotalDeducoes)*100)),'.')),15) //STRZERO((::cab_ValorTotalServicos-::cab_ValorTotalDeducoes),15)
cCHA += STRZERO(VAL(STRTRAN(STR(::cab_ValorTotalDeducoes*100,15),'.')),15) //STRZERO(::cab_ValorTotalDeducoes/100,15)
cCHA += PADL(ALLTRIM(::rps_CodigoAtividade),5,'0')
IF LEN(ALLTRIM(::rps_CPFCNPJTomador)) == 11
cCHA += "1" // CPF
ELSE
cCHA += "2" // CNPJ
ENDIF
cCHA += PADL(ALLTRIM(::rps_CPFCNPJTomador),14,'0')
nHandle := FCREATE("StringParaAssinar.txt")
FWRITE(nHandle, ::ohbNFe:cSerialCert + CHR(13)+CHR(10)+ cCHA )
FCLOSE( nHandle )
WRunCMD( "AssinaRPS.EXE" )
cRET := MEMOREAD( "StringAssinada.txt" )
cRET := STRTRAN( cRET, CHR(13), "" )
cRET := STRTRAN( cRET, CHR(10), "" )
FERASE("StringParaAssinar.txt")
FERASE("StringAssinada.txt")
RETURN(oFuncoes:parseEncode( cRET ) )
/////////////////////////////////////
// EOM Gera_Chave_SHA1()
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
////////////////////////////////////////////////
METHOD Gera_Chave_SHA1_Cancelamento() Class NFSE
////////////////////////////////////////////////
LOCAL cRET:=''
LOCAL cCHA := ""
LOCAL aRetorno
LOCAL oDll
LOCAL oFuncoes := hbNFeFuncoes()
cCHA+=PADL(ALLTRIM(::rps_InscricaoMunicipalPrestador), 8, '0' )
cCHA+=PADL( ALLTRIM(STR(::numero_nota)) , 12, '0' )
nHandle := FCREATE("StringParaAssinar.txt")
FWRITE(nHandle, ::ohbNFe:cSerialCert + CHR(13)+CHR(10)+ cCHA )
FCLOSE( nHandle )
WRunCMD( "AssinaRPS.EXE" )
cRET := MEMOREAD( "StringAssinada.txt" )
cRET := STRTRAN( cRET, CHR(13), "" )
cRET := STRTRAN( cRET, CHR(10), "" )
FERASE("StringParaAssinar.txt")
FERASE("StringAssinada.txt")
RETURN(oFuncoes:parseEncode( cRET ) )
/////////////////////////////////////
// EOM Gera_Chave_SHA1_Cancelamento()
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//////////////////////////////////////////////
METHOD DataToYYYY_MM_DD(dDAT,lTIME) Class NFSE
//////////////////////////////////////////////
LOCAL cRET:=ALLTRIM(STR(YEAR(dDAT)))+'-'+STRZERO(MONTH(dDAT),2)+'-'+STRZERO(DAY(dDAT),2)
IF lTIME=NIL
lTIME:=.F.
ENDIF
IF lTIME
cRET+='T'+LEFT(TIME(),8)
ENDIF
RETURN(cRET)
////////////
// EOM DataToYYYY_MM_DD()
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//////////////////////////////////////
METHOD DataToYYYYMMDD(dDAT) Class NFSE
//////////////////////////////////////
LOCAL cRET:=ALLTRIM(STR(YEAR(dDAT)))+STRZERO(MONTH(dDAT),2)+STRZERO(DAY(dDAT),2)
RETURN(cRET)
////////////
// EOM DataToYYYY_MM_DD()
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//////////////////////////////////////
FUNCTION AlteraCaracteres(c, lInverte)
//////////////////////////////////////
LDEFAULT lInverte TO .F.
IF lInverte
c := STRTRAN( c, ">" , ">")
c := STRTRAN( c, "<" , "<")
c := STRTRAN( c, "&" , "&")
c := STRTRAN( c, """ , '"')
c := STRTRAN( c, "'" , "'")
ELSE
c := STRTRAN( c, ">", ">" )
c := STRTRAN( c, "<", "<" )
c := STRTRAN( c, "&", "&" )
c := STRTRAN( c, '"', """ )
c := STRTRAN( c, "'", "'" )
ENDIF
RETURN( c )
///////////
// EOF AlteraCaracteres()