diff --git a/pytrustnfe/certificado.py b/pytrustnfe/certificado.py
index a4f0241..1971f15 100644
--- a/pytrustnfe/certificado.py
+++ b/pytrustnfe/certificado.py
@@ -4,7 +4,6 @@
from uuid import uuid4
-import os.path
from OpenSSL import crypto
@@ -13,6 +12,13 @@ class Certificado(object):
self.pfx = pfx
self.password = password
+ def save_pfx(self):
+ pfx_temp = '/tmp/' + uuid4().hex
+ arq_temp = open(pfx_temp, 'w')
+ arq_temp.write(self.pfx)
+ arq_temp.close()
+ return pfx_temp
+
def extract_cert_and_key_from_pfx(pfx, password):
pfx = crypto.load_pkcs12(pfx, password)
@@ -25,6 +31,7 @@ def extract_cert_and_key_from_pfx(pfx, password):
return cert, key
+
def save_cert_key(cert, key):
cert_temp = '/tmp/' + uuid4().hex
key_temp = '/tmp/' + uuid4().hex
diff --git a/pytrustnfe/nfe/__init__.py b/pytrustnfe/nfe/__init__.py
index 2a9ccf5..8d24ceb 100644
--- a/pytrustnfe/nfe/__init__.py
+++ b/pytrustnfe/nfe/__init__.py
@@ -6,7 +6,7 @@
import os
from lxml import etree
from .comunicacao import Comunicacao
-from .assinatura import assinar, Assinatura
+from .assinatura import sign_xml, Assinatura
from pytrustnfe import utils
from pytrustnfe.xml import render_xml
@@ -40,7 +40,7 @@ class NFe(Comunicacao):
xml = render_xml(path, 'nfeEnv.xml', **nfe)
xmlElem = etree.fromstring(xml)
- xml_signed = assinar(xmlElem, self.cert, self.key, '#%s' % nfe_id)
+ xml_signed = sign_xml(xmlElem, self.cert, self.key, '#%s' % nfe_id)
xml_response, obj = self._executar_consulta(xml_signed)
diff --git a/pytrustnfe/nfe/assinatura.py b/pytrustnfe/nfe/assinatura.py
index 2b4a53f..eaf6b35 100644
--- a/pytrustnfe/nfe/assinatura.py
+++ b/pytrustnfe/nfe/assinatura.py
@@ -31,27 +31,21 @@ def recursively_empty(e):
return all((recursively_empty(c) for c in e.iterchildren()))
-def assinar(xml, cert, key, reference):
- context = etree.iterwalk(xml)
- for dummy, elem in context:
- parent = elem.getparent()
- if recursively_empty(elem):
- parent.remove(elem)
-
- element = xml.find('{' + xml.nsmap[None] + '}NFe')
+def sign_xml(xml, cert, key):
+ parser = etree.XMLParser(remove_blank_text=True, remove_comments=True)
+ elem = etree.fromstring(xml, parser=parser)
+
signer = XMLSigner(
digest_algorithm=u'sha1', signature_algorithm="rsa-sha1",
- method=methods.enveloped,
+ method=methods.enveloping,
c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
ns = {}
ns[None] = signer.namespaces['ds']
signer.namespaces = ns
- signed_root = signer.sign(element, key=str(key), cert=cert,
- reference_uri=reference)
+ signed_root = signer.sign(elem, key=str(key), cert=cert)
+
+ return etree.tostring(signed_root)
- xml.remove(element)
- xml.append(signed_root)
- return etree.tostring(xml)
class Assinatura(object):
@@ -84,12 +78,12 @@ class Assinatura(object):
self._inicializar_cripto()
try:
doc_xml = libxml2.parseMemory(
- xml.encode('utf-8'), len(xml.encode('utf-8')))
+ xml, len(xml))
signNode = xmlsec.TmplSignature(doc_xml, xmlsec.transformInclC14NId(),
xmlsec.transformRsaSha1Id(), None)
- doc_xml.getLastChild().addChild(signNode)
+ doc_xml.getRootElement().addChild(signNode)
refNode = signNode.addReference(xmlsec.transformSha1Id(),
None, reference, None)
@@ -129,4 +123,4 @@ class Assinatura(object):
return xml
finally:
doc_xml.freeDoc()
- self._finalizar_cripto()
+ # self._finalizar_cripto()
diff --git a/pytrustnfe/nfse/paulistana/__init__.py b/pytrustnfe/nfse/paulistana/__init__.py
index 1883f34..7edc38f 100644
--- a/pytrustnfe/nfse/paulistana/__init__.py
+++ b/pytrustnfe/nfse/paulistana/__init__.py
@@ -5,44 +5,30 @@
import os
import logging
import suds
+from OpenSSL import crypto
+from base64 import b64encode, b64decode
from uuid import uuid4
-from lxml import etree
from pytrustnfe.xml import render_xml, valida_schema, sanitize_response
from pytrustnfe.client import get_authenticated_client
from pytrustnfe.certificado import extract_cert_and_key_from_pfx, save_cert_key
+from pytrustnfe.nfe.assinatura import Assinatura
-from signxml import XMLSigner
-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 = XMLSigner(
- digest_algorithm=u'sha1', signature_algorithm="rsa-sha1",
- method=methods.enveloped,
- c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
- ns = {}
- ns[None] = signer.namespaces['ds']
- signer.namespaces = ns
- signed_root = signer.sign(rps, key=str(key), cert=cert)
-
- root.append(
- signed_root.find('{http://www.w3.org/2000/09/xmldsig#}Signature'))
- elem.remove(rps)
- elem.append(signed_root)
- elem.append(root.find('{http://www.w3.org/2000/09/xmldsig#}Signature'))
- return etree.tostring(elem)
+def sign_tag(certificado, **kwargs):
+ pkcs12 = crypto.load_pkcs12(certificado.pfx, certificado.password)
+ key = pkcs12.get_privatekey()
+ for item in kwargs['nfse']['lista_rps']:
+ signed = crypto.sign(key, item['assinatura'], 'SHA1')
+ item['assinatura'] = b64encode(signed)
def _send(certificado, method, **kwargs):
# A little hack to test
path = os.path.join(os.path.dirname(__file__), 'templates')
+ if method == 'TesteEnvioLoteRPS' or method == 'EnvioLoteRPS':
+ sign_tag(certificado, **kwargs)
+
if method == 'TesteEnvioLoteRPS':
xml = render_xml(path, 'EnvioLoteRPS.xml', **kwargs)
else:
@@ -54,7 +40,9 @@ def _send(certificado, method, **kwargs):
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)
+ pfx_path = certificado.save_pfx()
+ signer = Assinatura(pfx_path, certificado.password)
+ xml_signed = signer.assina_xml(xml, '')
try:
response = getattr(client.service, method)(1, xml_signed)
diff --git a/pytrustnfe/nfse/paulistana/templates/EnvioLoteRPS.xml b/pytrustnfe/nfse/paulistana/templates/EnvioLoteRPS.xml
index 5cc5e67..33a3fcd 100644
--- a/pytrustnfe/nfse/paulistana/templates/EnvioLoteRPS.xml
+++ b/pytrustnfe/nfse/paulistana/templates/EnvioLoteRPS.xml
@@ -4,8 +4,8 @@
{{ nfse.cpf_cnpj }}
false
- 2016-02-08
- 2016-02-08
+ {{ nfse.data_inicio }}
+ {{ nfse.data_fim }}
1
{{ nfse.total_servicos }}
{{ nfse.total_deducoes }}
@@ -22,8 +22,8 @@
{{ rps.data_emissao }}
N
T
- 1000
- 0.00
+ {{ rps.valor_servico }}
+ {{ rps.valor_deducao }}
0.00
0.00
0.00
@@ -40,7 +40,9 @@
{{ rps.tomador.cpf_cnpj }}
{% endif %}
- 23354900
+ {% if rps.tomador.inscricao_municipal -%}
+ {{ rps.tomador.inscricao_municipal }}
+ {% endif %}
{{ rps.tomador.razao_social }}
{{ rps.tomador.tipo_logradouro }}