Browse Source

Merge branch 'master3' into master3

pull/128/head
Danimar Ribeiro 8 years ago
committed by GitHub
parent
commit
c9d67075ed
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      pytrustnfe/Servidores.py
  2. 9
      pytrustnfe/client.py
  3. 26
      pytrustnfe/nfe/__init__.py
  4. 4
      pytrustnfe/nfe/comunicacao.py
  5. 78
      pytrustnfe/nfse/bh/__init__.py
  6. 13
      pytrustnfe/nfse/bh/templates/CancelarNfse.xml
  7. 11
      pytrustnfe/nfse/bh/templates/GerarNfse.xml
  8. 91
      pytrustnfe/nfse/bh/templates/Rps.xml
  9. 1
      pytrustnfe/utils.py

8
pytrustnfe/Servidores.py

@ -352,8 +352,8 @@ UFBA = {
UFCE = {
NFE_AMBIENTE_PRODUCAO: {
'servidor': 'nfe.sefaz.ce.gov.br',
WS_NFE_AUTORIZACAO: 'nfe2/services/NfeRecepcao2',
WS_NFE_RET_AUTORIZACAO: 'nfe2/services/NfeRetRecepcao2',
WS_NFE_AUTORIZACAO: 'nfe2/services/NfeAutorizacao',
WS_NFE_RET_AUTORIZACAO: 'nfe2/services/NfeRetAutorizacao',
WS_NFE_INUTILIZACAO: 'nfe2/services/NfeInutilizacao2',
WS_NFE_CONSULTA: 'nfe2/services/NfeConsulta2',
WS_NFE_SITUACAO: 'nfe2/services/NfeStatusServico2',
@ -363,8 +363,8 @@ UFCE = {
},
NFE_AMBIENTE_HOMOLOGACAO: {
'servidor': 'nfeh.sefaz.ce.gov.br',
WS_NFE_AUTORIZACAO: 'nfe2/services/NfeRecepcao2',
WS_NFE_RET_AUTORIZACAO: 'nfe2/services/NfeRetRecepcao2',
WS_NFE_AUTORIZACAO: 'nfe2/services/NfeAutorizacao',
WS_NFE_RET_AUTORIZACAO: 'nfe2/services/NfeRetAutorizacao',
WS_NFE_INUTILIZACAO: 'nfe2/services/NfeInutilizacao2',
WS_NFE_CONSULTA: 'nfe2/services/NfeConsulta2',
WS_NFE_SITUACAO: 'nfe2/services/NfeStatusServico2',

9
pytrustnfe/client.py

@ -45,19 +45,20 @@ class HttpClient(object):
def _headers(self, action, send_raw):
if send_raw:
return {
'Content-type': 'text/xml; charset=utf-8; action="http://www.portalfiscal.inf.br/nfe/wsdl/%s"' % action,
'Content-type': 'text/xml; charset=utf-8;',
'SOAPAction': "http://www.portalfiscal.inf.br/nfe/wsdl/%s" % action,
'Accept': 'application/soap+xml; charset=utf-8',
}
return {
'Content-type': 'application/soap+xml; charset=utf-8; action="http://www.portalfiscal.inf.br/nfe/wsdl/%s"' % action,
'Accept': 'application/soap+xml; charset=utf-8',
'Content-type': 'application/soap+xml; charset=utf-8;',
'SOAPAction': 'http://www.portalfiscal.inf.br/nfe/wsdl/%s' % action,
}
def post_soap(self, xml_soap, cabecalho, send_raw):
header = self._headers(cabecalho.soap_action, send_raw)
urllib3.disable_warnings(category=InsecureRequestWarning)
res = requests.post(self.url, data=xml_soap,
res = requests.post(self.url, data=xml_soap.encode('utf-8'),
cert=(self.cert_path, self.key_path),
verify=False, headers=header)
return res.text

26
pytrustnfe/nfe/__init__.py

@ -19,19 +19,21 @@ from pytrustnfe.exceptions import NFeValidationException
def _build_header(method, **kwargs):
action = {
'NfeAutorizacao': ('NfeAutorizacao', '3.10'),
'NfeRetAutorizacao': ('NfeRetAutorizacao', '3.10'),
'NfeConsultaCadastro': ('CadConsultaCadastro2', '2.00'),
'NfeInutilizacao': ('NfeInutilizacao2', '3.10'),
'RecepcaoEventoCancelamento': ('RecepcaoEvento', '1.00'),
'RecepcaoEventoCarta': ('RecepcaoEvento', '1.00'),
'NFeDistribuicaoDFe': ('NFeDistribuicaoDFe/nfeDistDFeInteresse',
'1.00'),
'RecepcaoEventoManifesto': ('RecepcaoEvento', '1.00'),
'NfeAutorizacao': ('NfeAutorizacao', '3.10', 'NfeAutorizacao/nfeAutorizacaoLote'),
'NfeRetAutorizacao': ('NfeRetAutorizacao', '3.10', 'NfeRetAutorizacao/nfeRetAutorizacaoLote'),
'NfeConsultaCadastro': ('CadConsultaCadastro2', '2.00', 'CadConsultaCadastro2/consultaCadastro2'),
'NfeInutilizacao': ('NfeInutilizacao2', '3.10', 'NfeInutilizacao2/nfeInutilizacaoNF2'),
'RecepcaoEventoCancelamento': ('RecepcaoEvento', '1.00', 'RecepcaoEvento/nfeRecepcaoEvento'),
'RecepcaoEventoCarta': ('RecepcaoEvento', '1.00', 'RecepcaoEvento/nfeRecepcaoEvento'),
'NFeDistribuicaoDFe': ('NFeDistribuicaoDFe/nfeDistDFeInteresse', '1.00', 'NFeDistribuicaoDFe/nfeDistDFeInteresse'),
'RecepcaoEventoManifesto': ('RecepcaoEvento', '1.00', 'RecepcaoEvento/nfeRecepcaoEvento'),
}
vals = {
'estado': kwargs['estado'],
'method': action[method][0],
'soap_action': action[method][2],
'versao': action[method][1]
}
vals = {'estado': kwargs['estado'],
'soap_action': action[method][0],
'versao': action[method][1]}
return CabecalhoSoap(**vals)

4
pytrustnfe/nfe/comunicacao.py

@ -12,9 +12,9 @@ from ..xml import sanitize_response
def _soap_xml(body, cabecalho):
xml = '<?xml version="1.0" encoding="utf-8"?>'
xml += '<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap:Header>'
xml += '<nfeCabecMsg xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/' + cabecalho.soap_action + '">'
xml += '<nfeCabecMsg xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/' + cabecalho.method + '">'
xml += '<cUF>' + cabecalho.estado + '</cUF><versaoDados>' + cabecalho.versao + '</versaoDados></nfeCabecMsg></soap:Header><soap:Body>'
xml += '<nfeDadosMsg xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/' + cabecalho.soap_action + '">'
xml += '<nfeDadosMsg xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/' + cabecalho.method + '">'
xml += body
xml += '</nfeDadosMsg></soap:Body></soap:Envelope>'
return xml.rstrip('\n')

78
pytrustnfe/nfse/bh/__init__.py

@ -0,0 +1,78 @@
# © 2018 Danimar Ribeiro, Trustcode
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import os
from requests import Session
from zeep import Client
from zeep.transports import Transport
from pytrustnfe.certificado import extract_cert_and_key_from_pfx, save_cert_key
from pytrustnfe.xml import render_xml, sanitize_response
from pytrustnfe.nfe.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, True, **kwargs)
reference = ''
if method == 'GerarNfse':
reference = 'r%s' % kwargs['rps']['numero']
elif method == 'CancelarNfse':
reference = 'Cancelamento_NF%s' % kwargs['cancelamento']['numero_nfse']
signer = Assinatura(certificado.pfx, certificado.password)
xml_send = signer.assina_xml(xml_send, reference)
return xml_send.encode('utf-8')
def _send(certificado, method, **kwargs):
base_url = ''
if kwargs['ambiente'] == 'producao':
base_url = 'https://bhissdigital.pbh.gov.br/bhiss-ws/nfse?wsdl'
else:
base_url = 'https://bhisshomologa.pbh.gov.br/bhiss-ws/nfse?wsdl'
xml_send = kwargs["xml"].decode('utf-8')
xml_cabecalho = ''
cert, key = extract_cert_and_key_from_pfx(
certificado.pfx, certificado.password)
cert, key = save_cert_key(cert, key)
session = Session()
session.cert = (cert, key)
session.verify = False
transport = Transport(session=session)
client = Client(base_url, transport=transport)
response = client.service[method](xml_cabecalho, xml_send)
response, obj = sanitize_response(response)
return {
'sent_xml': str(xml_send),
'received_xml': str(response),
'object': obj
}
def xml_gerar_nfse(certificado, **kwargs):
return _render(certificado, 'GerarNfse', **kwargs)
def gerar_nfse(certificado, **kwargs):
if "xml" not in kwargs:
kwargs['xml'] = xml_gerar_nfse(certificado, **kwargs)
return _send(certificado, 'GerarNfse', **kwargs)
def xml_cancelar_nfse(certificado, **kwargs):
return _render(certificado, 'CancelarNfse', **kwargs)
def cancelar_nfse(certificado, **kwargs):
if "xml" not in kwargs:
kwargs['xml'] = xml_cancelar_nfse(certificado, **kwargs)
return _send(certificado, 'CancelarNfse', **kwargs)

13
pytrustnfe/nfse/bh/templates/CancelarNfse.xml

@ -0,0 +1,13 @@
<CancelarNfseEnvio xmlns="http://www.abrasf.org.br/ABRASF/arquivos/nfse.xsd">
<Pedido xmlns="http://www.abrasf.org.br/nfse.xsd">
<InfPedidoCancelamento Id="pedidoCancelamento_{{ cancelamento.numero_nfse }}">
<IdentificacaoNfse>
<Numero>{{ cancelamento.numero_nfse }}</Numero>
<Cnpj>{{ cancelamento.cnpj_prestador }}</Cnpj>
<InscricaoMunicipal>{{ cancelamento.inscricao_municipal }}</InscricaoMunicipal>
<CodigoMunicipio>{{ cancelamento.cidade }}</CodigoMunicipio>
</IdentificacaoNfse>
<CodigoCancelamento>1</CodigoCancelamento>
</InfPedidoCancelamento>
</Pedido>
</CancelarNfseEnvio>

11
pytrustnfe/nfse/bh/templates/GerarNfse.xml

@ -0,0 +1,11 @@
<GerarNfseEnvio xmlns="http://www.abrasf.org.br/nfse.xsd">
<LoteRps Id="lote{{ nfse.numero_lote }}">
<NumeroLote>{{ nfse.numero_lote }}</NumeroLote>
<Cnpj>{{ nfse.cnpj_prestador }}</Cnpj>
<InscricaoMunicipal>{{ nfse.inscricao_municipal }}</InscricaoMunicipal>
<QuantidadeRps>1</QuantidadeRps>
<ListaRps xmlns="http://www.abrasf.org.br/nfse.xsd">
{% include 'Rps.xml' %}
</ListaRps>
</LoteRps>
</GerarNfseEnvio>

91
pytrustnfe/nfse/bh/templates/Rps.xml

@ -0,0 +1,91 @@
<Rps>
<InfRps xmlns="http://www.abrasf.org.br/ABRASF/arquivos/nfse.xsd" Id="r{{ rps.numero }}">
<IdentificacaoRps>
<Numero>{{ rps.numero }}</Numero>
<Serie>{{ rps.serie }}</Serie>
<Tipo>{{ rps.tipo_rps }}</Tipo>
</IdentificacaoRps>
<DataEmissao>{{ rps.data_emissao }}</DataEmissao>
<NaturezaOperacao>{{ rps.natureza_operacao }}</NaturezaOperacao>
<RegimeEspecialTributacao>{{ rps.regime_tributacao }}</RegimeEspecialTributacao>
<OptanteSimplesNacional>{{ rps.optante_simples }}</OptanteSimplesNacional>
<IncentivadorCultural>{{ rps.incentivador_cultural }}</IncentivadorCultural>
<Status>{{ rps.status }}</Status>
<RpsSubstituido>
<Numero>{{ rps.numero_substituido }}</Numero>
<Serie>{{ rps.serie_substituido }}</Serie>
<Tipo>{{ rps.tipo_substituido }}</Tipo>
</RpsSubstituido>
<Servico>
<Valores>
<ValorServicos>{{ rps.valor_servico }}</ValorServicos>
<ValorDeducoes>{{ rps.valor_deducao }}</ValorDeducoes>
<ValorPis>{{ rps.valor_pis }}</ValorPis>
<ValorCofins>{{ rps.valor_cofins }}</ValorCofins>
<ValorInss>{{ rps.valor_inss }}</ValorInss>
<ValorIr>{{ rps.valor_ir }}</ValorIr>
<ValorCsll>{{ rps.valor_csll }}</ValorCsll>
<IssRetido>{{ rps.iss_retido }}</IssRetido>
<ValorIss>{{ rps.valor_iss }}</ValorIss>
<ValorIssRetido>{{ rps.valor_iss_retido }}</ValorIssRetido>
<OutrasRetencoes>{{ rps.outras_retencoes }}</OutrasRetencoes>
<BaseCalculo>{{ rps.base_calculo }}</BaseCalculo>
<Aliquota>{{ rps.aliquota_issqn }}</Aliquota>
<ValorLiquidoNfse>{{ rps.valor_liquido_nfse }}</ValorLiquidoNfse>
<DescontoIncondicionado>{{ rps.desconto_incondicionado }}</DescontoIncondicionado>
<DescontoCondicionado>{{ rps.desconto_condicionado }}</DescontoCondicionado>
</Valores>
<ItemListaServico>{{ rps.codigo_servico }}</ItemListaServico>
<CodigoCnae>{{ rps.cnae_servico }}</CodigoCnae>
<CodigoTributacaoMunicipio>{{ rps.codigo_tributacao_municipio }}</CodigoTributacaoMunicipio>
<Discriminacao>{{ rps.descricao }}</Discriminacao>
<CodigoMunicipio>{{ rps.codigo_municipio }}</CodigoMunicipio>
</Servico>
<Prestador>
<Cnpj>{{ rps.prestador.cnpj }}</Cnpj>
<InscricaoMunicipal>{{ rps.prestador.inscricao_municipal }}</InscricaoMunicipal>
</Prestador>
<Tomador>
<IdentificacaoTomador>
<CpfCnpj>
{% if rps.tomador.cnpj_cpf|length == 14 %}
<Cnpj>{{ rps.tomador.cnpj_cpf }}</Cnpj>
{% endif %}
{% if rps.tomador.cnpj_cpf|length == 11 %}
<Cpf>{{ rps.tomador.cnpj_cpf }}</Cpf>
{% endif %}
</CpfCnpj>
<InscricaoMunicipal>{{ rps.tomador.inscricao_municipal }}</InscricaoMunicipal>
</IdentificacaoTomador>
<RazaoSocial>{{ rps.tomador.razao_social }}</RazaoSocial>
<Endereco>
<Endereco>{{ rps.tomador.logradouro }}</Endereco>
<Numero>{{ rps.tomador.numero }}</Numero>
<Complemento>{{ rps.tomador.complemento }}</Complemento>
<Bairro>{{ rps.tomador.bairro }}</Bairro>
<CodigoMunicipio>{{ rps.tomador.cidade }}</CodigoMunicipio>
<Uf>{{ rps.tomador.uf }}</Uf>
<Cep>{{ rps.tomador.cep }}</Cep>
</Endereco>
<Contato>
<Telefone>{{ rps.tomador.telefone }}</Telefone>
<Email>{{ rps.tomador.email }}</Email>
</Contato>
</Tomador>
{% if rps.intermediario is defined -%}
<IntermediarioServico>
<RazaoSocial>{{ rps.intermediario.razao_social }}</RazaoSocial>
<CpfCnpj>
<Cnpj>{{ rps.intermediario.cnpj }}</Cnpj>
</CpfCnpj>
<InscricaoMunicipal>{{ rps.intermediario.inscricao_municipal }}</InscricaoMunicipal>
</IntermediarioServico>
{% endif %}
{% if rps.construcao_civil is defined -%}
<ContrucaoCivil>
<CodigoObra>{{ rps.construcao_civil.codigo_obra }}</CodigoObra>
<Art>{{ rps.construcao_civil.art }}</Art>
</ContrucaoCivil>
{% endif %}
</InfRps>
</Rps>

1
pytrustnfe/utils.py

@ -13,6 +13,7 @@ class CabecalhoSoap(object):
def __init__(self, **kwargs):
self.versao = kwargs.pop('versao', '')
self.estado = kwargs.pop('estado', '')
self.method = kwargs.pop('method', '')
self.soap_action = kwargs.pop('soap_action', '')

Loading…
Cancel
Save