Browse Source

Metodo para assinar o xml com certificado digital

tags/0.1.5
Danimar Ribeiro 10 years ago
parent
commit
77429ae725
  1. 84
      pytrustnfe/nfse/paulistana/__init__.py
  2. 0
      pytrustnfe/nfse/paulistana/templates/CancelamentoNFe.xml
  3. 0
      pytrustnfe/nfse/paulistana/templates/ConsultaCNPJ.xml
  4. 0
      pytrustnfe/nfse/paulistana/templates/ConsultaInformacoesLote.xml
  5. 0
      pytrustnfe/nfse/paulistana/templates/ConsultaLote.xml
  6. 0
      pytrustnfe/nfse/paulistana/templates/ConsultaNFe.xml
  7. 0
      pytrustnfe/nfse/paulistana/templates/ConsultaNFeEmitidas.xml
  8. 58
      pytrustnfe/nfse/paulistana/templates/EnvioLoteRPS.xml
  9. 0
      pytrustnfe/nfse/paulistana/templates/EnvioRPS.xml
  10. 82
      pytrustnfe/nfse/paulistana/templates/TesteEnvioLoteRPS.xml
  11. 22
      pytrustnfe/xml/__init__.py

84
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)

0
pytrustnfe/nfse/paulistana/templates/cancelamento.xml → pytrustnfe/nfse/paulistana/templates/CancelamentoNFe.xml

0
pytrustnfe/nfse/paulistana/templates/consulta_cnpj.xml → pytrustnfe/nfse/paulistana/templates/ConsultaCNPJ.xml

0
pytrustnfe/nfse/paulistana/templates/ConsultaInformacoesLote.xml

0
pytrustnfe/nfse/paulistana/templates/consulta_lote.xml → pytrustnfe/nfse/paulistana/templates/ConsultaLote.xml

0
pytrustnfe/nfse/paulistana/templates/consulta_nfse_por_rps.xml → pytrustnfe/nfse/paulistana/templates/ConsultaNFe.xml

0
pytrustnfe/nfse/paulistana/templates/ConsultaNFeEmitidas.xml

58
pytrustnfe/nfse/paulistana/templates/EnvioLoteRPS.xml

@ -0,0 +1,58 @@
<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">
<Cabecalho Versao="1" xmlns="">
<CPFCNPJRemetente>
<CNPJ>{{ nfse.cpf_cnpj }}</CNPJ>
</CPFCNPJRemetente>
<transacao>false</transacao>
<dtInicio>2016-02-08</dtInicio>
<dtFim>2016-02-08</dtFim>
<QtdRPS>1</QtdRPS>
<ValorTotalServicos>{{ nfse.total_servicos }}</ValorTotalServicos>
<ValorTotalDeducoes>{{ nfse.total_deducoes }}</ValorTotalDeducoes>
</Cabecalho>
{% for rps in nfse.lista_rps -%}
<RPS xmlns="">
<Assinatura>{{ rps.assinatura }}</Assinatura>
<ChaveRPS>
<InscricaoPrestador>{{ rps.prestador.inscricao_municipal }}</InscricaoPrestador>
<SerieRPS>{{ rps.serie }}</SerieRPS>
<NumeroRPS>{{ rps.numero }}</NumeroRPS>
</ChaveRPS>
<TipoRPS>RPS</TipoRPS>
<DataEmissao>{{ rps.data_emissao }}</DataEmissao>
<StatusRPS>N</StatusRPS>
<TributacaoRPS>T</TributacaoRPS>
<ValorServicos>1000</ValorServicos>
<ValorDeducoes>0.00</ValorDeducoes>
<ValorPIS>0.00</ValorPIS>
<ValorCOFINS>0.00</ValorCOFINS>
<ValorINSS>0.00</ValorINSS>
<ValorIR>0.00</ValorIR>
<ValorCSLL>0.00</ValorCSLL>
<CodigoServico>{{ rps.codigo_atividade }}</CodigoServico>
<AliquotaServicos>{{ rps.aliquota_atividade }}</AliquotaServicos>
<ISSRetido>false</ISSRetido>
<CPFCNPJTomador>
{% if rps.tomador.tipo_cpfcnpj == 1 -%}
<CPF>{{ rps.tomador.cpf_cnpj }}</CPF>
{% endif %}
{% if rps.tomador.tipo_cpfcnpj == 2 -%}
<CNPJ>{{ rps.tomador.cpf_cnpj }}</CNPJ>
{% endif %}
</CPFCNPJTomador>
<InscricaoMunicipalTomador>23354900</InscricaoMunicipalTomador>
<RazaoSocialTomador>{{ rps.tomador.razao_social }}</RazaoSocialTomador>
<EnderecoTomador>
<TipoLogradouro>{{ rps.tomador.tipo_logradouro }}</TipoLogradouro>
<Logradouro>{{ rps.tomador.logradouro }}</Logradouro>
<NumeroEndereco>{{ rps.tomador.numero }}</NumeroEndereco>
<ComplementoEndereco>{{ rps.tomador.complemento }}</ComplementoEndereco>
<Bairro>{{ rps.tomador.bairro }}</Bairro>
<Cidade>{{ rps.tomador.cidade }}</Cidade>
<UF>{{ rps.tomador.uf }}</UF>
<CEP>{{ rps.tomador.cep }}</CEP>
</EnderecoTomador>
<Discriminacao>{{ rps.descricao }}</Discriminacao>
</RPS>
{% endfor %}
</PedidoEnvioLoteRPS>

0
pytrustnfe/nfse/paulistana/templates/envio_rps.xml → pytrustnfe/nfse/paulistana/templates/EnvioRPS.xml

82
pytrustnfe/nfse/paulistana/templates/TesteEnvioLoteRPS.xml

@ -1,82 +0,0 @@
<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">
<Cabecalho xmlns="" Versao="1">
<CPFCNPJRemetente>
<CNPJ>{{ nfse.cpf_cnpj }}</CNPJ>
</CPFCNPJRemetente>
<transacao>false</transacao>
<dtInicio>2016-02-08</dtInicio>
<dtFim>2016-02-08</dtFim>
<QtdRPS>1</QtdRPS>
<ValorTotalServicos>{{ nfse.total_servicos }}</ValorTotalServicos>
<ValorTotalDeducoes>{{ nfse.total_deducoes }}</ValorTotalDeducoes>
</Cabecalho>
{% for rps in nfse.lista_rps -%}
<RPS xmlns="">
<Assinatura>31000000OL03 00000000000120070103TNN00000000205000000000000050000002658100013167474254</Assinatura>
<ChaveRPS>
<InscricaoPrestador>{{ rps.prestador.inscricao_municipal }}</InscricaoPrestador>
<SerieRPS>{{ rps.serie }}</SerieRPS>
<NumeroRPS>{{ rps.numero }}</NumeroRPS>
</ChaveRPS>
<TipoRPS>RPS</TipoRPS>
<DataEmissao>{{ rps.data_emissao }}</DataEmissao>
<StatusRPS>N</StatusRPS>
<TributacaoRPS>T</TributacaoRPS>
<ValorServicos>1000</ValorServicos>
<ValorDeducoes>0.00</ValorDeducoes>
<ValorPIS>0.00</ValorPIS>
<ValorCOFINS>0.00</ValorCOFINS>
<ValorINSS>0.00</ValorINSS>
<ValorIR>0.00</ValorIR>
<ValorCSLL>0.00</ValorCSLL>
<CodigoServico>{{ rps.codigo_atividade }}</CodigoServico>
<AliquotaServicos>{{ rps.aliquota_atividade }}</AliquotaServicos>
<ISSRetido>false</ISSRetido>
<CPFCNPJTomador>
{% if rps.tomador.tipo_cpfcnpj == 1 -%}
<CPF>{{ rps.tomador.cpf_cnpj }}</CPF>
{% endif %}
{% if rps.tomador.tipo_cpfcnpj == 2 -%}
<CNPJ>{{ rps.tomador.cpf_cnpj }}</CNPJ>
{% endif %}
</CPFCNPJTomador>
<InscricaoMunicipalTomador>23354900</InscricaoMunicipalTomador>
<RazaoSocialTomador>{{ rps.tomador.razao_social }}</RazaoSocialTomador>
<EnderecoTomador>
<TipoLogradouro>{{ rps.tomador.tipo_logradouro }}</TipoLogradouro>
<Logradouro>{{ rps.tomador.logradouro }}</Logradouro>
<NumeroEndereco>{{ rps.tomador.numero }}</NumeroEndereco>
<ComplementoEndereco>{{ rps.tomador.complemento }}</ComplementoEndereco>
<Bairro>{{ rps.tomador.bairro }}</Bairro>
<Cidade>{{ rps.tomador.cidade }}</Cidade>
<UF>{{ rps.tomador.uf }}</UF>
<CEP>{{ rps.tomador.cep }}</CEP>
</EnderecoTomador>
<Discriminacao>{{ rps.descricao }}</Discriminacao>
</RPS>
<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>AkHyCjCwkANg3aRAnltAXR1YQ4c=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>
IkLB0qfZLDuTNXNB83tXXsZ2TFNK9X0l7gq8jRCOcwhit059iF5gNHfmuM4NoUhyhZ+rC6UGn9lSMv1A35lofsplIuWUJO13yPtHsxaY6/rP9DTB4Ve3ihzwrEkpenANoEU1C5wLenX0lRtYc1k3fWeDmZUvv+b/M81pwoPBL8k=
</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>
MIIFUzCCBDugAwIBAgIQSUJS8pELZyjasDkgGzKm0TANBgkqhkiG9w0BAQUFADBuMQswCQYDVQQGEwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDEsMCoGA1UECxMjU2VjcmV0YXJpYSBkYSBSZWNlaXRhIEZlZGVyYWwgLSBTUkYxHDAaBgNVBAMTE0FDIENlcnRpU2lnbiBTUkYgVjMwHhcNMDYwNzE5MDAwMDAwWhcNMDkwNzE4MjM1OTU5WjCB1DELMAkGA1UEBhMCQlIxEzARBgNVBAoUCklDUC1CcmFzaWwxKjAoBgNVBAsTIVNlY3JldGFyaWEgZGEgUmVjZWl0YSBGZWRlcmFsLVNSRjETMBEGA1UECxQKU1JGIGUtQ05QSjELMAkGA1UECBMCUkoxFzAVBgNVBAcUDlJJTyBERSBKQU5FSVJPMUkwRwYDVQQDE0BUSVBMQU4gQ09OU1VMVE9SSUEgRSBTRVJWSUNPUyBFTSBJTkZPUk1BVElDQSBMVERBOjA0NjQyNTU0MDAwMTQzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCx86LAoJRVmtQMzmtdWpyNgKy200+bwjtz/TuywNcTjvfw7qHFGIgTjipmuZ3zhX28CgYLYXp3tj1Dfh2B7EhjHdLJPfvoF4MgbN/dQGXmGpMpF5cNxYusOGCZiyASvI7Gqt/xE4xLSIalNr6kF6CaPLkpFgTNNe+WQkG0fMqsQQIDAQABo4ICCDCCAgQwgbEGA1UdEQSBqTCBpqA/BgVgTAEDBKA2DDQyNDA3MTk3NjA3MTM4NTM3Nzg2MDAwMDAwMDAwMDAwMDAwMDAwOTI5OTA2MjFDTkggIFJKoB8GBWBMAQMCoBYMFEZFUk5BTkRPIFNJTFZBIEJSQUdBoBkGBWBMAQMDoBAMDjA0NjQyNTU0MDAwMTQzoBEGBWBMAQMHoAgMBjIzOTU0OIEUZmJyYWdhQHRpcGxhbi5jb20uYnIwCQYDVR0TBAIwADBiBgNVHR8EWzBZMFegVaBThlFodHRwOi8vaWNwLWJyYXNpbC5jZXJ0aXNpZ24uY29tLmJyL3JlcG9zaXRvcmlvL2xjci9BQ0NlcnRpU2lnblNSRlYzL0xhdGVzdENSTC5jcmwwHwYDVR0jBBgwFoAU9p1ZXf6/xXLN3c7ELmYbLu4Iz3YwDgYDVR0PAQH/BAQDAgXgMFUGA1UdIAROMEwwSgYGYEwBAgMGMEAwPgYIKwYBBQUHAgEWMmh0dHA6Ly9pY3AtYnJhc2lsLmNlcnRpc2lnbi5jb20uYnIvcmVwb3NpdG9yaW8vZHBjMB0GA1UdJQQWMBQGCCsGAQUFBwMEBggrBgEFBQcDAjA4BggrBgEFBQcBAQQsMCowKAYIKwYBBQUHMAGGHGh0dHA6Ly9vY3NwLmNlcnRpc2lnbi5jb20uYnIwDQYJKoZIhvcNAQEFBQADggEBAC5w/CBXAykvPSbBGf+u0UPcWVJATL2ix0hCfNUVtHaCjMz8hRjgYqmhpefzDm2LCTvoCPzG6XQBYxAmnDhX1f/gyjHz+E1xJg451qtqcyCJ9861o9R2bHd4zR0DuyxCNGOTiYJ4Gc/Xa4xqECorAx5ktkk1T/HOc1K/ntRGpdL+llsO/jqSRmTOnRgdeNHcKkyXsOgL5BwxxgGNuIyqirgGXW0by4Io1GnSXtixxfvEOnqOicxBY6AcVS9HHuhmOBYiK9skAUp0Sm2v41hpsC8uIkfUeRxsJIp2CNZ4DjoyfmKwNLMCRZQAKpwMXyyHZlX1a4o/9iGTszNeeShw61g=
</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
{% endfor %}
</PedidoEnvioLoteRPS>

22
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

Loading…
Cancel
Save