Skip to content

Commit

Permalink
Merge pull request #292 from faio/master3
Browse files Browse the repository at this point in the history
Geração NFSe prefeitura de Goiânia
  • Loading branch information
danimaribeiro committed Mar 19, 2021
2 parents 922b26b + a008f99 commit 9697019
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ NFSe - Cidades atendidas
* **Paulistana** - São Paulo/SP
* **Nota Carioca** - Rio de Janeiro/RJ
* **Imperial** - Petrópolis/RH
* **Goiânia** - Goiânia/GO
* [Susesu](cidades/susesu.md) - 3 cidades atendidas
* [Simpliss](cidades/simpliss.md) - 18 cidade atendidas
* [GINFES](cidades/ginfes.md) - 79 cidades atendidas
Expand Down
61 changes: 61 additions & 0 deletions pytrustnfe/nfse/goiania/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import os
import suds

from lxml import etree

from pytrustnfe.client import get_authenticated_client
from pytrustnfe.certificado import extract_cert_and_key_from_pfx, save_cert_key
from pytrustnfe.xml import render_xml, sanitize_response

from .assinatura import Assinatura


def _render(certificado, method, **kwargs):
path = os.path.join(os.path.dirname(__file__), "templates")
xml_send = render_xml(path, f"{method}.xml", False, **kwargs)
signer = Assinatura(certificado.pfx, certificado.password)
xml_send = etree.fromstring(xml_send)
xml_send = signer.assina_xml(xml_send)
return xml_send


def _send(certificado, method, **kwargs):
base_url = "https://nfse.goiania.go.gov.br/ws/nfse.asmx?wsdl"
xml_send = kwargs["xml"]
cert, key = extract_cert_and_key_from_pfx(certificado.pfx, certificado.password)
cert, key = save_cert_key(cert, key)
client = get_authenticated_client(base_url, cert, key)

try:
response = getattr(client.service, method)(xml_send)
except suds.WebFault as e:
return {
"send_xml": str(xml_send),
"received_xml": str(e.fault.faultstring),
"object": None,
}

response, obj = sanitize_response(response)
return {"send_xml": str(xml_send), "received_xml": str(response), "object": obj}


def xml_gerar_nfse(certificado, **kwargs):
""" Retorna o XML montado para ser enviado para o Webservice """

return _render(certificado, "GerarNfse", **kwargs)


def gerar_nfse(certificado, **kwargs):
"""" Gera uma NFSe de saída """

if "xml" not in kwargs:
kwargs["xml"] = xml_gerar_nfse
return _send(certificado, "GerarNfse", **kwargs)


def consulta_nfse_por_rps(certificado, **kwargs):
""" Consulta os dados de um NFSe já emitida """

if "xml" not in kwargs:
kwargs["xml"] = _render(certificado, "ConsultarNfseRps", **kwargs)
return _send(certificado, "ConsultarNfseRps", **kwargs)
38 changes: 38 additions & 0 deletions pytrustnfe/nfse/goiania/assinatura.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from lxml import etree
from pytrustnfe.certificado import extract_cert_and_key_from_pfx
from signxml import XMLSigner, methods
from pytrustnfe.nfe.assinatura import Assinatura as _Assinatura


class Assinatura(_Assinatura):

def assina_xml(self, xml_element):
cert, key = extract_cert_and_key_from_pfx(self.arquivo, self.senha)

for element in xml_element.iter("*"):
if element.text is not None and not element.text.strip():
element.text = None

signer = XMLSigner(
method=methods.enveloped,
signature_algorithm=u"rsa-sha1",
digest_algorithm=u"sha1",
c14n_algorithm=u"http://www.w3.org/TR/2001/REC-xml-c14n-20010315",
)

ns = {}
ns[None] = signer.namespaces["ds"]
signer.namespaces = ns
element_signed = xml_element.find(".//{http://nfse.goiania.go.gov.br/xsd/nfse_gyn_v02.xsd}Rps")
signed_root = signer.sign(
xml_element, key=key.encode(), cert=cert.encode()
)
signature = signed_root.find(
".//{http://www.w3.org/2000/09/xmldsig#}Signature"
)

if element_signed is not None and signature is not None:
parent = xml_element.getchildren()[0]
parent.append(signature)

return etree.tostring(xml_element, encoding=str)
19 changes: 19 additions & 0 deletions pytrustnfe/nfse/goiania/templates/ConsultarNfseRps.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0"?>
<ConsultarNfseRpsEnvio xmlns="http://nfse.goiania.go.gov.br/xsd/nfse_gyn_v02.xsd">
<IdentificacaoRps>
<Numero>{{ numero }}</Numero>
<Serie>{{ serie }}</Serie>
<Tipo>{{ tipo }}</Tipo>
</IdentificacaoRps>
<Prestador>
<CpfCnpj>
{% if cnpj_cpf|length == 14 %}
<Cnpj>{{ cnpj_cpf }}</Cnpj>
{% endif %}
{% if cnpj_cpf|length == 11 %}
<Cpf>{{ cnpj_cpf }}</Cpf>
{% endif %}
</CpfCnpj>
<InscricaoMunicipal>{{ inscricao_municipal }}</InscricaoMunicipal>
</Prestador>
</ConsultarNfseRpsEnvio>
4 changes: 4 additions & 0 deletions pytrustnfe/nfse/goiania/templates/GerarNfse.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0"?>
<GerarNfseEnvio xmlns="http://nfse.goiania.go.gov.br/xsd/nfse_gyn_v02.xsd">
{% include 'Rps.xml' %}
</GerarNfseEnvio>
63 changes: 63 additions & 0 deletions pytrustnfe/nfse/goiania/templates/Rps.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<Rps>
<InfDeclaracaoPrestacaoServico>
<Rps>
<IdentificacaoRps>
<Numero>{{ numero }}</Numero>
<Serie>{{ serie }}</Serie>
<Tipo>{{ tipo }}</Tipo>
</IdentificacaoRps>
<DataEmissao>{{ data_emissao }}</DataEmissao>
<Status>{{ status }}</Status>
</Rps>
<Servico>
<Valores>
<ValorServicos>{{ servico.valor_servicos }}</ValorServicos>
{% if servico.valor_pis %}<ValorPis>{{ servico.valor_pis }}</ValorPis>{% endif %}
{% if servico.valor_confins %}<ValorCofins>{{ servico.valor_confins }}</ValorCofins>{% endif %}
{% if servico.valor_inss %}<ValorInss>{{ servico.valor_inss }}</ValorInss>{% endif %}
{% if servico.valor_csll %}<ValorCsll>{{ servico.valor_csll }}</ValorCsll>{% endif %}
{% if servico.aliquota %}<Aliquota>{{ servico.aliquota }}</Aliquota>{% endif %}
</Valores>
<CodigoTributacaoMunicipio>{{ servico.codigo_tributacao_municipio }}</CodigoTributacaoMunicipio>
<Discriminacao>{{ servico.discriminacao }}</Discriminacao>
<CodigoMunicipio>{{ servico.codigo_municipio }}</CodigoMunicipio>
</Servico>
<Prestador>
<CpfCnpj>
{% if prestador.cnpj_cpf|length == 14 %}
<Cnpj>{{ prestador.cnpj_cpf }}</Cnpj>
{% endif %}
{% if prestador.cnpj_cpf|length == 11 %}
<Cpf>{{ prestador.cnpj_cpf }}</Cpf>
{% endif %}
</CpfCnpj>
<InscricaoMunicipal>{{ prestador.inscricao_municipal }}</InscricaoMunicipal>
</Prestador>
<Tomador>
<IdentificacaoTomador>
<CpfCnpj>
{% if tomador.cnpj_cpf|length == 14 %}
<Cnpj>{{ tomador.cnpj_cpf }}</Cnpj>
{% endif %}
{% if prestador.cnpj_cpf|length == 11 %}
<Cpf>{{ prestador.cnpj_cpf }}</Cpf>
{% endif %}
</CpfCnpj>
{% if tomador.inscricao_municipal %}
<InscricaoMunicipal>{{ tomador.inscricao_municipal }}</InscricaoMunicipal>
{% endif %}
</IdentificacaoTomador>
<RazaoSocial>{{ tomador.razao_social }}</RazaoSocial>
{% if tomador.endereco %}
<Endereco>
{% if tomador.endereco.rua %}<Endereco>{{ tomador.endereco.rua }}</Endereco>{%endif %}
{% if tomador.endereco.numero %}<Numero>{{ tomador.endereco.numero }}</Numero>{%endif %}
{% if tomador.endereco.complemento %}<Complemento>{{ tomador.endereco.complemento }}</Complemento>{%endif %}
{% if tomador.endereco.bairro %}<Bairro>{{ tomador.endereco.bairro }}</Bairro>{%endif %}
{% if tomador.endereco.codigo_municipio %}<CodigoMunicipio>{{ tomador.endereco.codigo_municipio }}</CodigoMunicipio>{%endif %}
{% if tomador.endereco.uf %}<Uf>{{ tomador.endereco.uf }}</Uf>{%endif %}
</Endereco>
{% endif %}
</Tomador>
</InfDeclaracaoPrestacaoServico>
</Rps>

0 comments on commit 9697019

Please sign in to comment.