Browse Source

Adição envio NFe

pull/9/head
martini97 9 years ago
parent
commit
25c61605b7
  1. 24
      README.md
  2. 53
      cidades/betha.md
  3. 62
      cidades/ginfes.md
  4. 0
      cidades/issintel.md
  5. 0
      cidades/issnet.md
  6. 8
      cidades/saatri.md
  7. 32
      cidades/webiss.md
  8. 38
      pytrustnfe/Servidores.py
  9. 38
      pytrustnfe/nfe/__init__.py
  10. 8
      pytrustnfe/nfe/assinatura.py
  11. 2
      pytrustnfe/nfe/templates/NfeAutorizacao.xml
  12. 22
      pytrustnfe/nfe/templates/RecepcaoEventoCancelamento.xml
  13. 113
      pytrustnfe/nfse/betha/__init__.py
  14. 15
      pytrustnfe/nfse/betha/templates/CancelarNfse.xml
  15. 8
      pytrustnfe/nfse/betha/templates/ConsultarLoteRps.xml
  16. 13
      pytrustnfe/nfse/betha/templates/ConsultarNfseFaixa.xml
  17. 13
      pytrustnfe/nfse/betha/templates/ConsultarNfsePorRps.xml
  18. 13
      pytrustnfe/nfse/betha/templates/ConsultarNfseServicoPrestado.xml
  19. 27
      pytrustnfe/nfse/betha/templates/ConsultarNfseServicoTomado.xml
  20. 3
      pytrustnfe/nfse/betha/templates/GerarNfse.xml
  21. 13
      pytrustnfe/nfse/betha/templates/RecepcionarLoteRps.xml
  22. 13
      pytrustnfe/nfse/betha/templates/RecepcionarLoteRpsSincrono.xml
  23. 78
      pytrustnfe/nfse/betha/templates/Rps.xml
  24. 18
      pytrustnfe/nfse/betha/templates/SubstituirNfse.xml
  25. 3
      pytrustnfe/nfse/ginfes/__init__.py
  26. 3
      pytrustnfe/nfse/issintel/__init__.py
  27. 3
      pytrustnfe/nfse/issnet/__init__.py
  28. 16
      pytrustnfe/nfse/paulistana/templates/EnvioLoteRPS.xml
  29. 3
      pytrustnfe/nfse/saatri/__init__.py
  30. 3
      pytrustnfe/nfse/webiss/__init__.py
  31. 37
      pytrustnfe/test/XMLs/paulistana_signature.xml
  32. 29
      pytrustnfe/test/test_nfse_paulistana.py

24
README.md

@ -14,6 +14,22 @@ Dependências:
* reportlab
* Jinja2
Roadmap
--------------
Teste unitários
Emissão de NFCe
Compatibilidade [python 2 e 3](https://github.com/danimaribeiro/PyTrustNFe/pull/6)
Implementar novos provedores de NFSe
* [Betha](cidades/betha.md) - 81 cidades atendidas WIP
* [GINFES](cidades/ginfes.md) - 79 cidades atendidas
* [WebISS](cidades/webiss.md) - 51 cidades atendidas
* [ISSIntel](cidades/issintel.md) - 32 cidades atendidas
* [ISSNET](cidades/issnet.md) - 32 cidades atendidas
* [Saatri](cidades/saatri.md) - 31 cidades atendidas
Exemplos de uso da NFe
---------------
@ -48,8 +64,8 @@ Envio de RPS por lote
'numero': '1',
'data_emissao': '2016-08-29',
'codigo_atividade': '07498',
'total_servicos': '2.00',
'total_deducoes': '3.00',
'valor_servico': '2.00',
'valor_deducao': '3.00',
'prestador': {
'inscricao_municipal': '123456'
},
@ -62,7 +78,7 @@ Envio de RPS por lote
'logradouro': 'Vinicius de Moraes, 42',
'numero': '42',
'bairro': 'Corrego',
'cidade': 'Floripa',
'cidade': '4205407', # Código da cidade, de acordo com o IBGE
'uf': 'SC',
'cep': '88037240',
},
@ -75,6 +91,8 @@ Envio de RPS por lote
'cpf_cnpj': '12345678901234',
'data_inicio': '2016-08-29',
'data_fim': '2016-08-29',
'total_servicos': '2.00',
'total_deducoes': '3.00',
'lista_rps': rps
}

53
cidades/betha.md

@ -0,0 +1,53 @@
* Água Boa - MT
* Alfenas - MG
* Almirante Tamandaré - PR
* Barracão - PR
* Braço do Norte - SC
* Bento Gonçalves - RS
* Bombinhas - SC
* Capão da Canoa - RS
* Capinzal - SC
* Catanduvas - SC
* Chapecó - SC
* Cocal do Sul - SC
* Congonhas - MG
* Cornélio Procópio - PR
* Criciúma - SC
* Dionísio Cerqueira - SC
* Imbituba - SC
* Garopaba - SC
* General Carneiro - PR
* Goioerê - PR
* Fazenda Rio Grande - PR
* Juti - MS
* Joaçaba - SC
* Itapiranga - SC
* Itaú de Minas - MG
* Lages - SC
* Laguna - SC
* Mandaguaçu - PR
* Mandirituba - PR
* Maravilha - SC
* Mariana - MG
* Mococa - SP
* Morro da Fumaça - SC
* Navegantes - SC
* Nova Andradina - MS
* Orlândia - SP
* Orleans - SC
* Paranavaí - PR
* Pinhalzinho - SC
* Santa Rosa de Viterbo - SP
* Santo Amaro da Imperatriz - SC.
* São Joaquim - SC
* São José - SC
* São Mateus do Sul - PR
* São Miguel do Oeste - SC
* Sombrio - SC
* Tijucas - SC
* Torres - RS
* União da Vitória - PR
* Urussanga - SC
* Várzea Grande - MT
* Xanxerê - SC
* Xaxim - SC

62
cidades/ginfes.md

@ -0,0 +1,62 @@
* Amparo - SP
* Arapiraca - AL
* Araraquara - SP
* Araxá - MG
* Belford Roxo - RJ
* Betim - MG
* Caraguatatuba - SP
* Caruaru - PE
* Capivari - SP
* Cataguases - MG
* Cotia - SP
* Diadema - SP
* Eusébio - CE
* Fortaleza - CE
* Franca - SP
* Guaíba - RS
* Guaratinguetá - SP
* Guarujá - SP
* Guarulhos - SP
* Hortolândia - SP
* Itaboraí - RJ
* Itabira - MG
* Itajuba - MG
* Itaúna - MG
* Itu - SP
* Jaboticabal - SP
* Jardinópolis - SP
* Jaú - SP
* Jundiaí - SP
* Lagoa Santa - MG
* Maceió - AL
* Manaus - AM
* Morro Agudo - SP
* Mauá - SP
* Muriaé - MG
* Olímpia - SP
* Paulínia - SP
* Pelotas - RS
* Poços de Caldas - MG
* Porto Ferreira - SP
* Pouso Alegre - MG
* Ribeirão das Neves - MG
* Ribeirão Pires - SP
* Ribeirão Preto - SP
* Rio Claro - SP
* Salto - SP
* Santa Rita do Passa Quatro - SP
* Santo André - SP
* Santos - SP
* São Bernardo do Campo - SP
* São Caetano do Sul - SP
* São Carlos - SP
* São José do Rio Preto - SP
* São José dos Campos - SP
* São Roque - SP
* Sarzedo - MG
* Suzano - SP
* Taquaritinga - SP
* Ubá - MG
* Ubatuba - SP
* Umuarama - PR
* Votuporanga - SP

0
cidades/issintel.md

0
cidades/issnet.md

8
cidades/saatri.md

@ -0,0 +1,8 @@
* Barreiras - BA
* Boa Vista - RR
* Bom Jesus da Lapa - BA
* Catu - BA
* Eunápolis - BA
* Ipiaú - BA
* Jacobina - BA
* São Sebastião de Passé - BA

32
cidades/webiss.md

@ -0,0 +1,32 @@
* Aracajú - SE
* Arcos - MG
* Bagé - RS
* Barbacena - MG
* Brumado - BA.
* Campo Belo - MG
* Candeias - BA
* Cássia - MG
* Caldas Novas - GO
* Coronel Fabriciano - MG
* Estância - SE
* Extrema - MG
* Feira de Santana–BA
* Formiga - MG
* Guanambi - BA
* Itabuna - BA
* Itapetinga - BA
* Lagarto - SE
* Lucas do Rio Verde - MT
* Luís Eduardo Magalhães - BA
* Niterói - RJ
* Nova Serrana - MG
* Palmas - TO
* Passos - MG
* Porto Nacional - TO
* Santa Rita do Sapucai - MG
* São Gotardo - MG
* São Lourenço - MG
* Tangará da Serra - MT
* Teresópolis - RJ
* Uberaba-MG
* Vitória da Conquista - BA

38
pytrustnfe/Servidores.py

@ -10,15 +10,15 @@ WS_NFE_CONSULTA = 'NfeConsultaProtocolo'
WS_NFE_SITUACAO = 'NfeStatusServico'
WS_NFE_CADASTRO = 'NfeConsultaCadastro'
WS_NFCE_AUTORIZACAO = 'NfceAutorizacao'
WS_NFCE_RET_AUTORIZACAO = 'NfceRetAutorizacao'
WS_NFCE_AUTORIZACAO = 'NfeAutorizacao'
WS_NFCE_RET_AUTORIZACAO = 'NfeRetAutorizacao'
WS_NFCE_CANCELAMENTO = 'RecepcaoEventoCancelamento'
WS_NFCE_INUTILIZACAO = 'NfceInutilizacao'
WS_NFCE_CONSULTA = 'NfceConsultaProtocolo'
WS_NFCE_SITUACAO = 'NfceStatusServico'
WS_NFCE_CADASTRO = 'NfceConsultaCadastro'
WS_NFCE_INUTILIZACAO = 'NfeInutilizacao'
WS_NFCE_CONSULTA = 'NfeConsultaProtocolo'
WS_NFCE_SITUACAO = 'NfeStatusServico'
WS_NFCE_CADASTRO = 'NfeConsultaCadastro'
WS_NFCE_RECEPCAO_EVENTO = 'RecepcaoEventoCarta'
WS_NFCE_QR_CODE = 'NcfeQRCode'
WS_NFCE_QR_CODE = 'NfeQRCode'
WS_NFE_CADASTRO = 'NfeConsultaCadastro'
WS_DPEC_RECEPCAO = 'RecepcaoEventoEPEC'
@ -34,8 +34,8 @@ NFE_AMBIENTE_HOMOLOGACAO = 2
NFCE_AMBIENTE_PRODUCAO = 1
NFCE_AMBIENTE_HOMOLOGACAO = 2
NFE_MODELO = 55
NFCE_MODELO = 65
NFE_MODELO = u'55'
NFCE_MODELO = u'65'
SIGLA_ESTADO = {
'12': 'AC',
@ -69,11 +69,9 @@ SIGLA_ESTADO = {
def localizar_url(servico, estado, mod=55, ambiente=2):
import pdb
pdb.set_trace()
sigla = SIGLA_ESTADO[estado]
dominio = ESTADO_WS[sigla][ambiente]['servidor']
complemento = ESTADO_WS[sigla][ambiente][servico]
dominio = ESTADO_WS[sigla][mod][ambiente]['servidor']
complemento = ESTADO_WS[sigla][mod][ambiente][servico]
if sigla == 'RS' and servico == WS_NFE_CADASTRO:
dominio = 'cad.sefazrs.rs.gov.br'
@ -84,6 +82,14 @@ def localizar_url(servico, estado, mod=55, ambiente=2):
return "https://%s/%s" % (dominio, complemento)
def localizar_qrcode(estado, ambiente=2):
sigla = SIGLA_ESTADO[estado]
dominio = ESTADO_WS[sigla]['65'][ambiente]['servidor']
complemento = ESTADO_WS[sigla]['65'][ambiente][WS_NFCE_QR_CODE]
return "https://%s/%s" % (dominio, complemento)
METODO_WS = {
WS_NFE_AUTORIZACAO: {
'webservice': 'NfeAutorizacao',
@ -131,6 +137,7 @@ SVRS = {
NFE_AMBIENTE_PRODUCAO: {
'servidor': 'nfe.svrs.rs.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFE_CANCELAMENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFE_AUTORIZACAO: 'ws/NfeAutorizacao/NfeAutorizacao.asmx',
WS_NFE_RET_AUTORIZACAO: 'ws/NfeRetAutorizacao/NfeRetAutorizacao.asmx',
WS_NFE_CADASTRO: 'ws/CadConsultaCadastro/CadConsultaCadastro2.asmx',
@ -141,6 +148,7 @@ SVRS = {
NFE_AMBIENTE_HOMOLOGACAO: {
'servidor': 'nfe-homologacao.svrs.rs.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFE_CANCELAMENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFE_AUTORIZACAO: 'ws/NfeAutorizacao/NfeAutorizacao.asmx',
WS_NFE_RET_AUTORIZACAO: 'ws/NfeRetAutorizacao/NfeRetAutorizacao.asmx',
WS_NFE_CADASTRO: 'ws/CadConsultaCadastro/CadConsultaCadastro2.asmx',
@ -486,6 +494,7 @@ UFRS = {
WS_NFE_INUTILIZACAO: 'ws/NfeInutilizacao/NfeInutilizacao2.asmx',
WS_NFE_CONSULTA: 'ws/NfeConsulta/NfeConsulta2.asmx',
WS_NFE_SITUACAO: 'ws/NfeStatusServico/NfeStatusServico2.asmx',
WS_NFE_CANCELAMENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
},
NFE_AMBIENTE_HOMOLOGACAO: {
'servidor': 'nfe-homologacao.sefazrs.rs.gov.br',
@ -498,6 +507,7 @@ UFRS = {
WS_NFE_INUTILIZACAO: 'ws/NfeInutilizacao/NfeInutilizacao2.asmx',
WS_NFE_CONSULTA: 'ws/NfeConsulta/NfeConsulta2.asmx',
WS_NFE_SITUACAO: 'ws/NfeStatusServico/NfeStatusServico2.asmx',
WS_NFE_CANCELAMENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
}
}
@ -546,7 +556,7 @@ UFSP = {
WS_NFCE_SITUACAO: 'ws/nfestatusservico2.asmx',
WS_NFCE_CADASTRO: 'ws/cadconsultacadastro2.asmx',
WS_NFCE_RECEPCAO_EVENTO: 'ws/recepcaoevento.asmx',
WS_NFCE_QR_CODE: '/NFCEConsultaPublica/Paginas/ConstultaQRCode.aspx',
WS_NFCE_QR_CODE: 'NFCEConsultaPublica/Paginas/ConstultaQRCode.aspx',
}
}
}

38
pytrustnfe/nfe/__init__.py

@ -10,7 +10,7 @@ from .assinatura import Assinatura
from pytrustnfe.xml import render_xml
from pytrustnfe.utils import CabecalhoSoap
from pytrustnfe.utils import gerar_chave, ChaveNFe
from pytrustnfe.Servidores import localizar_url
from pytrustnfe.Servidores import localizar_url, localizar_qrcode
def _build_header(method, **kwargs):
@ -18,6 +18,7 @@ def _build_header(method, **kwargs):
'NfeAutorizacao': ('NfeAutorizacao', '3.10'),
'NfeRetAutorizacao': ('NfeRetAutorizacao', '3.10'),
'NfeConsultaCadastro': ('CadConsultaCadastro2', '2.00'),
'RecepcaoEventoCancelamento': ('RecepcaoEvento', '1.00')
}
vals = {'estado': kwargs['estado'],
'soap_action': action[method][0],
@ -60,9 +61,31 @@ def _add_required_node(elemTree):
return elemTree
def _add_qrCode(xml, **kwargs):
xml = etree.fromstring(xml)
inf_nfe = kwargs['NFes'][0]['infNFe']
nfe = xml.find(".//{http://www.portalfiscal.inf.br/nfe}NFe")
infnfesupl = etree.Element('infNFeSupl')
qrcode = etree.Element('qrCode')
qrcode_url = localizar_qrcode(kwargs['estado'], kwargs['ambiente'])
chave_nfe = inf_nfe['Id'][3:]
dh_emissao = inf_nfe['ide']['dhEmi'].encode('hex')
versao = 100
ambiente = kwargs['ambiente']
valor_total = inf_nfe['total']['vNF']
if inf_nfe.get('dest', False):
dest_cpf = inf_nfe['dest'].get('CPF', False)
icms_total = inf_nfe['total']['vICMS']
dig_val_tag = xml.find(
".//{http://www.portalfiscal.inf.br/nfe}Signature/SignedInfo/Reference/DigestValue")
dig_val = dig_val_tag.text.encode('hex')
qrcode_text = qrcode_url
def _send(certificado, method, sign, **kwargs):
path = os.path.join(os.path.dirname(__file__), 'templates')
modelo = kwargs['NFes'][0]['infNFe']['ide']['mod']
xmlElem_send = render_xml(path, '%s.xml' % method, True, **kwargs)
if sign:
# Caso for autorização temos que adicionar algumas tags tipo
@ -71,12 +94,21 @@ def _send(certificado, method, sign, **kwargs):
xmlElem_send = _add_required_node(xmlElem_send)
signer = Assinatura(certificado.pfx, certificado.password)
if method == 'NfeAutorizacao':
xml_send = signer.assina_xml(
xmlElem_send, kwargs['NFes'][0]['infNFe']['Id'])
elif method == 'RecepcaoEventoCancelamento':
xml_send = signer.assina_xml(
xmlElem_send, kwargs['eventos'][0]['Id'])
if modelo == '65':
_add_qrCode(xml_send, **kwargs)
else:
xml_send = etree.tostring(xmlElem_send)
url = localizar_url(method, kwargs['estado'], kwargs['ambiente'])
url = localizar_url(method, kwargs['estado'], modelo,
kwargs['ambiente'])
cabecalho = _build_header(method, **kwargs)
response, obj = executar_consulta(certificado, url, cabecalho, xml_send)

8
pytrustnfe/nfe/assinatura.py

@ -33,6 +33,10 @@ class Assinatura(object):
signed_root = signer.sign(
xml_element, key=key, cert=cert,
reference_uri=('#%s' % reference))
if len(signed_root) > 3:
signed_root[2].append(signed_root[3])
element_signed = signed_root.find(".//*[@Id='%s']" % reference)
signature = signed_root.find(
".//{http://www.w3.org/2000/09/xmldsig#}Signature")
if element_signed and signature:
parent = element_signed.getparent()
parent.append(signature)
return etree.tostring(signed_root)

2
pytrustnfe/nfe/templates/NfeAutorizacao.xml

@ -99,7 +99,7 @@
<CRT>{{ emit.CRT }}</CRT>
{% endwith %}
</emit>
{% if dest is defined %}
{% if NFe.infNFe.dest is defined %}
<dest>
{% with dest = NFe.infNFe.dest %}
{% if dest.tipo == 'person' -%}

22
pytrustnfe/nfe/templates/RecepcaoEventoCancelamento.xml

@ -1,20 +1,22 @@
<envEvento xmlns="http://www.portalfiscal.inf.br/nfe" versao="1.00">
<idLote>{{ obj.lote }}</idLote>
<idLote>{{ idLote }}</idLote>
{% for evento in eventos %}
<evento xmlns="http://www.portalfiscal.inf.br/nfe" versao="1.00">
<infEvento Id="{{ obj.id }}">
<cOrgao>{{ obj.orgao }}</cOrgao>
<tpAmb>{{ obj.ambiente }}</tpAmb>
<CNPJ>{{ obj.cnpj }}</CNPJ>
<chNFe>{{ obj.chave_nfe }}</chNFe>
<dhEvento>{{ obj.data_hora_evento }}</dhEvento>
<infEvento Id="{{ evento.Id }}">
<cOrgao>{{ evento.cOrgao }}</cOrgao>
<tpAmb>{{ evento.tpAmb }}</tpAmb>
<CNPJ>{{ evento.CNPJ }}</CNPJ>
<chNFe>{{ evento.chNFe }}</chNFe>
<dhEvento>{{ evento.dhEvento }}</dhEvento>
<tpEvento>110111</tpEvento>
<nSeqEvento>{{ obj.numero_evento }}</nSeqEvento>
<nSeqEvento>{{ evento.nSeqEvento }}</nSeqEvento>
<verEvento>1.00</verEvento>
<detEvento versao="1.00">
<descEvento>Cancelamento</descEvento>
<nProt>{{ obj.protocolo }}</nProt>
<xJust>{{obj.justificativa }}</xJust>
<nProt>{{ evento.nProt }}</nProt>
<xJust>{{ evento.xJust }}</xJust>
</detEvento>
</infEvento>
</evento>
{% endfor %}
</envEvento>

113
pytrustnfe/nfse/betha/__init__.py

@ -0,0 +1,113 @@
# -*- coding: utf-8 -*-
# © 2016 Danimar Ribeiro, Trustcode
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import os
import suds
from OpenSSL import crypto
from base64 import b64encode
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
from pytrustnfe.nfse.assinatura import Assinatura
def sign_tag(certificado, **kwargs):
pkcs12 = crypto.load_pkcs12(certificado.pfx, certificado.password)
key = pkcs12.get_privatekey()
if 'nfse' in kwargs:
for item in kwargs['nfse']['lista_rps']:
signed = crypto.sign(key, item['assinatura'], 'SHA1')
item['assinatura'] = b64encode(signed)
if 'cancelamento' in kwargs:
signed = crypto.sign(key, kwargs['cancelamento']['assinatura'], 'SHA1')
kwargs['cancelamento']['assinatura'] = b64encode(signed)
def _send(certificado, method, **kwargs):
path = os.path.join(os.path.dirname(__file__), 'templates')
if method in ('GerarNfse', 'RecepcionarLoteRps',
'RecepcionarLoteRpsSincrono',
'CancelarNfse', 'SubstituirNfse'):
sign_tag(certificado, **kwargs)
if kwargs['ambiente'] == 'producao':
url = \
'http://e-gov.betha.com.br/e-nota-contribuinte-test-ws/nfseWS?wsdl'
else:
url = 'http://e-gov.betha.com.br/e-nota-contribuinte-ws/nfseWS?wsdl'
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)
client = get_authenticated_client(url, cert, key)
pfx_path = certificado.save_pfx()
signer = Assinatura(pfx_path, certificado.password)
xml_send = signer.assina_xml(xml_send, '')
try:
response = getattr(client.service, method)(1, xml_send)
except suds.WebFault, e:
return {
'sent_xml': xml_send,
'received_xml': e.fault.faultstring,
'object': None
}
response, obj = sanitize_response(response)
return {
'sent_xml': xml_send,
'received_xml': response,
'object': obj
}
def gerar_nfse(certificado, **kwargs):
return _send(certificado, 'GerarNfse', **kwargs)
def envio_lote_rps_assincrono(certificado, **kwargs):
return _send(certificado, 'RecepcionarLoteRps', **kwargs)
def envio_lote_rps(certificado, **kwargs):
return _send(certificado, 'RecepcionarLoteRpsSincrono', **kwargs)
def cancelar_nfse(certificado, **kwargs):
return _send(certificado, 'CancelarNfse', **kwargs)
def substituir_nfse(certificado, **kwargs):
return _send(certificado, 'SubstituirNfse', **kwargs)
def consulta_situacao_lote_rps(certificado, **kwargs):
return _send(certificado, 'ConsultaSituacaoLoteRPS', **kwargs)
def consulta_nfse_por_rps(certificado, **kwargs):
return _send(certificado, 'ConsultaNfsePorRps', **kwargs)
def consultar_lote_rps(certificado, **kwargs):
return _send(certificado, 'ConsultarLoteRps', **kwargs)
def consulta_nfse_servico_prestado(certificado, **kwargs):
return _send(certificado, 'ConsultarNfseServicoPrestado', **kwargs)
def consultar_nfse_servico_tomado(certificado, **kwargs):
return _send(certificado, 'ConsultarNfseServicoTomado', **kwargs)
def consulta_nfse_faixe(certificado, **kwargs):
return _send(certificado, 'ConsultarNfseFaixa', **kwargs)
def consulta_cnpj(certificado, **kwargs):
return _send(certificado, 'ConsultaCNPJ', **kwargs)

15
pytrustnfe/nfse/betha/templates/CancelarNfse.xml

@ -0,0 +1,15 @@
<CancelarNfseEnvio xmlns = "http://www.betha.com.br/e-nota-contribuinte-ws">
<Pedido>
<InfPedidoCancelamento Id="1">
<IdentificacaoNfse>
<Numero>58</Numero>
<CpfCnpj>
<Cnpj>45111111111100</Cnpj>
</CpfCnpj>
<InscricaoMunicipal>123498</InscricaoMunicipal>
<CodigoMunicipio>4204608</CodigoMunicipio>
</IdentificacaoNfse>
<CodigoCancelamento>1</CodigoCancelamento>
</InfPedidoCancelamento>
</Pedido>
</CancelarNfseEnvio>

8
pytrustnfe/nfse/betha/templates/ConsultarLoteRps.xml

@ -0,0 +1,8 @@
<ConsultarLoteRpsEnvio xmlns="http://www.betha.com.br/e-nota-contribuinte-ws">
<Prestador>
<CpfCnpj>
<Cnpj>45111111111100</Cnpj>
</CpfCnpj>
</Prestador>
<Protocolo>141542179222170</Protocolo>
</ConsultarLoteRpsEnvio>

13
pytrustnfe/nfse/betha/templates/ConsultarNfseFaixa.xml

@ -0,0 +1,13 @@
<ConsultarNfseFaixaEnvio xmlns="http://www.betha.com.br/e-nota-contribuinte-ws">
<Prestador>
<CpfCnpj>
<Cnpj>45111111111100</Cnpj>
</CpfCnpj>
<InscricaoMunicipal>123498</InscricaoMunicipal>
</Prestador>
<Faixa>
<NumeroNfseInicial>50</NumeroNfseInicial>
<NumeroNfseFinal>60</NumeroNfseFinal>
</Faixa>
<Pagina>1</Pagina>
</ConsultarNfseFaixaEnvio>

13
pytrustnfe/nfse/betha/templates/ConsultarNfsePorRps.xml

@ -0,0 +1,13 @@
<ConsultarNfseRpsEnvio xmlns="http://www.betha.com.br/e-nota-contribuinte-ws">
<IdentificacaoRps>
<Numero>24</Numero>
<Serie>A1</Serie>
<Tipo>1</Tipo>
</IdentificacaoRps>
<Prestador>
<CpfCnpj>
<Cnpj>45111111111100</Cnpj>
</CpfCnpj>
<InscricaoMunicipal>123498</InscricaoMunicipal>
</Prestador>
</ConsultarNfseRpsEnvio>

13
pytrustnfe/nfse/betha/templates/ConsultarNfseServicoPrestado.xml

@ -0,0 +1,13 @@
<ConsultarNfseServicoPrestadoEnvio xmlns="http://www.betha.com.br/e-nota-contribuinte-ws">
<Prestador>
<CpfCnpj>
<Cnpj>45111111111100</Cnpj>
</CpfCnpj>
</Prestador>
<NumeroNfse>61</NumeroNfse>
<PeriodoEmissao>
<DataInicial>2014-12-01</DataInicial>
<DataFinal>2014-12-31</DataFinal>
</PeriodoEmissao>
<Pagina>1</Pagina>
</ConsultarNfseServicoPrestadoEnvio>

27
pytrustnfe/nfse/betha/templates/ConsultarNfseServicoTomado.xml

@ -0,0 +1,27 @@
<ConsultarNfseServicoTomadoEnvio xmlns="http://www.betha.com.br/e-nota-contribuinte-ws">
<Consulente>
<CpfCnpj>
<Cnpj>45111111111100</Cnpj>
</CpfCnpj>
</Consulente>
<PeriodoEmissao>
<DataInicial>2014-01-01</DataInicial>
<DataFinal>2014-12-31</DataFinal>
</PeriodoEmissao>
<Prestador>
<CpfCnpj>
<Cnpj>45111111111100</Cnpj>
</CpfCnpj>
</Prestador>
<Tomador>
<CpfCnpj>
<Cnpj>83787494000123</Cnpj>
</CpfCnpj>
</Tomador>
<Intermediario>
<CpfCnpj>
<Cnpj>45111111111100</Cnpj>
</CpfCnpj>
</Intermediario>
<Pagina>1</Pagina>
</ConsultarNfseServicoTomadoEnvio>

3
pytrustnfe/nfse/betha/templates/GerarNfse.xml

@ -0,0 +1,3 @@
<GerarNfseEnvio xmlns = "http://www.betha.com.br/e-nota-contribuinte-ws">
{% include 'rps.xml' %}
</GerarNfseEnvio>

13
pytrustnfe/nfse/betha/templates/RecepcionarLoteRps.xml

@ -0,0 +1,13 @@
<EnviarLoteRpsEnvio xmlns = "http://www.betha.com.br/e-nota-contribuinte-ws">
<LoteRps Id="lote1" versao="2.02">
<NumeroLote>2012024</NumeroLote>
<CpfCnpj>
<Cnpj>45111111111100</Cnpj>
</CpfCnpj>
<InscricaoMunicipal>123498</InscricaoMunicipal>
<QuantidadeRps>1</QuantidadeRps>
<ListaRps>
{% include 'rps.xml' %}
</ListaRps>
</LoteRps>
</EnviarLoteRpsEnvio>

13
pytrustnfe/nfse/betha/templates/RecepcionarLoteRpsSincrono.xml

@ -0,0 +1,13 @@
<EnviarLoteRpsSincronoEnvio xmlns = "http://www.betha.com.br/e-nota-contribuinte-ws">
<LoteRps Id="lote1" versao="2.02">
<NumeroLote>2012021</NumeroLote>
<CpfCnpj>
<Cnpj>45111111111100</Cnpj>
</CpfCnpj>
<InscricaoMunicipal>123498</InscricaoMunicipal>
<QuantidadeRps>1</QuantidadeRps>
<ListaRps>
{% include 'rps.xml' %}
</ListaRps>
</LoteRps>
</EnviarLoteRpsSincronoEnvio>

78
pytrustnfe/nfse/betha/templates/Rps.xml

@ -0,0 +1,78 @@
<Rps>
<InfDeclaracaoPrestacaoServico Id="rps1">
<Rps>
<IdentificacaoRps>
<Numero>25</Numero>
<Serie>A1</Serie>
<Tipo>1</Tipo>
</IdentificacaoRps>
<DataEmissao>2014-12-06</DataEmissao>
<Status>1</Status>
</Rps>
<Competencia>2014-12-01</Competencia>
<Servico>
<Valores>
<ValorServicos>100</ValorServicos>
<ValorDeducoes>0</ValorDeducoes>
<ValorPis>0</ValorPis>
<ValorCofins>0</ValorCofins>
<ValorInss>0</ValorInss>
<ValorIr>0</ValorIr>
<ValorCsll>0</ValorCsll>
<OutrasRetencoes>0</OutrasRetencoes>
<DescontoIncondicionado>0</DescontoIncondicionado>
<DescontoCondicionado>0</DescontoCondicionado>
</Valores>
<IssRetido>2</IssRetido>
<ItemListaServico>0702</ItemListaServico>
<CodigoTributacaoMunicipio>2525</CodigoTributacaoMunicipio>
<Discriminacao>Prog.</Discriminacao>
<CodigoMunicipio>4204608</CodigoMunicipio>
<ExigibilidadeISS>1</ExigibilidadeISS>
<MunicipioIncidencia>4204608</MunicipioIncidencia>
</Servico>
<Prestador>
<CpfCnpj>
<Cnpj>45111111111100</Cnpj>
</CpfCnpj>
<InscricaoMunicipal>123498</InscricaoMunicipal>
</Prestador>
<Tomador>
<IdentificacaoTomador>
<CpfCnpj>
<Cnpj>83787494000123</Cnpj>
</CpfCnpj>
</IdentificacaoTomador>
<RazaoSocial>INSTITUICAO FINANCEIRA</RazaoSocial>
<Endereco>
<Endereco>AV. 7 DE SETEMBRO</Endereco>
<Numero>1505</Numero>
<Complemento>AO LADO DO JOAO AUTOMOVEIS</Complemento>
<Bairro>CENTRO</Bairro>
<CodigoMunicipio>4201406</CodigoMunicipio>
<Uf>SC</Uf>
<Cep>88900000</Cep>
</Endereco>
<Contato>
<Telefone>4835220026</Telefone>
<Email>luiz.alves@cxpostal.com</Email>
</Contato>
</Tomador>
<Intermediario>
<IdentificacaoIntermediario>
<CpfCnpj>
<Cnpj>06410987065144</Cnpj>
</CpfCnpj>
<InscricaoMunicipal>22252</InscricaoMunicipal>
</IdentificacaoIntermediario>
<RazaoSocial>CONSTRUTORA TERRA FIRME</RazaoSocial>
</Intermediario>
<ConstrucaoCivil>
<CodigoObra>142</CodigoObra>
<Art>1/2014</Art>
</ConstrucaoCivil>
<RegimeEspecialTributacao>3</RegimeEspecialTributacao>
<OptanteSimplesNacional>2</OptanteSimplesNacional>
<IncentivoFiscal>2</IncentivoFiscal>
</InfDeclaracaoPrestacaoServico>
</Rps>

18
pytrustnfe/nfse/betha/templates/SubstituirNfse.xml

@ -0,0 +1,18 @@
<SubstituirNfseEnvio xmlns = "http://www.betha.com.br/e-nota-contribuinte-ws">
<SubstituicaoNfse Id="subst">
<Pedido>
<InfPedidoCancelamento Id="cancel">
<IdentificacaoNfse>
<Numero>57</Numero>
<CpfCnpj>
<Cnpj>45111111111100</Cnpj>
</CpfCnpj>
<InscricaoMunicipal>123498</InscricaoMunicipal>
<CodigoMunicipio>4204608</CodigoMunicipio>
</IdentificacaoNfse>
<CodigoCancelamento>2</CodigoCancelamento>
</InfPedidoCancelamento>
</Pedido>
{% include 'rps.xml' %}
</SubstituicaoNfse>
</SubstituirNfseEnvio>

3
pytrustnfe/nfse/ginfes/__init__.py

@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
# © 2016 Danimar Ribeiro, Trustcode
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

3
pytrustnfe/nfse/issintel/__init__.py

@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
# © 2016 Danimar Ribeiro, Trustcode
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

3
pytrustnfe/nfse/issnet/__init__.py

@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
# © 2016 Danimar Ribeiro, Trustcode
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

16
pytrustnfe/nfse/paulistana/templates/EnvioLoteRPS.xml

@ -18,20 +18,20 @@
<SerieRPS>{{ rps.serie }}</SerieRPS>
<NumeroRPS>{{ rps.numero }}</NumeroRPS>
</ChaveRPS>
<TipoRPS>RPS</TipoRPS>
<TipoRPS>{{ rps.tipo_rps | default('RPS') }}</TipoRPS>
<DataEmissao>{{ rps.data_emissao }}</DataEmissao>
<StatusRPS>N</StatusRPS>
<TributacaoRPS>T</TributacaoRPS>
<TributacaoRPS>{{ rps.tributacao_rps | default('T') }}</TributacaoRPS>
<ValorServicos>{{ rps.valor_servico }}</ValorServicos>
<ValorDeducoes>{{ rps.valor_deducao }}</ValorDeducoes>
<ValorPIS>0.00</ValorPIS>
<ValorCOFINS>0.00</ValorCOFINS>
<ValorINSS>0.00</ValorINSS>
<ValorIR>0.00</ValorIR>
<ValorCSLL>0.00</ValorCSLL>
<ValorPIS>{{ rps.valor_pis | default('0.00') }}</ValorPIS>
<ValorCOFINS>{{ rps.valor_cofins | default('0.00') }}</ValorCOFINS>
<ValorINSS>{{ rps.valor_inss | default('0.00') }}</ValorINSS>
<ValorIR>{{ rps.valor_ir | default('0.00') }}</ValorIR>
<ValorCSLL>{{ rps.valor_csll | default('0.00') }}</ValorCSLL>
<CodigoServico>{{ rps.codigo_atividade }}</CodigoServico>
<AliquotaServicos>{{ rps.aliquota_atividade }}</AliquotaServicos>
<ISSRetido>false</ISSRetido>
<ISSRetido>{{ rps.iss_retido | default('false') }}</ISSRetido>
<CPFCNPJTomador>
{% if rps.tomador.tipo_cpfcnpj == 1 -%}
<CPF>{{ rps.tomador.cpf_cnpj }}</CPF>

3
pytrustnfe/nfse/saatri/__init__.py

@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
# © 2016 Danimar Ribeiro, Trustcode
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

3
pytrustnfe/nfse/webiss/__init__.py

@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
# © 2016 Danimar Ribeiro, Trustcode
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

37
pytrustnfe/test/XMLs/paulistana_signature.xml

@ -0,0 +1,37 @@
<?xml version="1.0"?>
<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 xmlns="" Versao="1"><CPFCNPJRemetente><CNPJ>12345678901234</CNPJ></CPFCNPJRemetente><transacao>false</transacao><dtInicio>2016-08-29</dtInicio><dtFim>2016-08-29</dtFim><QtdRPS>1</QtdRPS><ValorTotalServicos/><ValorTotalDeducoes/></Cabecalho><RPS xmlns=""><Assinatura>E4fpHYkQa7Naxn6IKGb7NwwZu5tPk/KXJ9hCwtZgq0xvKS450aQqqBL+7Iv46lTgqrSMu7+gLrl+LC1qs/8aT2mbHE8uaVFSbzwZ+sF/BkcT6nsFHLMswEiTAEs95Jb7hN1cC91xqQGRH4buw0TzxHKmhuLJ22WwtG/scxyKtjM=</Assinatura><ChaveRPS><InscricaoPrestador>123456</InscricaoPrestador><SerieRPS>1</SerieRPS><NumeroRPS>1</NumeroRPS></ChaveRPS><TipoRPS>RPS</TipoRPS><DataEmissao>2016-08-29</DataEmissao><StatusRPS>N</StatusRPS><TributacaoRPS>T</TributacaoRPS><ValorServicos/><ValorDeducoes/><ValorPIS>0.00</ValorPIS><ValorCOFINS>0.00</ValorCOFINS><ValorINSS>0.00</ValorINSS><ValorIR>0.00</ValorIR><ValorCSLL>0.00</ValorCSLL><CodigoServico>07498</CodigoServico><AliquotaServicos>5.00</AliquotaServicos><ISSRetido>false</ISSRetido><CPFCNPJTomador>
</CPFCNPJTomador><InscricaoMunicipalTomador>123456</InscricaoMunicipalTomador><RazaoSocialTomador>Trustcode</RazaoSocialTomador><EnderecoTomador><TipoLogradouro>1</TipoLogradouro><Logradouro>Vinicius de Moraes, 42</Logradouro><NumeroEndereco>42</NumeroEndereco><ComplementoEndereco/><Bairro>Corrego</Bairro><Cidade>Floripa</Cidade><UF>SC</UF><CEP>88037240</CEP></EnderecoTomador><Discriminacao>Venda de servico</Discriminacao></RPS><Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>ivaOwkcrt0pfuMYsAdfyLaUAcIk=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>FjIHdfPavSEyaWYhAT0z0shPLuTsqBKyy78PUEZ8PUhTZ+iSV0MOvAIRq9MPPVK9
jjXOw1TE903uSK8aJon52RNKPd68ORVJ3bKFSjTqQLxFRR9tiiAQFrWDETf7FF89
EhG6dy6TGcgVbOyn0Jqm8MkqrE1XrJ44orN1X+Jt+7U=</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>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==</X509Certificate>
</X509Data>
</KeyInfo>
</Signature></PedidoEnvioLoteRPS>

29
pytrustnfe/test/test_nfse_paulistana.py

@ -6,15 +6,15 @@ import unittest
from pytrustnfe.certificado import Certificado
from pytrustnfe.nfse.paulistana import envio_lote_rps
from pytrustnfe.nfse.paulistana import cancelamento_nfe
from pytrustnfe.nfse.assinatura import Assinatura
from pytrustnfe.nfse.paulistana import sign_tag
class test_nfse_paulistana(unittest.TestCase):
caminho = os.path.dirname(__file__)
def test_envio_nfse(self):
pfx_source = open(os.path.join(self.caminho, 'teste.pfx'), 'r').read()
pfx = Certificado(pfx_source, '123456')
def _get_nfse(self):
rps = [
{
'assinatura': '123',
@ -51,7 +51,13 @@ class test_nfse_paulistana(unittest.TestCase):
'data_fim': '2016-08-29',
'lista_rps': rps
}
return nfse
def test_envio_nfse(self):
pfx_source = open(os.path.join(self.caminho, 'teste.pfx'), 'r').read()
pfx = Certificado(pfx_source, '123456')
nfse = self._get_nfse()
path = os.path.join(os.path.dirname(__file__), 'XMLs')
xml_return = open(os.path.join(
path, 'paulistana_resultado.xml'), 'r').read()
@ -70,6 +76,23 @@ class test_nfse_paulistana(unittest.TestCase):
self.assertEqual(
retorno['object'].ChaveNFeRPS.ChaveRPS.NumeroRPS, 6)
def test_nfse_signature(self):
pfx_source = open(os.path.join(self.caminho, 'teste.pfx'), 'r').read()
pfx = Certificado(pfx_source, '123456')
nfse = self._get_nfse()
path = os.path.join(os.path.dirname(__file__), 'XMLs')
xml_sent = open(os.path.join(
path, 'paulistana_signature.xml'), 'r').read()
with mock.patch('pytrustnfe.nfse.paulistana.get_authenticated_client') as client:
retorno = mock.MagicMock()
client.return_value = retorno
retorno.service.EnvioLoteRPS.return_value = '<xml></xml>'
retorno = envio_lote_rps(pfx, nfse=nfse)
self.assertEqual(retorno['sent_xml'], xml_sent)
def _get_cancelamento(self):
return {
'cnpj_remetente': '123',

Loading…
Cancel
Save