From a8d5996ff0ab797c6ee54f8f31d71881b86d6197 Mon Sep 17 00:00:00 2001 From: Leonardo Tada Date: Wed, 23 Dec 2015 16:55:32 -0200 Subject: [PATCH] assinar nfe ginfes --- pynfe/processamento/assinatura.py | 67 +++++++++------------------------ pynfe/processamento/autorizador_nfse.py | 6 +-- 2 files changed, 19 insertions(+), 54 deletions(-) diff --git a/pynfe/processamento/assinatura.py b/pynfe/processamento/assinatura.py index ef7a2cb..828288f 100644 --- a/pynfe/processamento/assinatura.py +++ b/pynfe/processamento/assinatura.py @@ -64,20 +64,20 @@ class AssinaturaA1(Assinatura): except Exception as e: raise e - def assinarNfse(self, xml, xpath='/GerarNfseEnvio/ns1:Rps', retorna_string=False): + def assinarNfse(self, xml, xpath='.//ns1:InfDeclaracaoPrestacaoServico', + tag='InfDeclaracaoPrestacaoServico', retorna_string=False, + namespaces=None): try: xml = etree.fromstring(xml) + namespaces = xml.nsmap if namespaces is None else namespaces # No raiz do XML de saida - tag = 'InfDeclaracaoPrestacaoServico' # tag que serĂ¡ assinada raiz = etree.Element('Signature', xmlns='http://www.w3.org/2000/09/xmldsig#') siginfo = etree.SubElement(raiz, 'SignedInfo') etree.SubElement(siginfo, 'CanonicalizationMethod', Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315') etree.SubElement(siginfo, 'SignatureMethod', Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1') - # Tenta achar a tag infNFe - # TODO a proxima linha nao eh encontrada pq precisa colocar o namespace, GerarNfseEnvio. + # Tenta achar a tag ref = etree.SubElement(siginfo, 'Reference', URI='#' + - xml.xpath(xpath + '/ns1:InfDeclaracaoPrestacaoServico', namespaces={'ns1': 'http://www.betha.com.br/e-nota-contribuinte-ws'})[0].attrib['Id']) - + xml.xpath(xpath, namespaces=namespaces)[0].attrib['Id']) trans = etree.SubElement(ref, 'Transforms') etree.SubElement(trans, 'Transform', Algorithm='http://www.w3.org/2000/09/xmldsig#enveloped-signature') etree.SubElement(trans, 'Transform', Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315') @@ -87,59 +87,26 @@ class AssinaturaA1(Assinatura): keyinfo = etree.SubElement(raiz, 'KeyInfo') etree.SubElement(keyinfo, 'X509Data') - rps = xml.xpath(xpath, namespaces={'ns1': 'http://www.betha.com.br/e-nota-contribuinte-ws'})[0] + rps = xml.xpath(xpath+'/..', namespaces=namespaces)[0] rps.append(raiz) # Escreve no arquivo depois de remover caracteres especiais e parse string with open('nfse.xml', 'w') as arquivo: - arquivo.write(remover_acentos(etree.tostring(xml, encoding="unicode", pretty_print=False).replace('ns1:', '').replace(':ns1', ''))) + texto = remover_acentos(etree.tostring(xml, encoding="unicode", pretty_print=False)) + # se for tag do Betha + if tag == 'InfDeclaracaoPrestacaoServico': + texto = texto.replace('ns1:', '').replace(':ns1', '') + arquivo.write(texto) - subprocess.call(['xmlsec1', '--sign', '--pkcs12', self.certificado, '--pwd', self.senha, '--crypto', 'openssl', '--output', 'funfa.xml', '--id-attr:Id', tag, 'nfse.xml']) - xml = etree.parse('funfa.xml').getroot() - if retorna_string: - return etree.tostring(xml, encoding="unicode", pretty_print=False) - else: - return xml - except Exception as e: - raise e - - def assinarLoteNfse(self, lote, retorna_string=False): - try: - # Assina a nota - lote = self.assinarNfse(xml=lote, xpath='/EnviarLoteRpsSincronoEnvio/ns1:LoteRps/ns1:ListaRps/ns1:Rps', retorna_string=True) - # Assina o lote - lote = etree.fromstring(lote) - # No raiz do XML de saida - tag = 'LoteRps' # tag que serĂ¡ assinada - raiz = etree.Element('Signature', xmlns='http://www.w3.org/2000/09/xmldsig#') - siginfo = etree.SubElement(raiz, 'SignedInfo') - etree.SubElement(siginfo, 'CanonicalizationMethod', Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315') - etree.SubElement(siginfo, 'SignatureMethod', Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1') - # Tenta achar a tag LoteRps - ref = etree.SubElement(siginfo, 'Reference', URI='#' + lote[0].attrib['Id']) - trans = etree.SubElement(ref, 'Transforms') - etree.SubElement(trans, 'Transform', Algorithm='http://www.w3.org/2000/09/xmldsig#enveloped-signature') - etree.SubElement(trans, 'Transform', Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315') - etree.SubElement(ref, 'DigestMethod', Algorithm='http://www.w3.org/2000/09/xmldsig#sha1') - etree.SubElement(ref, 'DigestValue') - etree.SubElement(raiz, 'SignatureValue') - keyinfo = etree.SubElement(raiz, 'KeyInfo') - etree.SubElement(keyinfo, 'X509Data') - - lote.append(raiz) - - # Escreve no arquivo depois de remover caracteres especiais e parse string - with open('nfse.xml', 'w') as arquivo: - arquivo.write(remover_acentos(etree.tostring(lote, encoding="unicode", pretty_print=False).replace('ns1:', '').replace(':ns1', ''))) - - subprocess.call(['xmlsec1', '--sign', '--pkcs12', self.certificado, '--pwd', self.senha, '--crypto', 'openssl', '--output', 'lote.xml', '--id-attr:Id', tag, 'nfse.xml']) - xml = etree.parse('lote.xml').getroot() + subprocess.call(['xmlsec1', '--sign', '--pkcs12', self.certificado, + '--pwd', self.senha, '--crypto', 'openssl', '--output', + 'nfse.xml', '--id-attr:Id', tag, '--trusted-pem', 'cert.pem', 'nfse.xml']) if retorna_string: - return etree.tostring(xml, encoding="unicode", pretty_print=False) + return open('nfse.xml', 'r').read() else: - return xml + return etree.parse('nfse.xml').getroot() except Exception as e: raise e diff --git a/pynfe/processamento/autorizador_nfse.py b/pynfe/processamento/autorizador_nfse.py index 8390b96..369d2df 100644 --- a/pynfe/processamento/autorizador_nfse.py +++ b/pynfe/processamento/autorizador_nfse.py @@ -1,8 +1,6 @@ -import ipdb from pyxb import BIND from importlib import import_module -# import pynfe.utils.nfse.ginfes.servico_enviar_lote_rps_envio_v03 as servico_enviar_lote_rps_envio_v03 -# import pynfe.utils.nfse.ginfes._tipos as _tipos + class InterfaceAutorizador(): #TODO Colocar raise Exception Not Implemented nos metodos @@ -365,7 +363,7 @@ class SerializacaoGinfes(InterfaceAutorizador): enviarLote = servico_enviar_lote_rps_envio_v03.EnviarLoteRpsEnvio() enviarLote.LoteRps = lote - return enviarLote.toxml("UTF-8", element_name='ns1:EnviarLoteRpsEnvio') + return enviarLote.toxml(element_name='ns1:EnviarLoteRpsEnvio') def cabecalho(self): # info