Página 1 de 2

Usando classe para assinar nfse - São Paulo

Enviado: 14 Mar 2023 14:02
por malcarli
Boa tarde mestre, estou fazendo testes com a nfseclass.prg e a ze_sefazclass.prg

Estou apanhando na assinatura, ainda não consegui assinar, mas já como nfse não tem o Id, implementei esse teste para desviar do trecho já que o conteudo do cUri é branco. Não sei se vai implementar, mas fica a dica:

Código: Selecionar todos


***************** qdo for nfse não tem esta tag
If lComURI  /// acrescentei para não calcular
   // Pega URI
   nPosIni := At( [Id=], cTxtXml )
   IF nPosIni = 0
      cRetorno := "Erro Assinatura: Não encontrado início do URI: Id= (com I maiúsculo)"
      RETURN .F.
   ENDIF
   nPosIni := hb_At( ["], cTxtXml, nPosIni + 2 )
   IF nPosIni = 0
      cRetorno := "Erro Assinatura: Não encontrado início do URI: aspas inicial"
      RETURN .F.
   ENDIF

   nPosFim := hb_At( ["], cTxtXml, nPosIni + 1 )
   IF nPosFim = 0
      cRetorno := "Erro Assinatura: Não encontrado início do URI: aspas final"
      RETURN .F.
   ENDIF
   cURI := Substr( cTxtXml, nPosIni + 1, nPosFim - nPosIni - 1 )
else
   cUri := []
Endif



Falta agora assinar pois está sem o digest

Usando classe para assinar nfse - São Paulo

Enviado: 14 Mar 2023 14:43
por JoséQuintas
Acho que já falamos disso.

NFSE está em DRAFTS - rascunhos.
Essa pasta é pra uma espécie de anotações.

Assinatura, NFSE são no mínimo duas.
À primeira vista estava pronto pra isso, mas manualmente precisa separar/juntar os blocos.

Usando classe para assinar nfse - São Paulo

Enviado: 14 Mar 2023 14:47
por JoséQuintas

Código: Selecionar todos

STATIC FUNCTION AssinaAjustaInformacao( cTxtXml, cXmlTagInicial, cXmlTagFinal, cRetorno, lComURI )

   LOCAL aDelimitadores, nPos, nPosIni, nPosFim, cURI

   aDelimitadores := { ;
      ...
      { "<PedidoEnvioLoteRPS",    "</RPS>" }, ;
      { "<PedidoEnvioRPS",        "</RPS>" }, ;
      { "<infPedidoCancelamento", "</Pedido>" }, ;               // NFSE ABRASF Cancelamento
      { "<LoteRps",               "</EnviarLoteRpsEnvio>" }, ;   // NFSE ABRASF Lote
      { "<infRps",                "</Rps>" } }                   // NFSE ABRASF RPS

Usando classe para assinar nfse - São Paulo

Enviado: 14 Mar 2023 14:50
por malcarli
Sim, agora retomei acabei de conseguir assinar, mas o delimitador final está incorreto. Não vou postar aqui ele assinado, por lgpd, mas se quiser ver assinado mando no teu zap.

Veja o que fiz para assinar:
troquei este: { "<PedidoEnvioRPS", "</RPS>" }, ;

Por este e assinou: { "<PedidoEnvioRPS", "</PedidoEnvioRPS>" }, ;

e testei o If lComURI para não passar no trecho.

Código: Selecionar todos

STATIC FUNCTION AssinaAjustaInformacao( cTxtXml, cXmlTagInicial, cXmlTagFinal, cRetorno, lComURI )

   LOCAL aDelimitadores, nPos, nPosIni, nPosFim, cURI

   aDelimitadores := { ;
      { "<enviMDFe",              "</MDFe></enviMDFe>" }, ;
      { "<eventoMDFe",            "</eventoMDFe>" }, ;
      { "<eventoCTe",             "</eventoCTe>" }, ;
      { "<infMDFe",               "</MDFe>" }, ;
      { "<infCte",                "</CTe>" }, ;
      { "<infNFe",                "</NFe>" }, ;
      { "<infDPEC",               "</envDPEC>" }, ;
      { "<infInut",               "<inutNFe>" }, ;
      { "<infCanc",               "</cancNFe>" }, ;
      { "<infInut",               "</inutNFe>" }, ;
      { "<infInut",               "</inutCTe>" }, ;
      { "<infEvento",             "</evento>" }, ;
      { "<evtInfoEmpregador",     "</eSocial>" }, ;
      { "<PedidoEnvioLoteRPS",    "</RPS>" }, ;
      { "<PedidoEnvioRPS",        "</PedidoEnvioRPS>" }, ;
      { "<infPedidoCancelamento", "</Pedido>" }, ;               // NFSE ABRASF Cancelamento
      { "<LoteRps",               "</EnviarLoteRpsEnvio>" }, ;   // NFSE ABRASF Lote
      { "<infRps",                "</Rps>" } }                   // NFSE ABRASF RPS

*      { "<PedidoEnvioRPS",        "</RPS>" }, ;

   // Define Tipo de Documento
   IF ( nPos := hb_AScan( aDelimitadores, { | oElement | oElement[ 1 ] $ cTxtXml .AND. oElement[ 2 ] $ cTxtXml } ) ) == 0
      cRetorno := "Erro Assinatura: Não identificado documento"
      RETURN .F.
   ENDIF
   cXmlTagFinal  := aDelimitadores[ nPos, 2 ]

***************** qdo for nfse não tem esta tag
If lComURI  /// acrescentei para não calcular
   // Pega URI
   nPosIni := At( [Id=], cTxtXml )
   IF nPosIni = 0
      cRetorno := "Erro Assinatura: Não encontrado início do URI: Id= (com I maiúsculo)"
      RETURN .F.
   ENDIF
   nPosIni := hb_At( ["], cTxtXml, nPosIni + 2 )
   IF nPosIni = 0
      cRetorno := "Erro Assinatura: Não encontrado início do URI: aspas inicial"
      RETURN .F.
   ENDIF

   nPosFim := hb_At( ["], cTxtXml, nPosIni + 1 )
   IF nPosFim = 0
      cRetorno := "Erro Assinatura: Não encontrado início do URI: aspas final"
      RETURN .F.
   ENDIF
   cURI := Substr( cTxtXml, nPosIni + 1, nPosFim - nPosIni - 1 )
else
   cUri := []
Endif

Usando classe para assinar nfse - São Paulo

Enviado: 14 Mar 2023 16:58
por malcarli
Consegui assinar e comparei com um xml assinado pelo acbr e estão exatamente iguais

Agora só falta enviar (kkkk)

Alterei o prg em anexo (NFSEClass.prg) , mas dá msg de falha no servidor e não conseguir resolver, imagino que seja no METHOD XmlsoapEnvelope()

obrigado
NFSEClass.prg
(8.09 KiB) Baixado 460 vezes

Usando classe para assinar nfse - São Paulo

Enviado: 14 Mar 2023 21:12
por JoséQuintas
A resposta quase está no seu texto.

mexeu na assinatura

Código: Selecionar todos

      { "<PedidoEnvioLoteRPS",    "</RPS>" }, ;
      { "<PedidoEnvioRPS",        "</PedidoEnvioRPS>" }, ; // <<-----------------------------------
mexeu na lista

Código: Selecionar todos

METHOD Setup( cCertificado, cAmbiente, nWsServico ) CLASS SefazClass1

   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" } }
Mas ...

Código: Selecionar todos

METHOD EnvioLoteRPS( cXml, cCertificado, cAmbiente ) CLASS SefazClass1

   ::Setup( cCertificado, cAmbiente, WS_ENVIOLOTERPS )
lote é lote.

Usando classe para assinar nfse - São Paulo

Enviado: 15 Mar 2023 08:19
por malcarli
Bom dia mestre, mesmo alterando o trecho:

Código: Selecionar todos

METHOD EnvioLoteRPS( cXml, cCertificado, cAmbiente ) CLASS SefazClass1
	 
	   ::Setup( cCertificado, cAmbiente, WS_ENVIORPS )
Está assinando corretamente, mas continua o erro no envio, não acha o servidor

neste trecho, não alterei nada (onde é feito o envelopamento com o nome do servidor):

Código: Selecionar todos

METHOD XmlsoapEnvelope() CLASS SefazClass1
   ::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://schemas.xmlsoap.org/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
Tentei alerar pelo trecho que consta no site, mas tb não funcionou (só falta isso para enviar e ver o retorno), mas não tenho o conhecimento técnico suficiente

Código: Selecionar todos


SOAP 1.2
The following is a sample SOAP 1.2 request and response. The placeholders shown need to be replaced with actual values.

POST /ws/lotenfe.asmx HTTP/1.1
Host: nfe.prefeitura.sp.gov.br
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length

<?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://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <EnvioRPSRequest xmlns="http://www.prefeitura.sp.gov.br/nfe">
      <VersaoSchema>int</VersaoSchema>
      <MensagemXML>string</MensagemXML>
    </EnvioRPSRequest>
  </soap12:Body>
</soap12:Envelope>
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length

<?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://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <EnvioRPSResponse xmlns="http://www.prefeitura.sp.gov.br/nfe">
      <RetornoXML>string</RetornoXML>
    </EnvioRPSResponse>
  </soap12:Body>
</soap12:Envelope>

Usando classe para assinar nfse - São Paulo

Enviado: 15 Mar 2023 08:50
por JoséQuintas
Vou verificar.

Usando classe para assinar nfse - São Paulo

Enviado: 15 Mar 2023 09:15
por malcarli
Mestre consegui:


alterei aqui:

Código: Selecionar todos

*  ::cXmlsoap    +=       [xmlns:soap12="http://schemas.xmlsoap.org/soap/envelope/">]
   ::cXmlsoap    +=       [xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">]
Agora vou ver se consigo fazer codificação da tag assinatura


vou postando resultados, e assim que finalizar aviso. obg por eqto


Está retornando xml com caracteres, tem alguma função que retira, pois usei o xmltransform mas não funcionou

Usando classe para assinar nfse - São Paulo

Enviado: 15 Mar 2023 11:39
por JoséQuintas
Fica ruim ver imagens assim.
Coloque no paint e recorte só a parte que interessa.

Talvez o XmlTansform.
Se realmente estiver em UTF-8, converter os textos com função do Harbour.

Usando classe para assinar nfse - São Paulo

Enviado: 15 Mar 2023 11:42
por JoséQuintas
imagem.png

Usando classe para assinar nfse - São Paulo

Enviado: 15 Mar 2023 12:56
por malcarli
Desculpa, é a pressa. Como o xmltransform não funcionou


E agora apanhado da tag assinatura também

Usando classe para assinar nfse - São Paulo

Enviado: 21 Mar 2023 08:57
por malcarli
Bom dia Mestre Quintas

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)

Usando classe para assinar nfse - São Paulo

Enviado: 21 Mar 2023 09:15
por Itamar M. Lins Jr.
Olá!
Parabéns aos envolvidos !

Isso fortalece a comunidade.

Saudações,
Itamar M. Lins Jr.

Usando classe para assinar nfse - São Paulo

Enviado: 21 Mar 2023 09:52
por JoséQuintas

Código: Selecionar todos

 ShellExecute(0, [open], [AssinaRPS.EXE],,, 1)
Não entendi isso.

Sobre município, talvez igual NFE, mas município ao invés de UF.

Código: Selecionar todos

#define WS_BPE_CONSULTAPROTOCOLO { ;
   { "MG",   "1.00P", "https://bpe.fazenda.mg.gov.br/bpe/services/BPeConsulta" }, ;
   { "MS",   "1.00P", "https://bpe.fazenda.ms.gov.br/ws/BPeConsulta" }, ;
   { "PR",   "1.00P", "https://bpe.fazenda.pr.gov.br/bpe/BpeConsulta" }, ;
   { "SVRS", "1.00P", "https://bpe.svrs.rs.gov.br/ms/bpeConsulta.asmx" }, ;
   ;
   { "MS",   "1.00H", "https://homologacao.bpe.ms.gov.br/ws/BPeConsulta" } }
Ou pelo esquema, acho que SP usa ABRASF

SERVIÇO NÃO É IGUAL NFE.
O padrão de SPaulo pode ser válido pra alguns municípios apenas.
Pra outro município pode ser tudo diferente, até mesmo o modo de assinar.