Browse Source

Implementação da NFSe de São Paulo - em andamento

tags/0.1.5
Danimar Ribeiro 10 years ago
parent
commit
3d57240edd
  1. 15
      pytrustnfe/certificado.py
  2. 31
      pytrustnfe/client.py
  3. 49
      pytrustnfe/nfse/paulistana/__init__.py
  4. 18
      pytrustnfe/nfse/paulistana/templates/cancelamento.xml
  5. 12
      pytrustnfe/nfse/paulistana/templates/consulta_cnpj.xml
  6. 10
      pytrustnfe/nfse/paulistana/templates/consulta_lote.xml
  7. 19
      pytrustnfe/nfse/paulistana/templates/consulta_nfse_por_rps.xml
  8. 54
      pytrustnfe/nfse/paulistana/templates/envio_lote_rps.xml
  9. 51
      pytrustnfe/nfse/paulistana/templates/envio_rps.xml
  10. 12
      pytrustnfe/nfse/paulistana/templates/soap_header.xml
  11. 6
      pytrustnfe/xml/__init__.py
  12. 3
      setup.py

15
pytrustnfe/Certificado.py → pytrustnfe/certificado.py

@ -8,12 +8,15 @@ import os.path
from OpenSSL import crypto
def converte_pfx_pem(caminho, senha):
if not os.path.isfile(caminho):
raise Exception('Certificado não existe')
stream = open(caminho, 'rb').read()
class Certificado(object):
def __init__(self, pfx, password):
self.pfx = pfx
self.password = password
def converte_pfx_pem(pfx_stream, senha):
try:
certificado = crypto.load_pkcs12(stream, senha)
certificado = crypto.load_pkcs12(pfx_stream, senha)
privada = crypto.dump_privatekey(crypto.FILETYPE_PEM,
certificado.get_privatekey())
@ -24,4 +27,4 @@ def converte_pfx_pem(caminho, senha):
e.message[0][2] == 'mac verify failure':
raise Exception('Senha inválida')
raise
return privada, certificado
return certificado, privada

31
pytrustnfe/client.py

@ -0,0 +1,31 @@
import requests
import suds.client
import suds_requests
def get_authenticated_client(base_url, key_p, cert):
cache_location = '/tmp/suds'
cache = suds.cache.DocumentCache(location=cache_location)
session = requests.Session()
session.cert = (cert, key)
return suds.client.Client(
base_url,
cache=cache,
transport=suds_requests.RequestsTransport(session)
)
def get_client(base_url):
cache_location = '/tmp/suds'
cache = suds.cache.DocumentCache(location=cache_location)
session = requests.Session()
return suds.client.Client(
base_url,
cache=cache,
transport=suds_requests.RequestsTransport(session)
)

49
pytrustnfe/nfse/paulistana/__init__.py

@ -1,27 +1,45 @@
import os
from pytrustnfe.xml import render_xml
from pytrustnfe.client import get_authenticated_client
from pytrustnfe.certificado import converte_pfx_pem
def _send(method, data):
pass
# TODO Assinar xml e retornar objeto de resposta
def _send(certificado, method, **kwargs):
# A little hack to test
path = os.path.join(os.path.dirname(__file__), 'templates')
if method == 'teste_envio_lote_rps':
xml = render_xml(path, 'envio_lote_rps.xml', **kwargs)
else:
xml = render_xml(path, '%s.xml' % method, **kwargs)
base_url = 'https://nfe.prefeitura.sp.gov.br/ws/lotenfe.asmx'
def envio_rps(data=None):
return _send('envio_rps', data)
import ipdb; ipdb.set_trace()
key, cert = converte_pfx_pem(certificado.pfx, certificado.password)
client = get_authenticated_client(base_url, key, cert)
def envio_lote_rps(data=None):
return _send('envio_lote_rps', data)
response = client.teste_envio_lote_rps(xml)
def teste_envio_lote_rps(data=None):
return _send('teste_envio_lote_rps', data)
return response
def cancelamento_nfe(data=None):
return _send('cancelamento_n_fe', data)
def consulta_nfe(data=None):
return _send('consulta_n_fe', data)
def envio_rps(certificado, **kwargs):
return _send(certificado, 'envio_rps', **kwargs)
def consulta_nfe_recebidas(data=None):
return _send('consulta_n_fe_recebidas', data)
def envio_lote_rps(certificado, **kwargs):
return _send(certificado, 'envio_lote_rps', **kwargs)
def teste_envio_lote_rps(certificado, **kwargs):
return _send(certificado, 'teste_envio_lote_rps', **kwargs)
def cancelamento_nfe(certificado, **kwargs):
return _send(certificado, 'cancelamento_n_fe', **kwargs)
def consulta_nfe(certificado, **kwargs):
return _send('consulta_n_fe', **kwargs)
def consulta_nfe_recebidas(certificado, **kwargs):
return _send('consulta_n_fe_recebidas', **kwargs)
def consulta_nfe_emitidas(data=None):
return _send('consulta_n_fe_emitidas', data)
@ -34,4 +52,3 @@ def consulta_informacoes_lote(data=None):
def consulta_cnpj(data=None):
return _send('consulta_cnpj', data)

18
pytrustnfe/nfse/paulistana/templates/cancelamento.xml

@ -0,0 +1,18 @@
<ns1:ReqCancelamentoNFSe xmlns:ns1="http://localhost:8080/WsNFe2/lote"
xmlns:tipos="http://localhost:8080/WsNFe2/tp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://localhost:8080/WsNFe2/lote http://localhost:8080/WsNFe2/xsd/ReqCancelamentoNFSe.xsd">
<Cabecalho>
<CodCidade>{{ cancelamento.cidade }}</CodCidade>
<CPFCNPJRemetente>{{ cancelamento.cpf_cnpj }}</CPFCNPJRemetente>
<transacao>{{ cancelamento.transacao }}</transacao>
<Versao>1</Versao>
</Cabecalho>
<Lote Id="lote:{{ cancelamento.lote }}">
<Nota Id="nota:{{ cancelamento.nota_id }}">
<InscricaoMunicipalPrestador>{{ cancelamento.inscricao_municipal }}</InscricaoMunicipalPrestador>
<NumeroNota>{{ cancelamento.nota_id }}</NumeroNota>
<CodigoVerificacao>{{ cancelamento.assinatura }}</CodigoVerificacao>
<MotivoCancelamento>{{ cancelamento.motivo }}</MotivoCancelamento>
</Nota>
</Lote>
</ns1:ReqCancelamentoNFSe>

12
pytrustnfe/nfse/paulistana/templates/consulta_cnpj.xml

@ -0,0 +1,12 @@
<p1:PedidoConsultaCNPJ
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p1="http://www.prefeitura.sp.gov.br/nfe">
<Cabecalho Versao="1">
<CPFCNPJRemetente>
<CNPJ>{{ nfse.cpf_cnpj }}</CNPJ>
</CPFCNPJRemetente>
</Cabecalho>
<CNPJContribuinte>
<CNPJ>08944335000170</CNPJ>
</CNPJContribuinte>
</p1:PedidoConsultaCNPJ>

10
pytrustnfe/nfse/paulistana/templates/consulta_lote.xml

@ -0,0 +1,10 @@
<ns1:ReqConsultaLote xmlns:ns1="http://localhost:8080/WsNFe2/lote"
xmlns:tipos="http://localhost:8080/WsNFe2/tp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://localhost:8080/WsNFe2/lote http://localhost:8080/WsNFe2/xsd/ReqConsultaLote.xsd">
<Cabecalho>
<CodCidade>{{ consulta.cidade }}</CodCidade>
<CPFCNPJRemetente>{{ consulta.cpf_cnpj }}</CPFCNPJRemetente>
<Versao>1</Versao>
<NumeroLote>{{ consulta.lote }}</NumeroLote>
</Cabecalho>
</ns1:ReqConsultaLote>

19
pytrustnfe/nfse/paulistana/templates/consulta_nfse_por_rps.xml

@ -0,0 +1,19 @@
<ns1:ReqConsultaNFSeRPS xmlns:ns1="http://localhost:8080/WsNFe2/lote"
xmlns:tipos="http://localhost:8080/WsNFe2/tp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://localhost:8080/WsNFe2/lote http://localhost:8080/WsNFe2/xsd/ReqConsultaNFSeRPS.xsd">
<Cabecalho>
<CodCidade>{{ consulta.cidade }}</CodCidade>
<CPFCNPJRemetente>{{ consulta.cpf_cnpj }}</CPFCNPJRemetente>
<transacao>{{ consulta.transacao }}</transacao>
<Versao>1</Versao>
</Cabecalho>
<Lote Id="lote:{{ consulta.lote }}">
<RPSConsulta>
<RPS Id="rps:{{ consulta.rps_id }}">
<InscricaoMunicipalPrestador>{{ consulta.inscricao_municipal }}</InscricaoMunicipalPrestador>
<NumeroRPS>{{ consulta.rps_id }}</NumeroRPS>
<SeriePrestacao>{{ consulta.serie_prestacao }}</SeriePrestacao>
</RPS>
</RPSConsulta>
</Lote>
</ns1:ReqConsultaNFSeRPS>

54
pytrustnfe/nfse/paulistana/templates/envio_lote_rps.xml

@ -0,0 +1,54 @@
<PedidoEnvioLoteRPS
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.prefeitura.sp.gov.br/nfe">
<Cabecalho Versao="1" xmlns="">
<CPFCNPJRemetente>
<CNPJ>{{ nfse.cpf_cnpj }}</CNPJ>
</CPFCNPJRemetente>
<transacao>false</transacao>
<dtInicio>2016-02-08</dtInicio>
<dtFim>2016-02-08</dtFim>
<QtdRPS>1</QtdRPS>
<ValorTotalServicos>{{ nfse.total_servicos }}</ValorTotalServicos>
<ValorTotalDeducoes>{{ nfse.total_deducoes }}</ValorTotalDeducoes>
</Cabecalho>
{% for rps in nfse.lista_rps -%}
<RPS xmlns="">
<Assinatura>{{ rps.assinatura }}</Assinatura>
<ChaveRPS>
<InscricaoPrestador>{{ rps.prestador.inscricao_municipal }}</InscricaoPrestador>
<SerieRPS>{{ rps.serie }}</SerieRPS>
<NumeroRPS>{{ rps.numero }}</NumeroRPS>
</ChaveRPS>
<TipoRPS>RPS</TipoRPS>
<DataEmissao>{{ rps.data_emissao }}</DataEmissao>
<StatusRPS>N</StatusRPS>
<TributacaoRPS>T</TributacaoRPS>
<ValorServicos>1000</ValorServicos>
<ValorDeducoes>100</ValorDeducoes>
<CodigoServico>{{ rps.codigo_atividade }}</CodigoServico>
<AliquotaServicos>{{ rps.aliquota_atividade }}</AliquotaServicos>
<ISSRetido>false</ISSRetido>
<CPFCNPJTomador>
{% if rps.tomador.tipo_cpfcnpj == 1 -%}
<CPF>{{ rps.tomador.cpf_cnpj }}</CPF>
{% endif %}
{% if rps.tomador.tipo_cpfcnpj == 2 -%}
<CNPJ>{{ rps.tomador.cpf_cnpj }}</CNPJ>
{% endif %}
</CPFCNPJTomador>
<RazaoSocialTomador>{{ rps.tomador.razao_social }}</RazaoSocialTomador>
<EnderecoTomador>
<TipoLogradouro>{{ rps.tomador.tipo_logradouro }}</TipoLogradouro>
<Logradouro>{{ rps.tomador.logradouro }}</Logradouro>
<NumeroEndereco>{{ rps.tomador.numero }}</NumeroEndereco>
<ComplementoEndereco>{{ rps.tomador.complemento }}</ComplementoEndereco>
<Bairro>{{ rps.tomador.bairro }}</Bairro>
<Cidade>{{ rps.tomador.cidade }}</Cidade>
<UF>{{ rps.tomador.uf }}</UF>
<CEP>{{ rps.tomador.cep }}</CEP>
</EnderecoTomador>
<Discriminacao>{{ rps.descricao }}</Discriminacao>
{% endfor %}
</RPS>
</PedidoEnvioLoteRPS>

51
pytrustnfe/nfse/paulistana/templates/envio_rps.xml

@ -0,0 +1,51 @@
<PedidoEnvioRPS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.prefeitura.sp.gov.br/nfe">
<Cabecalho Versao="1" xmlns="">
<CPFCNPJRemetente>
<CNPJ>{{ nfse.cpf_cnpj }}</CNPJ>
</CPFCNPJRemetente>
</Cabecalho>
{% for rps in nfse.lista_rps -%}
<RPS xmlns="">
<Assinatura>{{ rps.assinatura }}</Assinatura>
<ChaveRPS>
<InscricaoPrestador>{{ rps.prestador.inscricao_municipal }}</InscricaoPrestador>
<SerieRPS>{{ rps.serie }}</SerieRPS>
<NumeroRPS>{{ rps.numero }}</NumeroRPS>
</ChaveRPS>
<TipoRPS>RPS-M</TipoRPS>
<DataEmissao>{{ rps.data_emissao }}</DataEmissao>
<StatusRPS>N</StatusRPS>
<TributacaoRPS>T</TributacaoRPS>
<ValorServicos>{{ nfse.total_servicos }}</ValorServicos>
<ValorDeducoes>{{ nfse.total_deducoes }}</ValorDeducoes>
<ValorPIS>{{ rps.valor_pis }}</ValorPIS>
<ValorCOFINS>{{ rps.valor_cofins }}</ValorCOFINS>
<ValorINSS>{{ rps.valor_inss }}</ValorINSS>
<ValorIR>{{ rps.valor_pis }}</ValorIR>
<ValorCSLL>{{ rps.valor_csll }}</ValorCSLL>
<CodigoServico>{{ rps.codigo_atividade }}</CodigoServico>
<AliquotaServicos>{{ rps.aliquota_atividade }}</AliquotaServicos>
<ISSRetido>false</ISSRetido>
<CPFCNPJTomador>
{% if rps.tomador.tipo_cpfcnpj == 1 -%}
<CPF>{{ rps.tomador.cpf_cnpj }}</CPF>
{% endif %}
{% if rps.tomador.tipo_cpfcnpj == 2 -%}
<CNPJ>{{ rps.tomador.cpf_cnpj }}</CNPJ>
{% endif %}
</CPFCNPJTomador>
<RazaoSocialTomador>{{ rps.tomador.razao_social }}</RazaoSocialTomador>
<EnderecoTomador>
<TipoLogradouro>{{ rps.tomador.tipo_logradouro }}</TipoLogradouro>
<Logradouro>{{ rps.tomador.logradouro }}</Logradouro>
<NumeroEndereco>{{ rps.tomador.numero }}</NumeroEndereco>
<ComplementoEndereco>{{ rps.tomador.complemento }}</ComplementoEndereco>
<Bairro>{{ rps.tomador.bairro }}</Bairro>
<Cidade>{{ rps.tomador.cidade }}</Cidade>
<UF>{{ rps.tomador.uf }}</UF>
<CEP>{{ rps.tomador.cep }}</CEP>
</EnderecoTomador>
<Discriminacao>{{ rps.descricao }}</Discriminacao>
{% endfor %}
</RPS>
</PedidoEnvioRPS>

12
pytrustnfe/nfse/paulistana/templates/soap_header.xml

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:dsf="http://dsfnet.com.br">
<soapenv:Body>
<dsf:enviar soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<mensagemXml xsi:type="xsd:string"><![CDATA[
{% block content %}{% endblock %}
]]></mensagemXml>
</dsf:enviar>
</soapenv:Body>
</soapenv:Envelope>

6
pytrustnfe/xml/__init__.py

@ -4,8 +4,7 @@ from jinja2 import Environment, FileSystemLoader
from . import filters
def render_xml(template_name, **nfe):
path = os.path.dirname(__file__)
def render_xml(path, template_name, **nfe):
env = Environment(
loader=FileSystemLoader(path), extensions=['jinja2.ext.with_'])
@ -19,4 +18,5 @@ def render_xml(template_name, **nfe):
xml = template.render(**nfe)
xml = xml.replace('&', '&amp;')
parser = etree.XMLParser(remove_blank_text=True, remove_comments=True)
return etree.fromstring(xml, parser=parser)
elem = etree.fromstring(xml, parser=parser)
return etree.tostring(elem)

3
setup.py

@ -18,7 +18,8 @@ setup(
'Topic :: Software Development :: Libraries :: Python Modules',
],
packages=find_packages(exclude=['*test*']),
package_data={'pytrustnfe': ['xml/*xml']},
package_data={'pytrustnfe': ['xml/*xml',
'nfse/paulistana/templates/*xml']},
url='https://github.com/danimaribeiro/PyNfeTrust',
license='LGPL-v2.1+',
description='PyNfeTrust é uma biblioteca para envio de NF-e',

Loading…
Cancel
Save