diff --git a/pytrustnfe/nfe/__init__.py b/pytrustnfe/nfe/__init__.py index 0c2b0a7..824284b 100644 --- a/pytrustnfe/nfe/__init__.py +++ b/pytrustnfe/nfe/__init__.py @@ -10,6 +10,7 @@ from pytrustnfe.xml import render_xml from pytrustnfe.utils import CabecalhoSoap from pytrustnfe.utils import gerar_chave, ChaveNFe from pytrustnfe.Servidores import localizar_url +import re def _build_header(**kwargs): @@ -31,7 +32,9 @@ def _generate_nfe_id(**kwargs): 'codigo': item['infNFe']['ide']['cNF'], } chave = ChaveNFe(**vals) - item['infNFe']['Id'] = gerar_chave(chave, 'NFe') + chave_nfe = gerar_chave(chave, 'NFe') + item['infNFe']['Id'] = chave_nfe + item['infNFe']['ide']['cDV'] = chave_nfe[len(chave_nfe) - 1:] def _send(certificado, method, **kwargs): @@ -39,13 +42,15 @@ def _send(certificado, method, **kwargs): xml = render_xml(path, '%s.xml' % method, **kwargs) xml = ']>' + xml - + xml = xml.replace('\n', '') pfx_path = certificado.save_pfx() signer = Assinatura(pfx_path, certificado.password) - xml_signed = signer.assina_xml(xml, kwargs['NFes'][0]['infNFe']['Id']) + xml_signed = signer.assina_xml_nota(xml, kwargs['NFes'][0]['infNFe']['Id']) xml_signed = xml_signed.replace( '\n\n]>\n', '') + print xml_signed + xml_signed = xml_signed.replace('\n', '') url = localizar_url(0, 'RS') cabecalho = _build_header(**kwargs) diff --git a/pytrustnfe/nfe/assinatura.py b/pytrustnfe/nfe/assinatura.py index 81831fc..ad531b0 100644 --- a/pytrustnfe/nfe/assinatura.py +++ b/pytrustnfe/nfe/assinatura.py @@ -86,3 +86,54 @@ class Assinatura(object): finally: doc_xml.freeDoc() # self._finalizar_cripto() + + def assina_xml_nota(self, xml, reference): + self._checar_certificado() + self._inicializar_cripto() + try: + doc_xml = libxml2.parseMemory( + xml, len(xml)) + signNode = xmlsec.TmplSignature(doc_xml, + xmlsec.transformInclC14NId(), + xmlsec.transformRsaSha1Id(), None) + doc_xml.getRootElement().get_last().addChild(signNode) + refNode = signNode.addReference(xmlsec.transformSha1Id(), + None, '#' + str(reference), None) + + refNode.addTransform(xmlsec.transformEnvelopedId()) + refNode.addTransform(xmlsec.transformInclC14NId()) + keyInfoNode = signNode.ensureKeyInfo() + keyInfoNode.addX509Data() + + dsig_ctx = xmlsec.DSigCtx() + chave = xmlsec.cryptoAppKeyLoad(filename=str(self.arquivo), + format=xmlsec.KeyDataFormatPkcs12, + pwd=str(self.senha), + pwdCallback=None, + pwdCallbackCtx=None) + + dsig_ctx.signKey = chave + dsig_ctx.sign(signNode) + + status = dsig_ctx.status + dsig_ctx.destroy() + + if status != xmlsec.DSigStatusSucceeded: + raise RuntimeError( + 'Erro ao realizar a assinatura do arquivo; status: "' + + str(status) + + '"') + + xpath = doc_xml.xpathNewContext() + xpath.xpathRegisterNs('sig', NAMESPACE_SIG) + certificados = xpath.xpathEval( + '//sig:X509Data/sig:X509Certificate') + for i in range(len(certificados) - 1): + certificados[i].unlinkNode() + certificados[i].freeNode() + + xml = doc_xml.serialize() + return xml + finally: + doc_xml.freeDoc() + # self._finalizar_cripto()