diff --git a/pytrustnfe/nfe/assinatura.py b/pytrustnfe/nfe/assinatura.py index dea76d4..235057c 100644 --- a/pytrustnfe/nfe/assinatura.py +++ b/pytrustnfe/nfe/assinatura.py @@ -13,7 +13,7 @@ class Assinatura(object): self.arquivo = arquivo self.senha = senha - def assina_xml(self, xml_element, reference): + def assina_xml(self, xml_element, reference, getchildren=False): cert, key = extract_cert_and_key_from_pfx(self.arquivo, self.senha) for element in xml_element.iter("*"): @@ -26,8 +26,7 @@ class Assinatura(object): digest_algorithm="sha1", c14n_algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments", ) - #import ipdb - #ipdb.set_trace() + ns = {} ns[None] = signer.namespaces["ds"] signer.namespaces = ns @@ -41,8 +40,11 @@ class Assinatura(object): signature = signed_root.findall( ".//{http://www.w3.org/2000/09/xmldsig#}Signature" ) - - if element_signed is not None and signature is not None: + + if getchildren and element_signed is not None and signature is not None: element_intern = element_signed.getchildren() element_intern.append(signature) + elif element_signed is not None and signature is not None: + element_extern = element_signed.getparent() + element_extern.append(signature) return etree.tostring(signed_root, encoding=str) diff --git a/pytrustnfe/nfse/natal/__init__.py b/pytrustnfe/nfse/natal/__init__.py index 8466a0a..ba70b36 100644 --- a/pytrustnfe/nfse/natal/__init__.py +++ b/pytrustnfe/nfse/natal/__init__.py @@ -13,6 +13,7 @@ from requests.packages.urllib3 import disable_warnings from pytrustnfe.xml import render_xml, sanitize_response from pytrustnfe.certificado import extract_cert_and_key_from_pfx, save_cert_key from pytrustnfe.nfe.assinatura import Assinatura +from lxml import etree def sign_rps(path, certificado, **kwargs): @@ -24,7 +25,7 @@ def sign_rps(path, certificado, **kwargs): signer = Assinatura(certificado.pfx, certificado.password) lote += signer.assina_xml( - xml_rps, f"rps:{item.get('numero')}{item.get('serie')}" + xml_rps, f"rps:{item.get('numero')}{item.get('serie')}", getchildren=True ) return lote return "" @@ -32,6 +33,10 @@ def sign_rps(path, certificado, **kwargs): def _render(certificado, method, **kwargs): path = os.path.join(os.path.dirname(__file__), "templates") + parser = etree.XMLParser( + remove_blank_text=True, remove_comments=True, strip_cdata=False + ) + lote = "" if method == "RecepcionarLoteRps": lote = sign_rps(path, certificado, **kwargs) @@ -41,7 +46,8 @@ def _render(certificado, method, **kwargs): signer = Assinatura(certificado.pfx, certificado.password) referencia = "lote" - xml_send = signer.assina_xml(xml_send, f"{referencia}") + xml_send = signer.assina_xml(etree.fromstring( + xml_send, parser=parser), f"{referencia}", getchildren=True) return xml_send diff --git a/pytrustnfe/xml/__init__.py b/pytrustnfe/xml/__init__.py index a98283d..c6d21d9 100644 --- a/pytrustnfe/xml/__init__.py +++ b/pytrustnfe/xml/__init__.py @@ -42,7 +42,7 @@ def render_xml(path, template_name, remove_empty, **nfe): if recursively_empty(elem): parent.remove(elem) return root - return root + return etree.tostring(root, encoding=str) def sanitize_response(response): diff --git a/tests/XMLs/natal_sent_xml.xml b/tests/XMLs/natal_sent_xml.xml index 22a56c4..8cad55c 100644 --- a/tests/XMLs/natal_sent_xml.xml +++ b/tests/XMLs/natal_sent_xml.xml @@ -1,13 +1,154 @@ -123809070000190214399211UNICA12020-01-27911121.0020.0001.076209100Sistema NFSe2408102238090700001902143992SERVICOS DE TIAV AMINTAS3755SALA 32Lagoa NovaRN590758104132095554SUPORTE@EMAIL.COM.BRLEONIR128Lagoa NovaBH1231231313leonir@yahoo.com.br3159506z7+372qFhKwwj41AkJ3chbHEYGM=JgW5SbS50rDeJav88IiMdONT6wrKD1pom9otB3QfVllSzfe23olZBsAR6D1/XezBaqCd123yKTbN0o+WPGDaz6Qj+RiCC8Ezthv9Re3RZw5vFCaGGzjj5Rm+KwHoY5kfoK+EhZQKqMdLRzYesdI0f5B9RawM0R8c1XCIYNS6j/0=MIICMTCCAZqgAwIBAgIQfYOsIEVuAJ1FwwcTrY0t1DANBgkqhkiG9w0BAQUFADBX -MVUwUwYDVQQDHkwAewA1ADkARgAxAEUANAA2ADEALQBEAEQARQA1AC0ANABEADIA -RgAtAEEAMAAxAEEALQA4ADMAMwAyADIAQQA5AEUAQgA4ADMAOAB9MB4XDTE1MDYx -NTA1NDc1N1oXDTE2MDYxNDExNDc1N1owVzFVMFMGA1UEAx5MAHsANQA5AEYAMQBF -ADQANgAxAC0ARABEAEUANQAtADQARAAyAEYALQBBADAAMQBBAC0AOAAzADMAMgAy -AEEAOQBFAEIAOAAzADgAfTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAk41G -nqXXLaiOC/y0/cA4tbS+NZCqI+x4EsztgDFvPPlHstiVYcLRkni4i93gK9zoC6g0 -mh66HMVzAfE8vRNwW5b7m6nWS1SiHBon7/Mqsw4MIq3SC+J/fTbKpqwyfAuH2YZl -AiQuQc85fyllAMLh2WrA7JgOLR/5tF3kLtpbHdECAwEAATANBgkqhkiG9w0BAQUF -AAOBgQArdh+RyT6VxKGsXk1zhHsgwXfToe6GpTF4W8PHI1+T0WIsNForDhvst6nm -QtgAhuZM9rxpOJuNKc+pM29EixpAiZZiRMCSWEItNyEVdUIi+YnKBcAHd88TwO86 -d126MWQ2O8cu5W1VoDp7hYBYKOnLbYi11/StO+0rzK+oPYAvIw== - \ No newline at end of file + + + + 1 + 24533572000102 + 2143992 + 1 + + + + + 1 + UNICA + 1 + + 2010-06-16T21:00:00 + 1 + 1 + 1 + 2 + 1 + + + 1.00 + 0 + 0 + 0 + 0 + 0 + 2 + 2 + 2 + 0.00 + 2 + + 01.07 + 6209100 + Sistema NFSe + 2408102 + + + 24533572000102 + 2143992 + + + + + 01812418000166 + + 2143992 + + MARIO + + RUA GROBEIRO + 128 + ANDAR 14 + Lagoa Nova + 3159506 + BH + 30160010 + + + mario@email.com.br + + + + + + + + + + + + + + CqxPWMfRKwecg6TEoFNA82URG5I= + + + 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 + + + + + + + + + + + + + + + + + 3OyPtYPIjU7Vm5azBnCaQVBCBxM= + + + psdrJW0dE9bnGbK5UJchL/h4vRm5HUWPzkkX4LbCLJopsOAdR0l0M787njoX7b4tWwrPysgdNWfhGngNoiD6iVqXyNhbuHZftUJIlDUudAHIxjhrMJdiNVXQDz8lBYzOta8HMMGQqHzzEg6DCVSZ1zeF5D2Nu2I7UL12P3jTDPtrapLC0YHxcRamGcG48I5tMo1qCKPxtkePkwx13PahkET+aExnb+5sexl+nhzfFJIKC0mfIRtoLyLEidNxalzzfMLbDxwe6WGgJS66+VKOeYNL89Gn2yp17uMZdnS08a6tUKy8t7sZt9W3ktrrjCofRlkwK8dq8jsh/GIw8hXLkg== + + + MIIIMTCCBhmgAwIBAgIIDBYcAk2MYI0wDQYJKoZIhvcNAQELBQAwcjELMAkGA1UE +BhMCQlIxEzARBgNVBAoTCklDUC1CcmFzaWwxNjA0BgNVBAsTLVNlY3JldGFyaWEg +ZGEgUmVjZWl0YSBGZWRlcmFsIGRvIEJyYXNpbCAtIFJGQjEWMBQGA1UEAxMNQUMg +T05MSU5FIFJGQjAeFw0xOTA5MTgwMDAwMjZaFw0yMDA5MTcwMDAwMjZaMIIBADEL +MAkGA1UEBhMCQlIxCzAJBgNVBAgMAlJOMQ4wDAYDVQQHDAVOQVRBTDETMBEGA1UE +CgwKSUNQLUJyYXNpbDE2MDQGA1UECwwtU2VjcmV0YXJpYSBkYSBSZWNlaXRhIEZl +ZGVyYWwgZG8gQnJhc2lsIC0gUkZCMRYwFAYDVQQLDA1SRkIgZS1DTlBKIEExMSIw +IAYDVQQLDBlBUiBTT0xJTU9FUyBDRVJUSUZJQ0FET1JBMRcwFQYDVQQLDA4yMjc1 +OTUzMTAwMDEwMzEyMDAGA1UEAwwpVFNNWCBTRVJWSUNPUyBERSBUSSBFSVJFTEk6 +MjM4MDkwNzAwMDAxOTAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJ +9LXn3SvQ02Gx9+aGiQh3cJ9A7J7w2eOWRVcjYo147tTsVNbpbJM56D5rvQ4uYLYT +GEg9gnWRs/xkg/WwKmbC/ax3j/tJG62Boj8DF1QoGkiVfSOQbCYXnO9nDZ7fKRwU +KXkLnpjNGnsZr/FIt6U3nNv/HJ5uwfmHRi3NPeMIkyQR+HogOUWChu8ZJz2quQu4 +tpNePV3GhW4h0o0Ggoq2YTIRhAidobjq7FWCu2jYkTEZ08h5fLn2bMLhaUgO1iBo +JjzE1nD1C5wat4arxtzIz25q8lytp21q1kFD/Lkyh+RMjbngqeS8IBBrnMi0zear +tgxtOKSdQD7PXzHFcuzzAgMBAAGjggM5MIIDNTCBoQYIKwYBBQUHAQEEgZQwgZEw +XAYIKwYBBQUHMAKGUGh0dHA6Ly9pY3AtYnJhc2lsLnZwa2kudmFsaWRjZXJ0aWZp +Y2Fkb3JhLmNvbS5ici9hYy1vbmxpbmVyZmIvYWMtb25saW5lcmZidjIucDdiMDEG +CCsGAQUFBzABhiVodHRwOi8vb2NzcC52YWxpZGNlcnRpZmljYWRvcmEuY29tLmJy +MAkGA1UdEwQCMAAwHwYDVR0jBBgwFoAUkZp2jCuokxiYmHoD5MvstbAZJ/8wdQYD +VR0gBG4wbDBqBgZgTAECATcwYDBeBggrBgEFBQcCARZSaHR0cDovL2ljcC1icmFz +aWwudnBraS52YWxpZGNlcnRpZmljYWRvcmEuY29tLmJyL2FjLW9ubGluZXJmYi9k +cGMtYWMtb25saW5lcmZiLnBkZjCCAQYGA1UdHwSB/jCB+zBVoFOgUYZPaHR0cDov +L2ljcC1icmFzaWwudmFsaWRjZXJ0aWZpY2Fkb3JhLmNvbS5ici9hYy1vbmxpbmVy +ZmIvbGNyLWFjLW9ubGluZXJmYnYyLmNybDBWoFSgUoZQaHR0cDovL2ljcC1icmFz +aWwyLnZhbGlkY2VydGlmaWNhZG9yYS5jb20uYnIvYWMtb25saW5lcmZiL2xjci1h +Yy1vbmxpbmVyZmJ2Mi5jcmwwSqBIoEaGRGh0dHA6Ly9yZXBvc2l0b3Jpby5pY3Bi +cmFzaWwuZ292LmJyL2xjci9WQUxJRC9sY3ItYWMtb25saW5lcmZidjIuY3JsMA4G +A1UdDwEB/wQEAwIF4DAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwgbIG +A1UdEQSBqjCBp4ERdGhpYWdvQHNncC5uZXQuYnKgOAYFYEwBAwSgLwQtMDMwNjE5 +ODQwNTQ5NzkyODQ4MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwoCQGBWBMAQMC +oBsEGVRISUFHTyBTQU1QQUlPIE1PTlRFTkVHUk+gGQYFYEwBAwOgEAQOMjM4MDkw +NzAwMDAxOTCgFwYFYEwBAwegDgQMMDAwMDAwMDAwMDAwMA0GCSqGSIb3DQEBCwUA +A4ICAQC+cp3UMxJPgs5JYHJmCJrCAw4qq4BMH7JWDUufvhiYKkWfWfhLMRidqRcP +ez+6u0EML5riw7uH3NoF/Byw5v8RY5/8diI7d5TB/SsM8wl9De3BiL5n9cC2oK5y +F+OfvTFdMYPx7VnlGpVjeEEDAcflrX2zM6u6D/Me2xu0g0YnbLhYKcjjXBlmkm2f +Zrn0fo8te4OanvYMDbCiP1MROQUk95hxzn5/dZ8OdLuZ2Q+GwLGADKV4p6CEy6U8 +U/1Hi2Dt+py2hphRbGHdP/QB59dxayQSYEq38HSsdbgNnWrRe0L8W2xkoAkq2a0U +0rW3sKae5dlrHs9hIsXrgDXHFl58snjTatz5g17IJ704ztshroRiWCiyJOsP12yv +c8ildHN/u9li2YBxBr/9F3O3k2MKHYdVe10VNZMtmlhBcUlrC/bECbrJF/uIfGk5 +UMC9Tx8ROYsI8Rsfs1fS8KnjlOPav6ikoZUnHsZiU75Dp/9i9wxf5txPzjCEqG7U +wjXEATC2ldlF+F1ZUbmREydeLcAHZu5eMBoRiNvl41E5LHbAfs42cnpI7QXbiqN3 +0EcNkCVtYlcy04q00fJ4CnI1WANuslfa6srLnaiWVUSCeYiDBK3FS+mwa8ixT7Mj +hKs/6BOBoYlaDzZm242gbvh1eG8/XcDjT4BAGr5aA/cHnjEiXw== + + + + + diff --git a/tests/test_nfse_natal.py b/tests/test_nfse_natal.py deleted file mode 100644 index 2bf75c1..0000000 --- a/tests/test_nfse_natal.py +++ /dev/null @@ -1,80 +0,0 @@ -# coding=utf-8 - -import mock -import os.path -import unittest -from pytrustnfe.certificado import Certificado -from pytrustnfe.nfse.natal import recepcionar_lote_rps - - -class test_nfse_natal(unittest.TestCase): - - caminho = os.path.dirname(__file__) - - def _get_nfse(self): - rps_list = [ - { - "numero": "1", - "serie": "UNICA", - "tipo_rps": "1", - "data_emissao": "2020-01-279", - "natureza_operacao": "1", - "regime_tributacao": "1", - "optante_simples": "1", - "incentivador_cultural": "2", - "servico": { - "valor_servico": "1.00", - "iss_retido": "2", - "base_calculo": "0.00", - "codigo_servico": "01.07", - "cnae_servico": "6209100", - "descricao": "Sistema NFSe", - "codigo_municipio": "2408102", - }, - "prestador": { - "cnpj": "23809070000190", - "inscricao_municipal": "2143992", - "razao_social": "SERVICOS DE TI", - "fantasia": "SERVICOS DE TI", - "endereco": "AV AMINTAS", - "numero": "3755", - "complemento": "SALA 32", - "bairro": "Lagoa Nova", - "codigo_municipio": "2408102", - "uf": "RN", - "cep": "59075810", - "telefone": "4132095554", - "email": "SUPORTE@EMAIL.COM.BR", - }, - "tomador": { - "cpf_cnpj": "01812418000166", - "razao_social": "LEONIR", - "endereco": "RUA GROBEIRO", - "numero": "128", - "bairro": "Lagoa Nova", - "cidade": "3159506", - "uf": "BH", - "cep": "1231231313", - "email": "leonir@yahoo.com.br", - "orgao_gerador": {"codigo_municipio": "3159506"}, - }, - } - ] - nfse = { - "numero_lote": "1", - "cnpj_prestador": "23809070000190", - "inscricao_municipal": "2143992", - "lista_rps": rps_list, - } - return nfse - - def test_recepcionar_lote_rps(self): - pfx_source = open(os.path.join(self.caminho, "teste.pfx"), "rb").read() - pfx = Certificado(pfx_source, "123456", ambiente="homologacao") - - nfse = self._get_nfse() - path = os.path.join(os.path.dirname(__file__), "XMLs") - sent_xml = open(os.path.join(path, "natal_sent_xml.xml"), "r").read() - - retorno = recepcionar_lote_rps(pfx, nfse=nfse) - self.assertEqual(retorno["sent_xml"], sent_xml)