From 7cff7bb5f1cbea4b871f3559e87a5c8bf7e2f72a Mon Sep 17 00:00:00 2001 From: Danimar Ribeiro Date: Thu, 14 Dec 2017 11:17:28 -0200 Subject: [PATCH] =?UTF-8?q?[WIP]=20Implementa=C3=A7=C3=A3o=20da=20nfse=20d?= =?UTF-8?q?e=20florian=C3=B3polis?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pytrustnfe/nfse/floripa/__init__.py | 105 +++++++++++++++++++++ .../nfse/floripa/templates/cancelar_nota.xml | 7 ++ .../nfse/floripa/templates/processar_nota.xml | 40 ++++++++ pytrustnfe/nfse/ginfes/__init__.py | 1 - requirements.txt | 4 +- 5 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 pytrustnfe/nfse/floripa/__init__.py create mode 100644 pytrustnfe/nfse/floripa/templates/cancelar_nota.xml create mode 100644 pytrustnfe/nfse/floripa/templates/processar_nota.xml diff --git a/pytrustnfe/nfse/floripa/__init__.py b/pytrustnfe/nfse/floripa/__init__.py new file mode 100644 index 0000000..9c13bcb --- /dev/null +++ b/pytrustnfe/nfse/floripa/__init__.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- +# © 2017 Danimar Ribeiro, Trustcode +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import os +import hashlib +import base64 +import requests +from pytrustnfe.xml import render_xml, sanitize_response +from pytrustnfe.certificado import extract_cert_and_key_from_pfx, save_cert_key +from pytrustnfe.nfse.assinatura import Assinatura + + +def _render(certificado, method, **kwargs): + path = os.path.join(os.path.dirname(__file__), 'templates') + xml_send = render_xml(path, '%s.xml' % method, False, **kwargs) + + cert, key = extract_cert_and_key_from_pfx( + certificado.pfx, certificado.password) + cert, key = save_cert_key(cert, key) + signer = Assinatura(cert, key, certificado.password) + xml_send = signer.assina_xml(xml_send, '') + return xml_send + + +def _get_oauth_token(**kwargs): + if kwargs['ambiente'] == 'producao': + url = 'https://nfps-e.pmf.sc.gov.br/api/v1/autenticacao/oauth/token' + else: + url = 'https://nfps-e-hml.pmf.sc.gov.br/api/v1/autenticacao/oauth/token' + + m = hashlib.md5() + secret = "%s:%s" % (kwargs["client_id"], kwargs["secret_id"]) + auth = base64.b64encode(secret.encode('utf-8')) + headers = { + "Content-Type": "application/x-www-form-urlencoded", + "Authorization": "Basic %s" % auth.decode('utf-8').replace('\n', '') + } + m.update(kwargs["password"].encode('utf-8')) + password = m.hexdigest().upper() + + dados = "grant_type=password&username=%s&password=%s&client_id=%s&client_secret=%s" % ( + kwargs["username"], password, kwargs["client_id"], kwargs["secret_id"]) + r = requests.post(url, data=dados, headers=headers) + if r.status_code == 200: + return r.json() + else: + return r.text + + +def _send(certificado, method, **kwargs): + if kwargs['ambiente'] == 'producao': + url = 'https://nfps-e.pmf.sc.gov.br/api/v1/processamento/notas/processa' + else: + url = 'https://nfps-e-hml.pmf.sc.gov.br/api/v1/processamento/notas/processa' + + xml_send = '' + kwargs['xml'] + + base = dict( + ambiente='homologacao', client_id="trustcode-tecnologia-client", + secret_id="", username="", + password="" + ) + token = _get_oauth_token(**kwargs) + + kwargs.update({"numero": 1, 'access_token': token["access_token"]}) + + headers = {"Accept": "application/xml", + "Authorization": "Bearer %s" % kwargs['access_token']} + r = requests.post(url, headers=headers, data=xml_send) + print(r.status_code) + if r.status_code != 200: + raise Exception(r.text) + + print(r.text) + response, obj = sanitize_response(r.text) + return { + 'sent_xml': xml_send, + 'received_xml': response, + 'object': obj + } + + +def xml_processar_nota(certificado, **kwargs): + return _render(certificado, 'processar_nota', **kwargs) + + +def processar_nota(certificado, **kwargs): + if "xml" not in kwargs: + kwargs['xml'] = xml_processar_nota(certificado, **kwargs) + return _send(certificado, 'processar_nota', **kwargs) + + +def consultar_nota(certificado, **kwargs): + url = "https://nfps-e-hml.pmf.sc.gov.br/api/v1/consultas/notas/numero/%s" % (kwargs["numero"]) + url = 'https://nfps-e-hml.pmf.sc.gov.br/api/v1/consultas/notas/prestador/24158233000185?pagina=1' + + headers = {"Accept": "application/json", + "Authorization": "Bearer %s" % kwargs['access_token']} + r = requests.get(url, headers=headers) + print(r.status_code) + if r.status_code == 200: + return r.text + else: + return r.text diff --git a/pytrustnfe/nfse/floripa/templates/cancelar_nota.xml b/pytrustnfe/nfse/floripa/templates/cancelar_nota.xml new file mode 100644 index 0000000..324d779 --- /dev/null +++ b/pytrustnfe/nfse/floripa/templates/cancelar_nota.xml @@ -0,0 +1,7 @@ + + + {{ cancelamento.motivo }} + {{ cancelamento.aedf }} + {{ cancelamento.numero }} + {{ cancelamento.codigo_verificacao }} + diff --git a/pytrustnfe/nfse/floripa/templates/processar_nota.xml b/pytrustnfe/nfse/floripa/templates/processar_nota.xml new file mode 100644 index 0000000..7a31ae3 --- /dev/null +++ b/pytrustnfe/nfse/floripa/templates/processar_nota.xml @@ -0,0 +1,40 @@ + + + {{ rps.tomador.bairro }} + {{ rps.base_calculo }} + 0.0 + {{ rps.cfps }} + {{ rps.tomador.cidade }} + {{ rps.tomador.cep }} + {{ rps.tomador.complemento }} + {{ rps.observacoes }} + {{ rps.data_emissao }} + {{ rps.tomador.email }} + {{ rps.numero }} + {{ rps.tomador.cnpj_cpf }} + {{ rps.tomador.inscricao_municipal }} + + {% for item in rps.itens_servico -%} + + {{ item.aliquota }} + {{ item.cst_servico }} + {{ item.descricao }} + {{ item.cnae }} + {{ item.quantidade }} + {{ item.valor_total }} + {{ item.valor_unitario }} + + {% endfor %} + + {{ rps.tomador.logradouro }} + + {{ rps.aedf }} + {{ rps.tomador.numero }} + 1058 + {{ rps.tomador.razao_social }} + {{ rps.tomador.telefone }} + {{ rps.tomador.uf }} + {{rps.valor_iss }} + 0.0 + {{ rps.valor_liquido_nfse }} + diff --git a/pytrustnfe/nfse/ginfes/__init__.py b/pytrustnfe/nfse/ginfes/__init__.py index e662f2f..80e969b 100644 --- a/pytrustnfe/nfse/ginfes/__init__.py +++ b/pytrustnfe/nfse/ginfes/__init__.py @@ -4,7 +4,6 @@ import os import suds -from lxml import etree from pytrustnfe.xml import render_xml, sanitize_response from pytrustnfe.client import get_authenticated_client from pytrustnfe.certificado import extract_cert_and_key_from_pfx, save_cert_key diff --git a/requirements.txt b/requirements.txt index c42cf9d..37ad7fd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,8 +7,8 @@ suds-jurko >= 0.6 suds-jurko-requests >= 1.1 defusedxml >= 0.4.1, < 0.6 eight >= 0.3.0, < 0.5 -cryptography >= 1.8, < 1.10 -pyOpenSSL >= 16.0.0, < 17 +cryptography >= 1.8, < 2.1 +pyOpenSSL >= 16.0.0, < 18 certifi >= 2015.11.20.1 xmlsec >= 1.3.3 reportlab