From 77429ae725adebd4fd66aa75aaf8693ee6d00036 Mon Sep 17 00:00:00 2001 From: Danimar Ribeiro Date: Fri, 5 Aug 2016 15:12:10 -0300 Subject: [PATCH] Metodo para assinar o xml com certificado digital --- pytrustnfe/nfse/paulistana/__init__.py | 84 +++++++++++++++++----- .../nfse/paulistana/templates/CancelamentoNFe.xml | 18 +++++ .../nfse/paulistana/templates/ConsultaCNPJ.xml | 12 ++++ .../templates/ConsultaInformacoesLote.xml | 0 .../nfse/paulistana/templates/ConsultaLote.xml | 10 +++ .../nfse/paulistana/templates/ConsultaNFe.xml | 19 +++++ .../paulistana/templates/ConsultaNFeEmitidas.xml | 0 .../nfse/paulistana/templates/EnvioLoteRPS.xml | 58 +++++++++++++++ pytrustnfe/nfse/paulistana/templates/EnvioRPS.xml | 51 +++++++++++++ .../paulistana/templates/TesteEnvioLoteRPS.xml | 82 --------------------- .../nfse/paulistana/templates/cancelamento.xml | 18 ----- .../nfse/paulistana/templates/consulta_cnpj.xml | 12 ---- .../nfse/paulistana/templates/consulta_lote.xml | 10 --- .../paulistana/templates/consulta_nfse_por_rps.xml | 19 ----- pytrustnfe/nfse/paulistana/templates/envio_rps.xml | 51 ------------- pytrustnfe/xml/__init__.py | 22 ++++++ 16 files changed, 256 insertions(+), 210 deletions(-) create mode 100755 pytrustnfe/nfse/paulistana/templates/CancelamentoNFe.xml create mode 100644 pytrustnfe/nfse/paulistana/templates/ConsultaCNPJ.xml create mode 100644 pytrustnfe/nfse/paulistana/templates/ConsultaInformacoesLote.xml create mode 100755 pytrustnfe/nfse/paulistana/templates/ConsultaLote.xml create mode 100755 pytrustnfe/nfse/paulistana/templates/ConsultaNFe.xml create mode 100644 pytrustnfe/nfse/paulistana/templates/ConsultaNFeEmitidas.xml create mode 100644 pytrustnfe/nfse/paulistana/templates/EnvioLoteRPS.xml create mode 100644 pytrustnfe/nfse/paulistana/templates/EnvioRPS.xml delete mode 100644 pytrustnfe/nfse/paulistana/templates/TesteEnvioLoteRPS.xml delete mode 100755 pytrustnfe/nfse/paulistana/templates/cancelamento.xml delete mode 100644 pytrustnfe/nfse/paulistana/templates/consulta_cnpj.xml delete mode 100755 pytrustnfe/nfse/paulistana/templates/consulta_lote.xml delete mode 100755 pytrustnfe/nfse/paulistana/templates/consulta_nfse_por_rps.xml delete mode 100644 pytrustnfe/nfse/paulistana/templates/envio_rps.xml diff --git a/pytrustnfe/nfse/paulistana/__init__.py b/pytrustnfe/nfse/paulistana/__init__.py index b31e95f..7bc1a87 100644 --- a/pytrustnfe/nfse/paulistana/__init__.py +++ b/pytrustnfe/nfse/paulistana/__init__.py @@ -1,59 +1,107 @@ import os import logging import suds +from uuid import uuid4 from lxml import etree -from pytrustnfe.xml import render_xml, valida_schema +from pytrustnfe.xml import render_xml, valida_schema, sanitize_response from pytrustnfe.client import get_authenticated_client from pytrustnfe.certificado import converte_pfx_pem, save_cert_key +from signxml import xmldsig +from signxml import methods + + +def sign_xml(xml, cert, key): + parser = etree.XMLParser(remove_blank_text=True, remove_comments=True) + elem = etree.fromstring(xml, parser=parser) + + root = etree.Element('root') + rps = elem.find('RPS') + + signer = xmldsig(rps, digest_algorithm=u'sha1') + ns = {} + ns[None] = signer.namespaces['ds'] + signer.namespaces = ns + signed_root = signer.sign( + key=str(key), cert=cert, + algorithm="rsa-sha1", method=methods.enveloped, + c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315') + + root.append( + signed_root.find('{http://www.w3.org/2000/09/xmldsig#}Signature')) + elem.append(signed_root) + elem.append(root.find('{http://www.w3.org/2000/09/xmldsig#}Signature')) + return etree.tostring(elem) + + def _send(certificado, method, **kwargs): # A little hack to test path = os.path.join(os.path.dirname(__file__), 'templates') - if method == 'teste_envio_lote_rps': - xml = render_xml(path, 'envio_lote_rps.xml', **kwargs) + if method == 'TesteEnvioLoteRPS': + xml = render_xml(path, 'EnvioLoteRPS.xml', **kwargs) else: xml = render_xml(path, '%s.xml' % method, **kwargs) - base_url = 'https://nfe.prefeitura.sp.gov.br/ws/lotenfe.asmx?wsdl' cert, key = converte_pfx_pem(certificado.pfx, certificado.password) - cert, key = save_cert_key(cert, key)eh - client = get_authenticated_client(base_url, cert, key) + cert_path, key_path = save_cert_key(cert, key) + client = get_authenticated_client(base_url, cert_path, key_path) + + xml_signed = sign_xml(xml, cert, key) try: - response = getattr(client.service, method)(1, xml) + response = getattr(client.service, method)(1, xml_signed) except suds.WebFault, e: - response = e.fault.faultstring - return response + return { + 'sent_xml': xml_signed, + 'received_xml': e.fault.faultstring, + 'object': None + } + + response, obj = sanitize_response(response) + return { + 'sent_xml': xml_signed, + 'received_xml': response, + 'object': obj + } def envio_rps(certificado, **kwargs): - return _send(certificado, 'envio_rps', **kwargs) + return _send(certificado, 'EnvioRPS', **kwargs) + def envio_lote_rps(certificado, **kwargs): - return _send(certificado, 'envio_lote_rps', **kwargs) + return _send(certificado, 'EnvioLoteRPS', **kwargs) + def teste_envio_lote_rps(certificado, **kwargs): return _send(certificado, 'TesteEnvioLoteRPS', **kwargs) + def cancelamento_nfe(certificado, **kwargs): - return _send(certificado, 'cancelamento_n_fe', **kwargs) + return _send(certificado, 'CancelamentoNFe', **kwargs) + def consulta_nfe(certificado, **kwargs): - return _send('consulta_n_fe', **kwargs) + return _send('ConsultaNFe', **kwargs) + def consulta_nfe_recebidas(certificado, **kwargs): - return _send('consulta_n_fe_recebidas', **kwargs) + return _send('ConsultaNFeRecebidas', **kwargs) + def consulta_nfe_emitidas(data=None): - return _send('consulta_n_fe_emitidas', data) + return _send('ConsultaNFeEmitidas', data) + def consulta_lote(data=None): - return _send('consulta_lote', data) + return _send('ConsultaLote', data) + def consulta_informacoes_lote(data=None): - return _send('consulta_informacoes_lote', data) + return _send('ConsultaInformacoesLote', data) + def consulta_cnpj(data=None): - return _send('consulta_cnpj', data) + return _send('ConsultaCNPJ', data) diff --git a/pytrustnfe/nfse/paulistana/templates/CancelamentoNFe.xml b/pytrustnfe/nfse/paulistana/templates/CancelamentoNFe.xml new file mode 100755 index 0000000..886e0a6 --- /dev/null +++ b/pytrustnfe/nfse/paulistana/templates/CancelamentoNFe.xml @@ -0,0 +1,18 @@ + + + {{ cancelamento.cidade }} + {{ cancelamento.cpf_cnpj }} + {{ cancelamento.transacao }} + 1 + + + + {{ cancelamento.inscricao_municipal }} + {{ cancelamento.nota_id }} + {{ cancelamento.assinatura }} + {{ cancelamento.motivo }} + + + diff --git a/pytrustnfe/nfse/paulistana/templates/ConsultaCNPJ.xml b/pytrustnfe/nfse/paulistana/templates/ConsultaCNPJ.xml new file mode 100644 index 0000000..9b4bbcb --- /dev/null +++ b/pytrustnfe/nfse/paulistana/templates/ConsultaCNPJ.xml @@ -0,0 +1,12 @@ + + + + {{ nfse.cpf_cnpj }} + + + + 08944335000170 + + diff --git a/pytrustnfe/nfse/paulistana/templates/ConsultaInformacoesLote.xml b/pytrustnfe/nfse/paulistana/templates/ConsultaInformacoesLote.xml new file mode 100644 index 0000000..e69de29 diff --git a/pytrustnfe/nfse/paulistana/templates/ConsultaLote.xml b/pytrustnfe/nfse/paulistana/templates/ConsultaLote.xml new file mode 100755 index 0000000..24afc5d --- /dev/null +++ b/pytrustnfe/nfse/paulistana/templates/ConsultaLote.xml @@ -0,0 +1,10 @@ + + + {{ consulta.cidade }} + {{ consulta.cpf_cnpj }} + 1 + {{ consulta.lote }} + + \ No newline at end of file diff --git a/pytrustnfe/nfse/paulistana/templates/ConsultaNFe.xml b/pytrustnfe/nfse/paulistana/templates/ConsultaNFe.xml new file mode 100755 index 0000000..676a6fc --- /dev/null +++ b/pytrustnfe/nfse/paulistana/templates/ConsultaNFe.xml @@ -0,0 +1,19 @@ + + + {{ consulta.cidade }} + {{ consulta.cpf_cnpj }} + {{ consulta.transacao }} + 1 + + + + + {{ consulta.inscricao_municipal }} + {{ consulta.rps_id }} + {{ consulta.serie_prestacao }} + + + + diff --git a/pytrustnfe/nfse/paulistana/templates/ConsultaNFeEmitidas.xml b/pytrustnfe/nfse/paulistana/templates/ConsultaNFeEmitidas.xml new file mode 100644 index 0000000..e69de29 diff --git a/pytrustnfe/nfse/paulistana/templates/EnvioLoteRPS.xml b/pytrustnfe/nfse/paulistana/templates/EnvioLoteRPS.xml new file mode 100644 index 0000000..5cc5e67 --- /dev/null +++ b/pytrustnfe/nfse/paulistana/templates/EnvioLoteRPS.xml @@ -0,0 +1,58 @@ + + + + {{ nfse.cpf_cnpj }} + + false + 2016-02-08 + 2016-02-08 + 1 + {{ nfse.total_servicos }} + {{ nfse.total_deducoes }} + + {% for rps in nfse.lista_rps -%} + + {{ rps.assinatura }} + + {{ rps.prestador.inscricao_municipal }} + {{ rps.serie }} + {{ rps.numero }} + + RPS + {{ rps.data_emissao }} + N + T + 1000 + 0.00 + 0.00 + 0.00 + 0.00 + 0.00 + 0.00 + {{ rps.codigo_atividade }} + {{ rps.aliquota_atividade }} + false + + {% if rps.tomador.tipo_cpfcnpj == 1 -%} + {{ rps.tomador.cpf_cnpj }} + {% endif %} + {% if rps.tomador.tipo_cpfcnpj == 2 -%} + {{ rps.tomador.cpf_cnpj }} + {% endif %} + + 23354900 + {{ rps.tomador.razao_social }} + + {{ rps.tomador.tipo_logradouro }} + {{ rps.tomador.logradouro }} + {{ rps.tomador.numero }} + {{ rps.tomador.complemento }} + {{ rps.tomador.bairro }} + {{ rps.tomador.cidade }} + {{ rps.tomador.uf }} + {{ rps.tomador.cep }} + + {{ rps.descricao }} + + {% endfor %} + diff --git a/pytrustnfe/nfse/paulistana/templates/EnvioRPS.xml b/pytrustnfe/nfse/paulistana/templates/EnvioRPS.xml new file mode 100644 index 0000000..d828534 --- /dev/null +++ b/pytrustnfe/nfse/paulistana/templates/EnvioRPS.xml @@ -0,0 +1,51 @@ + + + + {{ nfse.cpf_cnpj }} + + + {% for rps in nfse.lista_rps -%} + + {{ rps.assinatura }} + + {{ rps.prestador.inscricao_municipal }} + {{ rps.serie }} + {{ rps.numero }} + + RPS-M + {{ rps.data_emissao }} + N + T + {{ nfse.total_servicos }} + {{ nfse.total_deducoes }} + {{ rps.valor_pis }} + {{ rps.valor_cofins }} + {{ rps.valor_inss }} + {{ rps.valor_pis }} + {{ rps.valor_csll }} + {{ rps.codigo_atividade }} + {{ rps.aliquota_atividade }} + false + + {% if rps.tomador.tipo_cpfcnpj == 1 -%} + {{ rps.tomador.cpf_cnpj }} + {% endif %} + {% if rps.tomador.tipo_cpfcnpj == 2 -%} + {{ rps.tomador.cpf_cnpj }} + {% endif %} + + {{ rps.tomador.razao_social }} + + {{ rps.tomador.tipo_logradouro }} + {{ rps.tomador.logradouro }} + {{ rps.tomador.numero }} + {{ rps.tomador.complemento }} + {{ rps.tomador.bairro }} + {{ rps.tomador.cidade }} + {{ rps.tomador.uf }} + {{ rps.tomador.cep }} + + {{ rps.descricao }} + {% endfor %} + + diff --git a/pytrustnfe/nfse/paulistana/templates/TesteEnvioLoteRPS.xml b/pytrustnfe/nfse/paulistana/templates/TesteEnvioLoteRPS.xml deleted file mode 100644 index f657b75..0000000 --- a/pytrustnfe/nfse/paulistana/templates/TesteEnvioLoteRPS.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - {{ nfse.cpf_cnpj }} - - false - 2016-02-08 - 2016-02-08 - 1 - {{ nfse.total_servicos }} - {{ nfse.total_deducoes }} - - {% for rps in nfse.lista_rps -%} - - 31000000OL03 00000000000120070103TNN00000000205000000000000050000002658100013167474254 - - {{ rps.prestador.inscricao_municipal }} - {{ rps.serie }} - {{ rps.numero }} - - RPS - {{ rps.data_emissao }} - N - T - 1000 - 0.00 - 0.00 - 0.00 - 0.00 - 0.00 - 0.00 - {{ rps.codigo_atividade }} - {{ rps.aliquota_atividade }} - false - - {% if rps.tomador.tipo_cpfcnpj == 1 -%} - {{ rps.tomador.cpf_cnpj }} - {% endif %} - {% if rps.tomador.tipo_cpfcnpj == 2 -%} - {{ rps.tomador.cpf_cnpj }} - {% endif %} - - 23354900 - {{ rps.tomador.razao_social }} - - {{ rps.tomador.tipo_logradouro }} - {{ rps.tomador.logradouro }} - {{ rps.tomador.numero }} - {{ rps.tomador.complemento }} - {{ rps.tomador.bairro }} - {{ rps.tomador.cidade }} - {{ rps.tomador.uf }} - {{ rps.tomador.cep }} - - {{ rps.descricao }} - - - - - - - - - - - -AkHyCjCwkANg3aRAnltAXR1YQ4c= - - - -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 - - - - - {% endfor %} - diff --git a/pytrustnfe/nfse/paulistana/templates/cancelamento.xml b/pytrustnfe/nfse/paulistana/templates/cancelamento.xml deleted file mode 100755 index 886e0a6..0000000 --- a/pytrustnfe/nfse/paulistana/templates/cancelamento.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - {{ cancelamento.cidade }} - {{ cancelamento.cpf_cnpj }} - {{ cancelamento.transacao }} - 1 - - - - {{ cancelamento.inscricao_municipal }} - {{ cancelamento.nota_id }} - {{ cancelamento.assinatura }} - {{ cancelamento.motivo }} - - - diff --git a/pytrustnfe/nfse/paulistana/templates/consulta_cnpj.xml b/pytrustnfe/nfse/paulistana/templates/consulta_cnpj.xml deleted file mode 100644 index 9b4bbcb..0000000 --- a/pytrustnfe/nfse/paulistana/templates/consulta_cnpj.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - {{ nfse.cpf_cnpj }} - - - - 08944335000170 - - diff --git a/pytrustnfe/nfse/paulistana/templates/consulta_lote.xml b/pytrustnfe/nfse/paulistana/templates/consulta_lote.xml deleted file mode 100755 index 24afc5d..0000000 --- a/pytrustnfe/nfse/paulistana/templates/consulta_lote.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - {{ consulta.cidade }} - {{ consulta.cpf_cnpj }} - 1 - {{ consulta.lote }} - - \ No newline at end of file diff --git a/pytrustnfe/nfse/paulistana/templates/consulta_nfse_por_rps.xml b/pytrustnfe/nfse/paulistana/templates/consulta_nfse_por_rps.xml deleted file mode 100755 index 676a6fc..0000000 --- a/pytrustnfe/nfse/paulistana/templates/consulta_nfse_por_rps.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - {{ consulta.cidade }} - {{ consulta.cpf_cnpj }} - {{ consulta.transacao }} - 1 - - - - - {{ consulta.inscricao_municipal }} - {{ consulta.rps_id }} - {{ consulta.serie_prestacao }} - - - - diff --git a/pytrustnfe/nfse/paulistana/templates/envio_rps.xml b/pytrustnfe/nfse/paulistana/templates/envio_rps.xml deleted file mode 100644 index d828534..0000000 --- a/pytrustnfe/nfse/paulistana/templates/envio_rps.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - {{ nfse.cpf_cnpj }} - - - {% for rps in nfse.lista_rps -%} - - {{ rps.assinatura }} - - {{ rps.prestador.inscricao_municipal }} - {{ rps.serie }} - {{ rps.numero }} - - RPS-M - {{ rps.data_emissao }} - N - T - {{ nfse.total_servicos }} - {{ nfse.total_deducoes }} - {{ rps.valor_pis }} - {{ rps.valor_cofins }} - {{ rps.valor_inss }} - {{ rps.valor_pis }} - {{ rps.valor_csll }} - {{ rps.codigo_atividade }} - {{ rps.aliquota_atividade }} - false - - {% if rps.tomador.tipo_cpfcnpj == 1 -%} - {{ rps.tomador.cpf_cnpj }} - {% endif %} - {% if rps.tomador.tipo_cpfcnpj == 2 -%} - {{ rps.tomador.cpf_cnpj }} - {% endif %} - - {{ rps.tomador.razao_social }} - - {{ rps.tomador.tipo_logradouro }} - {{ rps.tomador.logradouro }} - {{ rps.tomador.numero }} - {{ rps.tomador.complemento }} - {{ rps.tomador.bairro }} - {{ rps.tomador.cidade }} - {{ rps.tomador.uf }} - {{ rps.tomador.cep }} - - {{ rps.descricao }} - {% endfor %} - - diff --git a/pytrustnfe/xml/__init__.py b/pytrustnfe/xml/__init__.py index 8f5c95a..145731f 100644 --- a/pytrustnfe/xml/__init__.py +++ b/pytrustnfe/xml/__init__.py @@ -1,5 +1,10 @@ import os.path +import unicodedata from lxml import etree + +from StringIO import StringIO +from lxml import objectify +import xml.etree.ElementTree as ET from jinja2 import Environment, FileSystemLoader from . import filters @@ -22,6 +27,23 @@ def render_xml(path, template_name, **nfe): return etree.tostring(elem) +def sanitize_response(response): + response = unicode(response) + response = unicodedata.normalize('NFKD', response).encode('ascii', + 'ignore') + + tree = etree.fromstring(response) + # Remove namespaces inuteis na resposta + for elem in tree.getiterator(): + if not hasattr(elem.tag, 'find'): + continue + i = elem.tag.find('}') + if i >= 0: + elem.tag = elem.tag[i+1:] + objectify.deannotate(tree, cleanup_namespaces=True) + return response, objectify.fromstring(etree.tostring(tree)) + + def valida_schema(xml, arquivo_xsd): '''Função que valida um XML usando lxml do Python via arquivo XSD''' # Carrega o esquema XML do arquivo XSD