Browse Source

Merge branch 'master3' of https://github.com/danimaribeiro/PyTrustNFe into mergenfe4

Merge com o branch master3 da trust com nfe4 implementado
pull/283/head
renato sabo 7 years ago
parent
commit
b3e74529ad
  1. 2
      .travis.yml
  2. 487
      pytrustnfe/Servidores.py
  3. 31
      pytrustnfe/client.py
  4. 176
      pytrustnfe/nfe/__init__.py
  5. 34
      pytrustnfe/nfe/comunicacao.py
  6. 460
      pytrustnfe/nfe/danfce.py
  7. 12
      pytrustnfe/nfe/danfe.py
  8. 12
      pytrustnfe/nfe/templates/NFeDistribuicaoDFe.xml
  9. 91
      pytrustnfe/nfe/templates/NfeAutorizacao.xml
  10. 3
      pytrustnfe/nfe/templates/NfeConsultaProtocolo.xml
  11. 2
      pytrustnfe/nfe/templates/NfeInutilizacao.xml
  12. 2
      pytrustnfe/nfe/templates/NfeRetAutorizacao.xml
  13. 2
      pytrustnfe/nfe/templates/NfeStatusServico.xml
  14. 6
      pytrustnfe/nfe/templates/RecepcaoEvento.xml
  15. 21
      pytrustnfe/nfe/templates/RecepcaoEventoCarta.xml
  16. 31
      pytrustnfe/nfe/templates/RecepcaoEventoEPEC.xml
  17. 2
      pytrustnfe/nfe/templates/RecepcaoEventoManifesto.xml
  18. 18
      pytrustnfe/nfse/bh/__init__.py
  19. 44
      pytrustnfe/nfse/bh/assinatura.py
  20. 8
      pytrustnfe/nfse/bh/templates/GerarNfse.xml
  21. 2
      pytrustnfe/nfse/bh/templates/Rps.xml
  22. 31
      pytrustnfe/nfse/ginfes/__init__.py
  23. 75
      pytrustnfe/nfse/mga/__init__.py
  24. 45
      pytrustnfe/nfse/mga/assinatura.py
  25. 15
      pytrustnfe/nfse/mga/templates/CancelarNfse.xml
  26. 3
      pytrustnfe/nfse/mga/templates/GerarNfse.xml
  27. 81
      pytrustnfe/nfse/mga/templates/Rps.xml
  28. 4
      pytrustnfe/nfse/paulistana/__init__.py
  29. 11
      pytrustnfe/utils.py
  30. 15
      pytrustnfe/xml/__init__.py
  31. 2
      pytrustnfe/xml/schemas/enviNFe_v4.00.xsd
  32. 1104
      pytrustnfe/xml/schemas/leiauteNFe_v4.00.xsd
  33. 2
      pytrustnfe/xml/schemas/nfe_v4.00.xsd
  34. 22
      pytrustnfe/xml/schemas/tiposBasico_v4.00.xsd
  35. 2
      pytrustnfe/xml/validate.py
  36. 1
      requirements.txt
  37. 5
      setup.py
  38. 20
      tests/test_comunicacao.py
  39. 19
      tests/test_consulta_cadastro.py
  40. 12
      tests/test_servidores.py
  41. 8
      tests/test_utils.py

2
.travis.yml

@ -1,7 +1,5 @@
language: python
python:
- "3.4"
- "3.5"
- "3.6"
virtual_env:
system_site_packages: true

487
pytrustnfe/Servidores.py

@ -2,41 +2,29 @@
# © 2016 Danimar Ribeiro
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
WS_NFE_AUTORIZACAO = 'NfeAutorizacao'
WS_NFE_RET_AUTORIZACAO = 'NfeRetAutorizacao'
WS_NFE_CANCELAMENTO = 'RecepcaoEventoCancelamento'
# Consultas básicas da NF-e
WS_NFE_INUTILIZACAO = 'NfeInutilizacao'
WS_NFE_CONSULTA = 'NfeConsultaProtocolo'
WS_NFE_SITUACAO = 'NfeStatusServico'
WS_NFE_CADASTRO = 'NfeConsultaCadastro'
WS_NFCE_AUTORIZACAO = 'NfeAutorizacao'
WS_NFCE_RET_AUTORIZACAO = 'NfeRetAutorizacao'
WS_NFCE_CANCELAMENTO = 'RecepcaoEventoCancelamento'
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 = 'NfeQRCode'
WS_NFCE_CONSULTA_DESTINADAS = 'NfeConsultaDest',
WS_NFCE_RET_AUTORIZACAO = 'NFeRetAutorizacao',
WS_NFE_RECEPCAO_EVENTO = 'RecepcaoEvento'
WS_NFE_AUTORIZACAO = 'NfeAutorizacao'
WS_NFE_RET_AUTORIZACAO = 'NfeRetAutorizacao'
# Alguns estados possuem essa consulta não todos
WS_NFE_CADASTRO = 'NfeConsultaCadastro'
WS_DPEC_RECEPCAO = 'RecepcaoEventoEPEC'
WS_DPEC_CONSULTA = 8
WS_NFE_RECEPCAO_EVENTO = 'RecepcaoEventoCarta'
WS_NFE_RECEPCAO_EVENTO_MANIFESTO = 'RecepcaoEventoManifesto'
# Ambiente nacional
WS_NFCE_QR_CODE = 'NfeQRCode'
WS_NFCE_CONSULTA_DESTINADAS = 'NfeConsultaDest'
WS_DFE_DISTRIBUICAO = 'NFeDistribuicaoDFe'
WS_DOWNLOAD_NFE = 'nfeDistDFeInteresse'
NFE_AMBIENTE_PRODUCAO = 1
NFE_AMBIENTE_HOMOLOGACAO = 2
NFCE_AMBIENTE_PRODUCAO = 1
NFCE_AMBIENTE_HOMOLOGACAO = 2
# Códigos do ambiente de homologação e produção
AMBIENTE_PRODUCAO = 1
AMBIENTE_HOMOLOGACAO = 2
# Modelos dos documentos eletrônicos
NFE_MODELO = '55'
NFCE_MODELO = '65'
@ -68,6 +56,7 @@ SIGLA_ESTADO = {
'28': 'SE',
'35': 'SP',
'17': 'TO',
'91': 'AN'
}
@ -75,8 +64,7 @@ def localizar_url(servico, estado, mod='55', ambiente=2):
sigla = SIGLA_ESTADO[estado]
ws = ESTADO_WS[sigla]
if servico in (WS_DFE_DISTRIBUICAO, WS_DOWNLOAD_NFE,
WS_NFE_RECEPCAO_EVENTO_MANIFESTO):
if servico in (WS_DFE_DISTRIBUICAO, WS_DOWNLOAD_NFE):
ws = AN
if mod in ws:
@ -97,11 +85,8 @@ def localizar_url(servico, estado, mod='55', ambiente=2):
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]
if 'https://' in complemento:
return complemento
return "https://%s/%s" % (dominio, complemento)
ws_qrcode = ESTADO_WS[sigla][NFCE_MODELO][ambiente][WS_NFCE_QR_CODE]
return ws_qrcode
METODO_WS = {
@ -123,7 +108,6 @@ METODO_WS = {
},
WS_NFE_SITUACAO: {
'webservice': 'NfeStatusServico2',
'metodo': 'nfeStatusServicoNF2',
},
WS_NFE_CADASTRO: {
@ -137,32 +121,55 @@ METODO_WS = {
}
SVRS = {
NFE_AMBIENTE_PRODUCAO: {
NFE_MODELO: {
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',
WS_NFE_INUTILIZACAO: 'ws/nfeinutilizacao/nfeinutilizacao2.asmx',
WS_NFE_CONSULTA: 'ws/NfeConsulta/NfeConsulta2.asmx',
WS_NFE_SITUACAO: 'ws/NfeStatusServico/NfeStatusServico2.asmx',
},
NFE_AMBIENTE_HOMOLOGACAO: {
WS_NFE_INUTILIZACAO: 'ws/nfeinutilizacao/nfeinutilizacao4.asmx?wsdl', # noqa
WS_NFE_CONSULTA: 'ws/NfeConsulta/NfeConsulta4.asmx?wsdl',
WS_NFE_SITUACAO: 'ws/NfeStatusServico/NfeStatusServico4.asmx?wsdl',
WS_NFE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento4.asmx?wsdl', # noqa
WS_NFE_AUTORIZACAO: 'ws/NfeAutorizacao/NFeAutorizacao4.asmx?wsdl',
WS_NFE_RET_AUTORIZACAO: 'ws/NfeRetAutorizacao/NFeRetAutorizacao4.asmx?wsdl', # noqa
WS_NFE_CADASTRO: 'ws/cadconsultacadastro/cadconsultacadastro2.asmx?wsdl', # noqa
},
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',
WS_NFE_INUTILIZACAO: 'ws/nfeinutilizacao/nfeinutilizacao2.asmx',
WS_NFE_CONSULTA: 'ws/NfeConsulta/NfeConsulta2.asmx',
WS_NFE_SITUACAO: 'ws/NfeStatusServico/NfeStatusServico2.asmx',
WS_NFE_INUTILIZACAO: 'ws/nfeinutilizacao/nfeinutilizacao4.asmx?wsdl', # noqa
WS_NFE_CONSULTA: 'ws/NfeConsulta/NfeConsulta4.asmx?wsdl',
WS_NFE_SITUACAO: 'ws/NfeStatusServico/NfeStatusServico4.asmx?wsdl',
WS_NFE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento4.asmx?wsdl', # noqa
WS_NFE_AUTORIZACAO: 'ws/NfeAutorizacao/NFeAutorizacao4.asmx?wsdl',
WS_NFE_RET_AUTORIZACAO: 'ws/NfeRetAutorizacao/NFeRetAutorizacao4.asmx?wsdl', # noqa
WS_NFE_CADASTRO: 'ws/cadconsultacadastro/cadconsultacadastro2.asmx?wsdl', # noqa
}
},
NFCE_MODELO: {
AMBIENTE_PRODUCAO: {
'servidor': 'nfce.svrs.rs.gov.br',
WS_NFE_INUTILIZACAO: 'ws/nfeinutilizacao/nfeinutilizacao4.asmx?wsdl',
WS_NFE_CONSULTA: 'ws/NfeConsulta/NfeConsulta4.asmx?wsdl',
WS_NFE_SITUACAO: 'ws/NfeStatusServico/NfeStatusServico4.asmx?wsdl',
WS_NFE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento4.asmx?wsdl',
WS_NFE_AUTORIZACAO: 'ws/NfeAutorizacao/NFeAutorizacao4.asmx?wsdl',
WS_NFE_RET_AUTORIZACAO: 'ws/NfeRetAutorizacao/NFeRetAutorizacao4.asmx?wsdl', # noqa
WS_NFCE_QR_CODE: 'http://dec.fazenda.df.gov.br/ConsultarNFCe.aspx',
},
AMBIENTE_HOMOLOGACAO: {
'servidor': 'nfce-homologacao.svrs.rs.gov.br',
WS_NFE_INUTILIZACAO: 'ws/nfeinutilizacao/nfeinutilizacao4.asmx?wsdl',
WS_NFE_CONSULTA: 'ws/NfeConsulta/NfeConsulta4.asmx?wsdl',
WS_NFE_SITUACAO: 'ws/NfeStatusServico/NfeStatusServico4.asmx?wsdl',
WS_NFE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento4.asmx?wsdl',
WS_NFE_AUTORIZACAO: 'ws/NfeAutorizacao/NFeAutorizacao4.asmx?wsdl',
WS_NFE_RET_AUTORIZACAO: 'ws/NfeRetAutorizacao/NFeRetAutorizacao4.asmx?wsdl', # noqa
WS_NFCE_QR_CODE: 'http://dec.fazenda.df.gov.br/ConsultarNFCe.aspx',
}
}
}
# TODO Daqui pra frente tem que revisar
SVAN = {
NFE_AMBIENTE_PRODUCAO: {
AMBIENTE_PRODUCAO: {
'servidor': 'www.sefazvirtual.fazenda.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'RecepcaoEvento/RecepcaoEvento.asmx',
WS_NFE_AUTORIZACAO: 'NfeAutorizacao/NfeAutorizacao.asmx',
@ -171,7 +178,7 @@ SVAN = {
WS_NFE_CONSULTA: 'NfeConsulta2/NfeConsulta2.asmx',
WS_NFE_SITUACAO: 'NfeStatusServico2/NfeStatusServico2.asmx',
},
NFE_AMBIENTE_HOMOLOGACAO: {
AMBIENTE_HOMOLOGACAO: {
'servidor': 'hom.sefazvirtual.fazenda.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'RecepcaoEvento/RecepcaoEvento.asmx',
WS_NFE_AUTORIZACAO: 'NfeAutorizacao/NfeAutorizacao.asmx',
@ -183,7 +190,7 @@ SVAN = {
}
SCAN = {
NFE_AMBIENTE_PRODUCAO: {
AMBIENTE_PRODUCAO: {
'servidor': 'www.scan.fazenda.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'RecepcaoEvento/RecepcaoEvento.asmx',
WS_NFE_AUTORIZACAO: 'NfeAutorizacao/NfeAutorizacao.asmx',
@ -192,7 +199,7 @@ SCAN = {
WS_NFE_CONSULTA: 'NfeConsulta2/NfeConsulta2.asmx',
WS_NFE_SITUACAO: 'NfeStatusServico2/NfeStatusServico2.asmx'
},
NFE_AMBIENTE_HOMOLOGACAO: {
AMBIENTE_HOMOLOGACAO: {
'servidor': 'hom.nfe.fazenda.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'RecepcaoEvento/RecepcaoEvento.asmx',
WS_NFE_AUTORIZACAO: 'NfeAutorizacao/NfeAutorizacao.asmx',
@ -204,7 +211,7 @@ SCAN = {
}
SVC_AN = {
NFE_AMBIENTE_PRODUCAO: {
AMBIENTE_PRODUCAO: {
'servidor': 'www.svc.fazenda.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'RecepcaoEvento/RecepcaoEvento.asmx',
WS_NFE_AUTORIZACAO: 'NfeAutorizacao/NfeAutorizacao.asmx',
@ -212,7 +219,7 @@ SVC_AN = {
WS_NFE_CONSULTA: 'NfeConsulta2/NfeConsulta2.asmx',
WS_NFE_SITUACAO: 'NfeStatusServico2/NfeStatusServico2.asmx'
},
NFE_AMBIENTE_HOMOLOGACAO: {
AMBIENTE_HOMOLOGACAO: {
'servidor': 'hom.nfe.fazenda.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'RecepcaoEvento/RecepcaoEvento.asmx',
WS_NFE_AUTORIZACAO: 'NfeAutorizacao/NfeAutorizacao.asmx',
@ -223,7 +230,7 @@ SVC_AN = {
}
SVC_RS = {
NFE_AMBIENTE_PRODUCAO: {
AMBIENTE_PRODUCAO: {
'servidor': 'nfe.sefazvirtual.rs.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFE_AUTORIZACAO: 'ws/NfeAutorizacao/NfeAutorizacao.asmx',
@ -231,7 +238,7 @@ SVC_RS = {
WS_NFE_CONSULTA: 'ws/NfeConsulta/NfeConsulta2.asmx',
WS_NFE_SITUACAO: 'ws/NfeStatusServico/NfeStatusServico2.asmx',
},
NFE_AMBIENTE_HOMOLOGACAO: {
AMBIENTE_HOMOLOGACAO: {
'servidor': 'homologacao.nfe.sefazvirtual.rs.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFE_AUTORIZACAO: 'ws/NfeAutorizacao/NfeAutorizacao.asmx',
@ -241,42 +248,26 @@ SVC_RS = {
}
}
DPEC = {
NFE_AMBIENTE_PRODUCAO: {
'servidor': 'www.nfe.fazenda.gov.br',
WS_DPEC_CONSULTA: 'SCERecepcaoRFB/SCERecepcaoRFB.asmx',
WS_DPEC_RECEPCAO: 'SCEConsultaRFB/SCEConsultaRFB.asmx'
},
NFE_AMBIENTE_HOMOLOGACAO: {
'servidor': 'hom.nfe.fazenda.gov.br',
WS_DPEC_CONSULTA: 'SCERecepcaoRFB/SCERecepcaoRFB.asmx',
WS_DPEC_RECEPCAO: 'SCEConsultaRFB/SCEConsultaRFB.asmx'
}
}
AN = {
NFE_AMBIENTE_PRODUCAO: {
AMBIENTE_PRODUCAO: {
'servidor': 'www1.nfe.fazenda.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'RecepcaoEvento/RecepcaoEvento.asmx',
WS_DFE_DISTRIBUICAO: 'NFeDistribuicaoDFe/NFeDistribuicaoDFe.asmx',
WS_DOWNLOAD_NFE: 'NFeDistribuicaoDFe/NFeDistribuicaoDFe.asmx',
WS_NFE_RECEPCAO_EVENTO_MANIFESTO: 'RecepcaoEvento/RecepcaoEvento.asmx',
WS_DFE_DISTRIBUICAO: 'NFeDistribuicaoDFe/NFeDistribuicaoDFe.asmx?wsdl',
WS_DOWNLOAD_NFE: 'NFeDistribuicaoDFe/NFeDistribuicaoDFe.asmx?wsdl',
WS_NFE_RECEPCAO_EVENTO: 'NFeRecepcaoEvento4/NFeRecepcaoEvento4.asmx?wsdl',
},
NFE_AMBIENTE_HOMOLOGACAO: {
AMBIENTE_HOMOLOGACAO: {
'servidor': 'hom.nfe.fazenda.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'RecepcaoEvento/RecepcaoEvento.asmx',
WS_DFE_DISTRIBUICAO: 'NFeDistribuicaoDFe/NFeDistribuicaoDFe.asmx',
WS_DOWNLOAD_NFE: 'NFeDistribuicaoDFe/NFeDistribuicaoDFe.asmx',
WS_NFE_RECEPCAO_EVENTO_MANIFESTO: 'RecepcaoEvento/RecepcaoEvento.asmx',
WS_DFE_DISTRIBUICAO: 'NFeDistribuicaoDFe/NFeDistribuicaoDFe.asmx?wsdl',
WS_DOWNLOAD_NFE: 'NFeDistribuicaoDFe/NFeDistribuicaoDFe.asmx?wsdl',
WS_NFE_RECEPCAO_EVENTO: 'NFeRecepcaoEvento4/NFeRecepcaoEvento4.asmx?Wsdl',
},
}
UFAM = {
NFE_MODELO: {
NFE_AMBIENTE_PRODUCAO: {
AMBIENTE_PRODUCAO: {
'servidor': 'nfe.sefaz.am.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'services2/services/RecepcaoEvento',
WS_NFE_CANCELAMENTO: 'services2/services/RecepcaoEvento',
WS_NFE_AUTORIZACAO: 'services2/services/NfeAutorizacao',
WS_NFE_RET_AUTORIZACAO: 'services2/services/NfeRetAutorizacao',
WS_NFE_INUTILIZACAO: 'services2/services/NfeInutilizacao2',
@ -284,10 +275,9 @@ UFAM = {
WS_NFE_SITUACAO: 'services2/services/NfeStatusServico2',
WS_NFE_CADASTRO: 'services2/services/cadconsultacadastro2',
},
NFE_AMBIENTE_HOMOLOGACAO: {
AMBIENTE_HOMOLOGACAO: {
'servidor': 'homnfe.sefaz.am.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'services2/services/RecepcaoEvento',
WS_NFE_CANCELAMENTO: 'services2/services/RecepcaoEvento',
WS_NFE_AUTORIZACAO: 'services2/services/NfeAutorizacao',
WS_NFE_RET_AUTORIZACAO: 'services2/services/NfeRetAutorizacao',
WS_NFE_INUTILIZACAO: 'services2/services/NfeInutilizacao2',
@ -297,10 +287,9 @@ UFAM = {
}
},
NFCE_MODELO: {
NFE_AMBIENTE_PRODUCAO: {
AMBIENTE_PRODUCAO: {
'servidor': 'nfe.sefaz.am.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'services2/services/RecepcaoEvento',
WS_NFE_CANCELAMENTO: 'services2/services/RecepcaoEvento',
WS_NFE_AUTORIZACAO: 'services2/services/NfeAutorizacao',
WS_NFE_RET_AUTORIZACAO: 'services2/services/NfeRetAutorizacao',
WS_NFE_INUTILIZACAO: 'services2/services/NfeInutilizacao2',
@ -308,101 +297,92 @@ UFAM = {
WS_NFE_SITUACAO: 'services2/services/NfeStatusServico2',
WS_NFE_CADASTRO: 'services2/services/cadconsultacadastro2',
},
NFE_AMBIENTE_HOMOLOGACAO: {
AMBIENTE_HOMOLOGACAO: {
'servidor': 'homnfce.sefaz.am.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'nfce-services-nac/services/RecepcaoEvento',
WS_NFE_CANCELAMENTO: 'nfce-services-nac/services/RecepcaoEvento',
WS_NFE_AUTORIZACAO: 'nfce-services-nac/services/NfeAutorizacao',
WS_NFE_RET_AUTORIZACAO: 'nfce-services-nac/services/NfeRetAutorizacao',
WS_NFE_INUTILIZACAO: 'nfce-services-nac/services/NfeInutilizacao2',
WS_NFE_CONSULTA: 'nfce-services-nac/services/NfeConsulta2',
WS_NFE_SITUACAO: 'nfce-services-nac/services/NfeStatusServico2',
WS_NFCE_QR_CODE: 'nfceweb/consultarNFCe.jsp',
WS_NFCE_QR_CODE: 'http://homnfce.sefaz.am.gov.br/nfceweb/consultarNFCe.jsp',
}
}
}
UFBA = {
NFE_AMBIENTE_PRODUCAO: {
AMBIENTE_PRODUCAO: {
'servidor': 'nfe.sefaz.ba.gov.br',
WS_NFE_AUTORIZACAO: 'webservices/NfeAutorizacao/NfeAutorizacao.asmx',
WS_NFE_RET_AUTORIZACAO:
'webservices/NfeRetAutorizacao/NfeRetAutorizacao.asmx',
WS_NFE_CONSULTA: 'webservices/NfeConsulta/NfeConsulta.asmx',
WS_NFE_SITUACAO: 'webservices/NfeStatusServico/NfeStatusServico.asmx',
WS_NFE_INUTILIZACAO: 'webservices/nfenw/nfeinutilizacao2.asmx',
WS_NFE_CADASTRO: 'webservices/nfenw/CadConsultaCadastro2.asmx',
WS_NFE_RECEPCAO_EVENTO: 'webservices/sre/recepcaoevento.asmx',
WS_NFE_CANCELAMENTO: 'webservices/sre/recepcaoevento.asmx',
},
NFE_AMBIENTE_HOMOLOGACAO: {
WS_NFE_INUTILIZACAO: 'webservices/NFeInutilizacao4/NFeInutilizacao4.asmx?wsdl',
WS_NFE_CONSULTA: 'webservices/NFeConsultaProtocolo4/NFeConsultaProtocolo4.asmx?wsdl',
WS_NFE_SITUACAO: 'webservices/NFeStatusServico4/NFeStatusServico4.asmx?wsdl',
WS_NFE_RECEPCAO_EVENTO: 'webservices/NFeRecepcaoEvento4/NFeRecepcaoEvento4.asmx?wsdl',
WS_NFE_AUTORIZACAO: 'webservices/NFeAutorizacao4/NFeAutorizacao4.asmx?wsdl',
WS_NFE_RET_AUTORIZACAO: 'webservices/NFeRetAutorizacao4/NFeRetAutorizacao4.asmx?wsdl',
WS_NFE_CADASTRO: 'webservices/CadConsultaCadastro4/CadConsultaCadastro4.asmx?wsdl',
},
AMBIENTE_HOMOLOGACAO: {
'servidor': 'hnfe.sefaz.ba.gov.br',
WS_NFE_AUTORIZACAO: 'webservices/NfeAutorizacao/NfeAutorizacao.asmx',
WS_NFE_RET_AUTORIZACAO:
'webservices/NfeRetAutorizacao/NfeRetAutorizacao.asmx',
WS_NFE_CONSULTA: 'webservices/NfeConsulta/NfeConsulta.asmx',
WS_NFE_SITUACAO: 'webservices/NfeStatusServico/NfeStatusServico.asmx',
WS_NFE_INUTILIZACAO: 'webservices/nfenw/nfeinutilizacao2.asmx',
WS_NFE_CADASTRO: 'webservices/nfenw/CadConsultaCadastro2.asmx',
WS_NFE_RECEPCAO_EVENTO: 'webservices/sre/recepcaoevento.asmx',
WS_NFE_CANCELAMENTO: 'webservices/sre/recepcaoevento.asmx',
WS_NFE_INUTILIZACAO: 'webservices/NFeInutilizacao4/NFeInutilizacao4.asmx?wsdl',
WS_NFE_CONSULTA: 'webservices/NFeConsultaProtocolo4/NFeConsultaProtocolo4.asmx?wsdl',
WS_NFE_SITUACAO: 'webservices/NFeStatusServico4/NFeStatusServico4.asmx?wsdl',
WS_NFE_RECEPCAO_EVENTO: 'webservices/NFeRecepcaoEvento4/NFeRecepcaoEvento4.asmx?wsdl',
WS_NFE_AUTORIZACAO: 'webservices/NFeAutorizacao4/NFeAutorizacao4.asmx?wsdl',
WS_NFE_RET_AUTORIZACAO: 'webservices/NFeRetAutorizacao4/NFeRetAutorizacao4.asmx?wsdl',
WS_NFE_CADASTRO: 'webservices/CadConsultaCadastro4/CadConsultaCadastro4.asmx?wsdl',
}
}
UFCE = {
NFE_AMBIENTE_PRODUCAO: {
AMBIENTE_PRODUCAO: {
'servidor': 'nfe.sefaz.ce.gov.br',
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',
WS_NFE_CADASTRO: 'nfe2/services/CadConsultaCadastro2',
WS_NFE_RECEPCAO_EVENTO: 'nfe2/services/RecepcaoEvento',
WS_NFE_CANCELAMENTO: 'nfe2/services/RecepcaoEvento',
},
NFE_AMBIENTE_HOMOLOGACAO: {
WS_NFE_AUTORIZACAO: 'nfe4/services/NFeAutorizacao4?WSDL',
WS_NFE_RET_AUTORIZACAO: 'nfe4/services/NFeRetAutorizacao4?WSDL',
WS_NFE_INUTILIZACAO: 'nfe4/services/NFeInutilizacao4?WSDL',
WS_NFE_CONSULTA: 'nfe4/services/NFeConsultaProtocolo4?WSDL',
WS_NFE_SITUACAO: 'nfe4/services/NFeStatusServico4?WSDL',
WS_NFE_CADASTRO: 'nfe4/services/CadConsultaCadastro4?WSDL',
WS_NFE_RECEPCAO_EVENTO: 'nfe4/services/NFeRecepcaoEvento4?WSDL',
},
AMBIENTE_HOMOLOGACAO: {
'servidor': 'nfeh.sefaz.ce.gov.br',
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',
WS_NFE_CADASTRO: 'nfe2/services/CadConsultaCadastro2',
WS_NFE_RECEPCAO_EVENTO: 'nfe2/services/RecepcaoEvento',
WS_NFE_CANCELAMENTO: 'nfe2/services/RecepcaoEvento',
WS_NFE_AUTORIZACAO: 'nfe4/services/NFeAutorizacao4?WSDL',
WS_NFE_RET_AUTORIZACAO: 'nfe4/services/NFeRetAutorizacao4?WSDL',
WS_NFE_INUTILIZACAO: 'nfe4/services/NFeInutilizacao4?WSDL',
WS_NFE_CONSULTA: 'nfe4/services/NFeConsultaProtocolo4?WSDL',
WS_NFE_SITUACAO: 'nfe4/services/NFeStatusServico4?WSDL',
WS_NFE_CADASTRO: 'nfe4/services/CadConsultaCadastro4?WSDL',
WS_NFE_RECEPCAO_EVENTO: 'nfe4/services/NFeRecepcaoEvento4?WSDL',
}
}
UFGO = {
NFE_AMBIENTE_PRODUCAO: {
AMBIENTE_PRODUCAO: {
'servidor': 'nfe.sefaz.go.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'nfe/services/v2/RecepcaoEvento',
WS_NFE_AUTORIZACAO: 'nfe/services/v2/NfeAutorizacao',
WS_NFE_RET_AUTORIZACAO: 'nfe/services/v2/NfeRetAutorizacao',
WS_NFE_INUTILIZACAO: 'nfe/services/v2/NfeInutilizacao2',
WS_NFE_CONSULTA: 'nfe/services/v2/NfeConsulta2',
WS_NFE_SITUACAO: 'nfe/services/v2/NfeStatusServico2',
WS_NFE_CADASTRO: 'nfe/services/v2/CadConsultaCadastro2',
WS_NFE_CANCELAMENTO: 'nfe/services/v2/RecepcaoEvento',
},
NFE_AMBIENTE_HOMOLOGACAO: {
WS_NFE_INUTILIZACAO: 'nfe/services/NFeInutilizacao4?wsdl',
WS_NFE_CONSULTA: 'nfe/services/NFeConsultaProtocolo4?wsdl',
WS_NFE_SITUACAO: 'nfe/services/NFeStatusServico4?wsdl',
WS_NFE_RECEPCAO_EVENTO: 'nfe/services/NFeRecepcaoEvento4?wsdl',
WS_NFE_AUTORIZACAO: 'nfe/services/NFeAutorizacao4?wsdl',
WS_NFE_RET_AUTORIZACAO: 'nfe/services/NFeRetAutorizacao4?wsdl',
WS_NFE_CADASTRO: 'nfe/services/CadConsultaCadastro4?wsdl',
},
AMBIENTE_HOMOLOGACAO: {
'servidor': 'homolog.sefaz.go.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'nfe/services/v2/RecepcaoEvento',
WS_NFE_AUTORIZACAO: 'nfe/services/v2/NfeAutorizacao',
WS_NFE_RET_AUTORIZACAO: 'nfe/services/v2/NfeRetAutorizacao',
WS_NFE_INUTILIZACAO: 'nfe/services/v2/NfeInutilizacao2',
WS_NFE_CONSULTA: 'nfe/services/v2/NfeConsulta2',
WS_NFE_SITUACAO: 'nfe/services/v2/NfeStatusServico2',
WS_NFE_CADASTRO: 'nfe/services/v2/CadConsultaCadastro2',
WS_NFE_CANCELAMENTO: 'nfe/services/v2/RecepcaoEvento',
WS_NFE_INUTILIZACAO: 'nfe/services/NFeInutilizacao4?wsdl',
WS_NFE_CONSULTA: 'nfe/services/NFeConsultaProtocolo4?wsdl',
WS_NFE_SITUACAO: 'nfe/services/NFeStatusServico4?wsdl',
WS_NFE_RECEPCAO_EVENTO: 'nfe/services/NFeRecepcaoEvento4?wsdl',
WS_NFE_AUTORIZACAO: 'nfe/services/NFeAutorizacao4?wsdl',
WS_NFE_RET_AUTORIZACAO: 'nfe/services/NFeRetAutorizacao4?wsdl',
WS_NFE_CADASTRO: 'nfe/services/CadConsultaCadastro4?wsdl',
}
}
UFMT = {
NFE_AMBIENTE_PRODUCAO: {
AMBIENTE_PRODUCAO: {
'servidor': 'nfe.sefaz.mt.gov.br',
WS_NFE_AUTORIZACAO: 'nfews/v2/services/NfeAutorizacao',
WS_NFE_RET_AUTORIZACAO: 'nfews/v2/services/NfeRetAutorizacao',
@ -411,9 +391,8 @@ UFMT = {
WS_NFE_SITUACAO: 'nfews/v2/services/NfeStatusServico2',
WS_NFE_CADASTRO: 'nfews/v2/services/CadConsultaCadastro2',
WS_NFE_RECEPCAO_EVENTO: 'nfews/v2/services/RecepcaoEvento',
WS_NFE_CANCELAMENTO: 'nfews/v2/services/RecepcaoEvento',
},
NFE_AMBIENTE_HOMOLOGACAO: {
AMBIENTE_HOMOLOGACAO: {
'servidor': 'homologacao.sefaz.mt.gov.br',
WS_NFE_AUTORIZACAO: 'nfews/v2/services/NfeAutorizacao',
WS_NFE_RET_AUTORIZACAO: 'nfews/v2/services/NfeRetAutorizacao',
@ -422,12 +401,11 @@ UFMT = {
WS_NFE_SITUACAO: 'nfews/v2/services/NfeStatusServico2',
WS_NFE_CADASTRO: 'nfews/v2/services/CadConsultaCadastro2',
WS_NFE_RECEPCAO_EVENTO: 'nfews/v2/services/RecepcaoEvento',
WS_NFE_CANCELAMENTO: 'nfews/v2/services/RecepcaoEvento',
}
}
UFMS = {
NFE_AMBIENTE_PRODUCAO: {
AMBIENTE_PRODUCAO: {
'servidor': 'nfe.fazenda.ms.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'producao/services2/RecepcaoEvento',
WS_NFE_AUTORIZACAO: 'producao/services2/NfeAutorizacao',
@ -436,9 +414,8 @@ UFMS = {
WS_NFE_INUTILIZACAO: 'producao/services2/NfeInutilizacao2',
WS_NFE_CONSULTA: 'producao/services2/NfeConsulta2',
WS_NFE_SITUACAO: 'producao/services2/NfeStatusServico2',
WS_NFE_CANCELAMENTO: 'producao/services2/RecepcaoEvento',
},
NFE_AMBIENTE_HOMOLOGACAO: {
AMBIENTE_HOMOLOGACAO: {
'servidor': 'homologacao.nfe.ms.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'homologacao/services2/RecepcaoEvento',
WS_NFE_AUTORIZACAO: 'homologacao/services2/NfeAutorizacao',
@ -447,37 +424,35 @@ UFMS = {
WS_NFE_INUTILIZACAO: 'homologacao/services2/NfeInutilizacao2',
WS_NFE_CONSULTA: 'homologacao/services2/NfeConsulta2',
WS_NFE_SITUACAO: 'homologacao/services2/NfeStatusServico2',
WS_NFE_CANCELAMENTO: 'homologacao/services2/RecepcaoEvento',
}
}
UFMG = {
NFE_AMBIENTE_PRODUCAO: {
AMBIENTE_PRODUCAO: {
'servidor': 'nfe.fazenda.mg.gov.br',
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/NfeStatus2',
WS_NFE_CADASTRO: 'nfe2/services/cadconsultacadastro2',
WS_NFE_RECEPCAO_EVENTO: 'nfe2/services/RecepcaoEvento',
WS_NFE_CANCELAMENTO: 'nfe2/services/RecepcaoEvento',
},
NFE_AMBIENTE_HOMOLOGACAO: {
WS_NFE_INUTILIZACAO: 'nfe2/services/NFeInutilizacao4?wsdl',
WS_NFE_CONSULTA: 'nfe2/services/NFeConsultaProtocolo4?wsdl',
WS_NFE_SITUACAO: 'nfe2/services/NFeStatusServico4?wsdl',
WS_NFE_RECEPCAO_EVENTO: 'nfe2/services/NFeRecepcaoEvento4?wsdl',
WS_NFE_AUTORIZACAO: 'nfe2/services/NFeAutorizacao4?wsdl',
WS_NFE_RET_AUTORIZACAO: 'nfe2/services/NFeRetAutorizacao4?wsdl',
WS_NFE_CADASTRO: 'nfe2/services/cadconsultacadastro2?wsdl',
},
AMBIENTE_HOMOLOGACAO: {
'servidor': 'hnfe.fazenda.mg.gov.br',
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/NfeStatus2',
WS_NFE_CADASTRO: 'nfe2/services/cadconsultacadastro2',
WS_NFE_RECEPCAO_EVENTO: 'nfe2/services/RecepcaoEvento',
WS_NFE_CANCELAMENTO: 'nfe2/services/RecepcaoEvento',
WS_NFE_INUTILIZACAO: 'nfe2/services/NFeInutilizacao4?wsdl',
WS_NFE_CONSULTA: 'nfe2/services/NFeConsultaProtocolo4?wsdl',
WS_NFE_SITUACAO: 'nfe2/services/NFeStatusServico4?wsdl',
WS_NFE_RECEPCAO_EVENTO: 'nfe2/services/NFeRecepcaoEvento4?wsdl',
WS_NFE_AUTORIZACAO: 'nfe2/services/NFeAutorizacao4?wsdl',
WS_NFE_RET_AUTORIZACAO: 'nfe2/services/NFeRetAutorizacao4?wsdl',
WS_NFE_CADASTRO: 'nfe2/services/cadconsultacadastro2?wsdl',
}
}
UFPR = {
NFE_AMBIENTE_PRODUCAO: {
AMBIENTE_PRODUCAO: {
'servidor': 'nfe.fazenda.pr.gov.br',
WS_NFE_AUTORIZACAO: 'nfe/NFeAutorizacao3',
WS_NFE_RET_AUTORIZACAO: 'nfe/NFeRetAutorizacao3',
@ -485,10 +460,9 @@ UFPR = {
WS_NFE_CONSULTA: 'nfe/NFeConsulta3',
WS_NFE_SITUACAO: 'nfe/NFeStatusServico3',
WS_NFE_CADASTRO: 'nfe/CadConsultaCadastro2',
WS_NFE_RECEPCAO_EVENTO: 'nfe-evento/NFeRecepcaoEvento',
WS_NFE_CANCELAMENTO: 'nfe-evento/NFeRecepcaoEvento',
WS_NFE_RECEPCAO_EVENTO: 'nfe/NFeRecepcaoEvento',
},
NFE_AMBIENTE_HOMOLOGACAO: {
AMBIENTE_HOMOLOGACAO: {
'servidor': 'homologacao.nfe.fazenda.pr.gov.br',
WS_NFE_AUTORIZACAO: 'nfe/NFeAutorizacao3',
WS_NFE_RET_AUTORIZACAO: 'nfe/NFeRetAutorizacao3',
@ -496,16 +470,14 @@ UFPR = {
WS_NFE_CONSULTA: 'nfe/NFeConsulta3',
WS_NFE_SITUACAO: 'nfe/NFeStatusServico3',
WS_NFE_CADASTRO: 'nfe/CadConsultaCadastro2',
WS_NFE_RECEPCAO_EVENTO: 'nfe-evento/NFeRecepcaoEvento',
WS_NFE_CANCELAMENTO: 'nfe-evento/NFeRecepcaoEvento',
WS_NFE_RECEPCAO_EVENTO: 'nfe/NFeRecepcaoEvento',
}
}
UFPE = {
NFE_AMBIENTE_PRODUCAO: {
AMBIENTE_PRODUCAO: {
'servidor': 'nfe.sefaz.pe.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'nfe-service/services/RecepcaoEvento',
WS_NFE_CANCELAMENTO: 'nfe-service/services/RecepcaoEvento',
WS_NFE_AUTORIZACAO: 'nfe-service/services/NfeAutorizacao',
WS_NFE_RET_AUTORIZACAO: 'nfe-service/services/NfeRetAutorizacao',
WS_NFE_INUTILIZACAO: 'nfe-service/services/NfeInutilizacao2',
@ -513,10 +485,9 @@ UFPE = {
WS_NFE_SITUACAO: 'nfe-service/services/NfeStatusServico2',
WS_NFE_CADASTRO: 'nfe-service/services/CadConsultaCadastro2',
},
NFE_AMBIENTE_HOMOLOGACAO: {
AMBIENTE_HOMOLOGACAO: {
'servidor': 'nfehomolog.sefaz.pe.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'nfe-service/services/RecepcaoEvento',
WS_NFE_CANCELAMENTO: 'nfe-service/services/RecepcaoEvento',
WS_NFE_AUTORIZACAO: 'nfe-service/services/NfeAutorizacao',
WS_NFE_RET_AUTORIZACAO: 'nfe-service/services/NfeRetAutorizacao',
WS_NFE_INUTILIZACAO: 'nfe-service/services/NfeInutilizacao2',
@ -529,7 +500,7 @@ UFPE = {
UFRS = {
NFE_MODELO: {
NFE_AMBIENTE_PRODUCAO: {
AMBIENTE_PRODUCAO: {
'servidor': 'nfe.sefazrs.rs.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFE_AUTORIZACAO: 'ws/NfeAutorizacao/NFeAutorizacao.asmx',
@ -538,9 +509,8 @@ 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: {
AMBIENTE_HOMOLOGACAO: {
'servidor': 'nfe-homologacao.sefazrs.rs.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFE_AUTORIZACAO: 'ws/NfeAutorizacao/NFeAutorizacao.asmx',
@ -549,32 +519,29 @@ 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',
}
},
NFCE_MODELO: {
NFE_AMBIENTE_PRODUCAO: {
AMBIENTE_PRODUCAO: {
'servidor': 'nfce.sefazrs.rs.gov.br',
WS_NFCE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFCE_AUTORIZACAO: 'ws/NfeAutorizacao/NFeAutorizacao.asmx',
WS_NFCE_RET_AUTORIZACAO: 'ws/NfeRetAutorizacao/NFeRetAutorizacao.asmx',
WS_NFCE_CADASTRO: 'ws/cadconsultacadastro/cadconsultacadastro2.asmx',
WS_NFCE_INUTILIZACAO: 'ws/NfeInutilizacao/NfeInutilizacao2.asmx',
WS_NFCE_CONSULTA: 'ws/NfeConsulta/NfeConsulta2.asmx',
WS_NFCE_SITUACAO: 'ws/NfeStatusServico/NfeStatusServico2.asmx',
WS_NFCE_CANCELAMENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFE_RECEPCAO_EVENTO: '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',
WS_NFE_INUTILIZACAO: 'ws/NfeInutilizacao/NfeInutilizacao2.asmx',
WS_NFE_CONSULTA: 'ws/NfeConsulta/NfeConsulta2.asmx',
WS_NFE_SITUACAO: 'ws/NfeStatusServico/NfeStatusServico2.asmx',
WS_NFCE_QR_CODE: 'https://www.sefaz.rs.gov.br/NFCE/NFCE-COM.aspx',
},
NFE_AMBIENTE_HOMOLOGACAO: {
AMBIENTE_HOMOLOGACAO: {
'servidor': 'nfce-homologacao.sefazrs.rs.gov.br',
WS_NFCE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFCE_AUTORIZACAO: 'ws/NfeAutorizacao/NFeAutorizacao.asmx',
WS_NFCE_RET_AUTORIZACAO: 'ws/NfeRetAutorizacao/NFeRetAutorizacao.asmx',
WS_NFCE_CADASTRO: 'ws/cadconsultacadastro/cadconsultacadastro2.asmx',
WS_NFCE_INUTILIZACAO: 'ws/NfeInutilizacao/NfeInutilizacao2.asmx',
WS_NFCE_CONSULTA: 'ws/NfeConsulta/NfeConsulta2.asmx',
WS_NFCE_SITUACAO: 'ws/NfeStatusServico/NfeStatusServico2.asmx',
WS_NFCE_CANCELAMENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFE_RECEPCAO_EVENTO: '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',
WS_NFE_INUTILIZACAO: 'ws/NfeInutilizacao/NfeInutilizacao2.asmx',
WS_NFE_CONSULTA: 'ws/NfeConsulta/NfeConsulta2.asmx',
WS_NFE_SITUACAO: 'ws/NfeStatusServico/NfeStatusServico2.asmx',
WS_NFCE_QR_CODE: 'https://www.sefaz.rs.gov.br/NFCE/NFCE-COM.aspx'
}
}
@ -582,8 +549,30 @@ UFRS = {
UFSP = {
NFE_MODELO: {
NFE_AMBIENTE_PRODUCAO: {
AMBIENTE_PRODUCAO: {
'servidor': 'nfe.fazenda.sp.gov.br',
WS_NFE_INUTILIZACAO: 'ws/nfeinutilizacao4.asmx?wsdl',
WS_NFE_CONSULTA: 'ws/nfeconsultaprotocolo4.asmx?wsdl',
WS_NFE_SITUACAO: 'ws/nfestatusservico4.asmx?wsdl',
WS_NFE_RECEPCAO_EVENTO: 'ws/nferecepcaoevento4.asmx?wsdl',
WS_NFE_AUTORIZACAO: 'ws/nfeautorizacao4.asmx?wsdl',
WS_NFE_RET_AUTORIZACAO: 'ws/nferetautorizacao4.asmx?wsdl',
WS_NFE_CADASTRO: 'ws/cadconsultacadastro4.asmx?wsdl',
},
AMBIENTE_HOMOLOGACAO: {
'servidor': 'homologacao.nfe.fazenda.sp.gov.br',
WS_NFE_INUTILIZACAO: 'ws/nfeinutilizacao4.asmx?wsdl',
WS_NFE_CONSULTA: 'ws/nfeconsultaprotocolo4.asmx?wsdl',
WS_NFE_SITUACAO: 'ws/nfestatusservico4.asmx?wsdl',
WS_NFE_RECEPCAO_EVENTO: 'ws/nferecepcaoevento4.asmx?wsdl',
WS_NFE_AUTORIZACAO: 'ws/nfeautorizacao4.asmx?wsdl',
WS_NFE_RET_AUTORIZACAO: 'ws/nferetautorizacao4.asmx?wsdl',
WS_NFE_CADASTRO: 'ws/cadconsultacadastro4.asmx?wsdl',
}
},
NFCE_MODELO: {
AMBIENTE_PRODUCAO: {
'servidor': 'nfce.fazenda.sp.gov.br',
WS_NFE_AUTORIZACAO: 'ws/nfeautorizacao.asmx',
WS_NFE_RET_AUTORIZACAO: 'ws/nferetautorizacao.asmx',
WS_NFE_INUTILIZACAO: 'ws/nfeinutilizacao2.asmx',
@ -591,10 +580,10 @@ UFSP = {
WS_NFE_SITUACAO: 'ws/nfestatusservico2.asmx',
WS_NFE_CADASTRO: 'ws/cadconsultacadastro2.asmx',
WS_NFE_RECEPCAO_EVENTO: 'ws/recepcaoevento.asmx',
WS_NFE_CANCELAMENTO: 'ws/recepcaoevento.asmx',
WS_NFCE_QR_CODE: '',
},
NFE_AMBIENTE_HOMOLOGACAO: {
'servidor': 'homologacao.nfe.fazenda.sp.gov.br',
AMBIENTE_HOMOLOGACAO: {
'servidor': 'homologacao.nfce.fazenda.sp.gov.br',
WS_NFE_AUTORIZACAO: 'ws/nfeautorizacao.asmx',
WS_NFE_RET_AUTORIZACAO: 'ws/nferetautorizacao.asmx',
WS_NFE_INUTILIZACAO: 'ws/nfeinutilizacao2.asmx',
@ -602,31 +591,7 @@ UFSP = {
WS_NFE_SITUACAO: 'ws/nfestatusservico2.asmx',
WS_NFE_CADASTRO: 'ws/cadconsultacadastro2.asmx',
WS_NFE_RECEPCAO_EVENTO: 'ws/recepcaoevento.asmx',
WS_NFE_CANCELAMENTO: 'ws/recepcaoevento.asmx',
}
},
NFCE_MODELO: {
NFCE_AMBIENTE_PRODUCAO: {
'servidor': 'nfce.fazenda.sp.gov.br',
WS_NFCE_AUTORIZACAO: 'ws/nfeautorizacao.asmx',
WS_NFCE_RET_AUTORIZACAO: 'ws/nferetautorizacao.asmx',
WS_NFCE_INUTILIZACAO: 'ws/nfeinutilizacao2.asmx',
WS_NFCE_CONSULTA: 'ws/nfeconsulta2.asmx',
WS_NFCE_SITUACAO: 'ws/nfestatusservico2.asmx',
WS_NFCE_CADASTRO: 'ws/cadconsultacadastro2.asmx',
WS_NFCE_RECEPCAO_EVENTO: 'ws/recepcaoevento.asmx',
WS_NFCE_QR_CODE: '',
},
NFCE_AMBIENTE_HOMOLOGACAO: {
'servidor': 'homologacao.nfce.fazenda.sp.gov.br',
WS_NFCE_AUTORIZACAO: 'ws/nfeautorizacao.asmx',
WS_NFCE_RET_AUTORIZACAO: 'ws/nferetautorizacao.asmx',
WS_NFCE_INUTILIZACAO: 'ws/nfeinutilizacao2.asmx',
WS_NFCE_CONSULTA: 'ws/nfeconsulta2.asmx',
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: 'https://homologacao.nfce.fazenda.sp.gov.br/NFCEConsultaPublica/Paginas/ConstultaQRCode.aspx',
}
}
}
@ -660,47 +625,5 @@ ESTADO_WS = {
'SE': SVRS,
'SP': UFSP,
'TO': SVRS,
}
#
# Informação obtida em
# http://www.nfe.fazenda.gov.br/portal/webServices.aspx
# Última verificação: 15/08/2014 16:22
#
# Autorizadores em contingência:
# - UF que utilizam a SVC-AN - Sefaz Virtual de Contingência Ambiente Nacional:
# AC, AL, AP, DF, ES, MG, PB, RJ, RN, RO, RR, RS, SC, SE, SP, TO
# - UF que utilizam a SVC-RS - Sefaz Virtual de Contingência Rio Grande do Sul:
# AM, BA, CE, GO, MA, MS, MT, PA, PE, PI, PR
#
ESTADO_WS_CONTINGENCIA = {
'AC': SVC_AN,
'AL': SVC_AN,
'AM': SVC_RS,
'AP': SVC_AN,
'BA': SVC_RS,
'CE': SVC_RS,
'DF': SVC_AN,
'ES': SVC_AN,
'GO': SVC_RS,
'MA': SVC_RS,
'MG': SVC_AN,
'MS': SVC_RS,
'MT': SVC_RS,
'PA': SVC_RS,
'PB': SVC_AN,
'PE': SVC_RS,
'PI': SVC_RS,
'PR': SVC_RS,
'RJ': SVC_AN,
'RN': SVC_AN,
'RO': SVC_AN,
'RR': SVC_AN,
'RS': SVC_AN,
'SC': SVC_AN,
'SE': SVC_AN,
'SP': SVC_AN,
'TO': SVC_AN,
'AN': AN,
}

31
pytrustnfe/client.py

@ -2,11 +2,9 @@
# © 2016 Danimar Ribeiro, Trustcode
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import urllib3
import requests
import suds.client
import suds_requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
def get_authenticated_client(base_url, cert, key):
@ -33,32 +31,3 @@ def get_client(base_url):
cache=cache,
transport=suds_requests.RequestsTransport(session)
)
class HttpClient(object):
def __init__(self, url, cert_path, key_path):
self.url = url
self.cert_path = cert_path
self.key_path = key_path
def _headers(self, action, send_raw):
if send_raw:
return {
'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;',
'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.encode('utf-8'),
cert=(self.cert_path, self.key_path),
verify=False, headers=header)
return res.text

176
pytrustnfe/nfe/__init__.py

@ -7,34 +7,16 @@ import os
import hashlib
import binascii
from lxml import etree
from .comunicacao import executar_consulta
from .assinatura import Assinatura
from pytrustnfe.xml import render_xml
from pytrustnfe.utils import CabecalhoSoap
from pytrustnfe.xml import render_xml, sanitize_response
from pytrustnfe.utils import gerar_chave, ChaveNFe
from pytrustnfe.Servidores import localizar_url, localizar_qrcode
from pytrustnfe.xml.validate import valida_nfe
from pytrustnfe.exceptions import NFeValidationException
def _build_header(method, **kwargs):
action = {
'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]
}
return CabecalhoSoap(**vals)
from pytrustnfe.certificado import extract_cert_and_key_from_pfx, save_cert_key
# Zeep
from requests import Session
from zeep import Client
from zeep.transports import Transport
def _generate_nfe_id(**kwargs):
@ -56,26 +38,6 @@ def _generate_nfe_id(**kwargs):
item['infNFe']['ide']['cDV'] = chave_nfe[len(chave_nfe) - 1:]
def _add_required_node(elemTree):
ns = elemTree.nsmap
if None in ns:
ns['ns'] = ns[None]
ns.pop(None)
prods = elemTree.findall('ns:NFe/ns:infNFe/ns:det/ns:prod', namespaces=ns)
for prod in prods:
element = prod.find('ns:cEAN', namespaces=ns)
if element is None:
cEan = etree.Element('cEAN')
prod.insert(1, cEan)
element = prod.find('ns:cEANTrib', namespaces=ns)
if element is None:
cEANTrib = etree.Element('cEANTrib')
vProd = prod.find('ns:vProd', namespaces=ns)
prod.insert(prod.index(vProd) + 1, cEANTrib)
return elemTree
def _add_qrCode(xml, **kwargs):
xml = etree.fromstring(xml)
inf_nfe = kwargs['NFes'][0]['infNFe']
@ -89,9 +51,7 @@ def _add_qrCode(xml, **kwargs):
valor_total = inf_nfe['total']['vNF']
dest_cpf = 'Inexistente'
dest = nfe.find(".//{http://www.portalfiscal.inf.br/nfe}dest")
if dest:
dest_parent = dest.getparent()
dest_parent.remove(dest)
if inf_nfe.get('dest', False):
if inf_nfe['dest'].get('CPF', False):
dest_cpf = inf_nfe['dest']['CPF']
@ -99,7 +59,7 @@ def _add_qrCode(xml, **kwargs):
cpf = etree.Element('CPF')
cpf.text = dest_cpf
dest.append(cpf)
dest_parent.append(dest)
icms_total = inf_nfe['total']['vICMS']
dig_val = binascii.hexlify(xml.find(
".//{http://www.w3.org/2000/09/xmldsig#}DigestValue").text.encode()).decode()
@ -132,44 +92,17 @@ def _render(certificado, method, sign, **kwargs):
modelo = xmlElem_send.find(".//{http://www.portalfiscal.inf.br/nfe}mod")
modelo = modelo.text if modelo is not None else '55'
if modelo == '65':
pagamento = etree.Element('pag')
tipo_pagamento = etree.Element('tPag')
valor = etree.Element('vPag')
valor_pago = kwargs['NFes'][0]['infNFe']['total']['vNF']
metodo_pagamento = kwargs['NFes'][0]['infNFe']['pagamento']
tipo_pagamento.text, valor.text = metodo_pagamento, valor_pago
pagamento.append(tipo_pagamento)
pagamento.append(valor)
transp = xmlElem_send.find(
".//{http://www.portalfiscal.inf.br/nfe}transp")
transp.addnext(pagamento)
if sign:
# Caso for autorização temos que adicionar algumas tags tipo
# cEan, cEANTrib porque o governo sempre complica e não segue padrão
if method == 'NfeAutorizacao':
xmlElem_send = _add_required_node(xmlElem_send)
signer = Assinatura(certificado.pfx, certificado.password)
if method == 'NfeInutilizacao':
xml_send = signer.assina_xml(xmlElem_send, kwargs['obj']['id'])
if method == 'NfeAutorizacao':
xml_send = signer.assina_xml(
xmlElem_send, kwargs['NFes'][0]['infNFe']['Id'])
if 'validate' in kwargs:
erros = valida_nfe(xml_send)
if erros:
raise NFeValidationException('Erro ao validar NFe',
erros=erros,
sent_xml=xml_send)
elif method == 'RecepcaoEventoCancelamento':
elif method == 'RecepcaoEvento':
xml_send = signer.assina_xml(
xmlElem_send, kwargs['eventos'][0]['Id'])
if method == 'RecepcaoEventoCarta':
xml_send = signer.assina_xml(
xmlElem_send, kwargs['Id'])
elif method == 'RecepcaoEventoManifesto':
xml_send = signer.assina_xml(
xmlElem_send, kwargs['manifesto']['identificador'])
@ -184,20 +117,31 @@ def _render(certificado, method, sign, **kwargs):
def _send(certificado, method, **kwargs):
xml_send = kwargs["xml"]
url = localizar_url(method, kwargs['estado'], '55',
kwargs['ambiente'])
cabecalho = _build_header(method, **kwargs)
send_raw = False
if method == 'NFeDistribuicaoDFe':
send_raw = True
response, obj = executar_consulta(certificado, url, cabecalho, xml_send,
send_raw=send_raw)
base_url = localizar_url(
method, kwargs['estado'], kwargs['modelo'], kwargs['ambiente'])
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)
xml = etree.fromstring(xml_send)
client = Client(base_url, transport=transport)
port = next(iter(client.wsdl.port_types))
first_operation = [x for x in iter(
client.wsdl.port_types[port].operations) if "Zip" not in x][0]
with client.settings(raw_response=True):
response = client.service[first_operation](xml)
response, obj = sanitize_response(response.text)
return {
'sent_xml': xml_send,
'received_xml': response.decode(),
'object': obj
'received_xml': response,
'object': obj.Body.getchildren()[0]
}
@ -223,13 +167,13 @@ def retorno_autorizar_nfe(certificado, **kwargs):
def xml_recepcao_evento_cancelamento(certificado, **kwargs): # Assinar
return _render(certificado, 'RecepcaoEventoCancelamento', True, **kwargs)
return _render(certificado, 'RecepcaoEvento', True, **kwargs)
def recepcao_evento_cancelamento(certificado, **kwargs): # Assinar
if "xml" not in kwargs:
kwargs['xml'] = xml_recepcao_evento_cancelamento(certificado, **kwargs)
return _send(certificado, 'RecepcaoEventoCancelamento', **kwargs)
return _send(certificado, 'RecepcaoEvento', **kwargs)
def xml_inutilizar_nfe(certificado, **kwargs):
@ -243,7 +187,7 @@ def inutilizar_nfe(certificado, **kwargs):
def xml_consultar_protocolo_nfe(certificado, **kwargs):
return _render(certificado, 'NfeConsultaProtocolo', True, **kwargs)
return _render(certificado, 'NfeConsultaProtocolo', False, **kwargs)
def consultar_protocolo_nfe(certificado, **kwargs):
@ -269,38 +213,29 @@ def xml_consulta_cadastro(certificado, **kwargs):
def consulta_cadastro(certificado, **kwargs):
if "xml" not in kwargs:
kwargs['xml'] = xml_consulta_cadastro(certificado, **kwargs)
kwargs['modelo'] = '55'
return _send(certificado, 'NfeConsultaCadastro', **kwargs)
def xml_recepcao_evento_carta_correcao(certificado, **kwargs): # Assinar
return _render(certificado, 'RecepcaoEventoCarta', True, **kwargs)
return _render(certificado, 'RecepcaoEvento', True, **kwargs)
def recepcao_evento_carta_correcao(certificado, **kwargs): # Assinar
if "xml" not in kwargs:
kwargs['xml'] = xml_recepcao_evento_carta_correcao(
certificado, **kwargs)
return _send(certificado, 'RecepcaoEventoCarta', **kwargs)
return _send(certificado, 'RecepcaoEvento', **kwargs)
def xml_recepcao_evento_manifesto(certificado, **kwargs): # Assinar
return _render(certificado, 'RecepcaoEventoManifesto', True, **kwargs)
return _render(certificado, 'RecepcaoEvento', True, **kwargs)
def recepcao_evento_manifesto(certificado, **kwargs): # Assinar
if "xml" not in kwargs:
kwargs['xml'] = xml_recepcao_evento_manifesto(certificado, **kwargs)
return _send(certificado, 'RecepcaoEventoManifesto', **kwargs)
def xml_recepcao_evento_epec(certificado, **kwargs): # Assinar
return _render(certificado, 'RecepcaoEventoEPEC', True, **kwargs)
def recepcao_evento_epec(certificado, **kwargs): # Assinar
if "xml" not in kwargs:
kwargs['xml'] = xml_recepcao_evento_epec(certificado, **kwargs)
return _send(certificado, 'RecepcaoEventoEPEC', **kwargs)
return _send(certificado, 'RecepcaoEvento', **kwargs)
def xml_consulta_distribuicao_nfe(certificado, **kwargs): # Assinar
@ -310,7 +245,34 @@ def xml_consulta_distribuicao_nfe(certificado, **kwargs): # Assinar
def consulta_distribuicao_nfe(certificado, **kwargs):
if "xml" not in kwargs:
kwargs['xml'] = xml_consulta_distribuicao_nfe(certificado, **kwargs)
return _send(certificado, 'NFeDistribuicaoDFe', **kwargs)
xml_send = kwargs["xml"]
base_url = localizar_url(
'NFeDistribuicaoDFe', kwargs['estado'], kwargs['modelo'],
kwargs['ambiente'])
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)
xml = etree.fromstring(xml_send)
xml_um = etree.fromstring('<nfeCabecMsg xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/"><cUF>AN</cUF><versaoDados>1.00</versaoDados></nfeCabecMsg>')
client = Client(base_url, transport=transport)
port = next(iter(client.wsdl.port_types))
first_operation = next(iter(client.wsdl.port_types[port].operations))
with client.settings(raw_response=True):
response = client.service[first_operation](nfeDadosMsg=xml, _soapheaders=[xml_um])
response, obj = sanitize_response(response.text)
return {
'sent_xml': xml_send,
'received_xml': response,
'object': obj.Body.nfeDistDFeInteresseResponse.nfeDistDFeInteresseResult
}
def xml_download_nfe(certificado, **kwargs): # Assinar

34
pytrustnfe/nfe/comunicacao.py

@ -1,34 +0,0 @@
# -*- coding: utf-8 -*-
# © 2016 Danimar Ribeiro, Trustcode
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from pytrustnfe.client import HttpClient
from pytrustnfe.certificado import save_cert_key, extract_cert_and_key_from_pfx
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.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.method + '">'
xml += body
xml += '</nfeDadosMsg></soap:Body></soap:Envelope>'
return xml.rstrip('\n')
def executar_consulta(certificado, url, cabecalho, xmlEnviar, send_raw=False):
cert, key = extract_cert_and_key_from_pfx(
certificado.pfx, certificado.password)
cert_path, key_path = save_cert_key(cert, key)
client = HttpClient(url, cert_path, key_path)
xml_enviar = _soap_xml(xmlEnviar, cabecalho)
if send_raw:
xml = '<?xml version="1.0" encoding="utf-8"?>' + xmlEnviar.rstrip('\n')
xml_enviar = xml
xml_retorno = client.post_soap(xml_enviar, cabecalho, send_raw)
return sanitize_response(xml_retorno.encode())

460
pytrustnfe/nfe/danfce.py

@ -0,0 +1,460 @@
# -*- coding: utf-8 -*-
# © 2017 Johny Chen Jy, Trustcode
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import re
from textwrap import wrap
from io import BytesIO
from reportlab.lib import utils
from reportlab.pdfgen import canvas
from reportlab.lib.units import cm, mm
from reportlab.graphics.barcode import qr
from reportlab.graphics import renderPDF
from reportlab.graphics.shapes import Drawing
from reportlab.platypus import Table, TableStyle, Paragraph, Image
from reportlab.lib.enums import TA_CENTER
from reportlab.lib.styles import ParagraphStyle
def format_cnpj_cpf(value):
if len(value) < 12: # CPF
cValue = '%s.%s.%s-%s' % (value[:-8], value[-8:-5],
value[-5:-2], value[-2:])
else:
cValue = '%s.%s.%s/%s-%s' % (value[:-12], value[-12:-9],
value[-9:-6], value[-6:-2], value[-2:])
return cValue
def getdateUTC(cDateUTC):
cDt = cDateUTC[0:10].split('-')
cDt.reverse()
return '/'.join(cDt), cDateUTC[11:16]
def format_number(cNumber, precision=0, group_sep='.', decimal_sep=','):
if cNumber:
number = float(cNumber)
return ("{:,." + str(precision) + "f}").format(number).\
replace(",", "X").replace(".", ",").replace("X", ".")
return ""
def tagtext(oNode=None, cTag=None):
try:
xpath = ".//{http://www.portalfiscal.inf.br/nfe}%s" % (cTag)
cText = oNode.find(xpath).text
except:
cText = ''
return cText
def get_image(path, width=1 * cm):
img = utils.ImageReader(path)
iw, ih = img.getSize()
aspect = ih / float(iw)
return Image(path, width=width, height=(width * aspect))
def format_telefone(telefone):
telefone = re.sub('[^0-9]', '', telefone)
if len(telefone) == 10:
telefone = '(%s) %s-%s' % (telefone[0:2],
telefone[2:6],
telefone[6:])
elif len(telefone) == 11:
telefone = '(%s) %s-%s' % (telefone[0:2],
telefone[2:7],
telefone[7:])
return telefone
class danfce(object):
def __init__(self, list_xml, logo=None):
self.current_font_size = 7
self.current_font_name = 'NimbusSanL-Regu'
self.max_height = 840
self.min_height = 1
self.min_width = 5
self.max_width = 200
self.current_height = 840
self.oPDF_IO = BytesIO()
self.canvas = canvas.Canvas(self.oPDF_IO, pagesize=(7.2 * cm, 30 * cm))
self.canvas.setTitle('DANFCE')
self.canvas.setLineWidth(.5)
self.canvas.setFont(self.current_font_name, self.current_font_size)
self.list_xml = list_xml
self.logo = logo
self.nfce_generate()
def ide_emit(self, oXML=None):
elem_emit = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}emit")
# Razão Social emitente
nomeEmpresa = tagtext(oNode=elem_emit, cTag='xFant')
self.drawTitle(nomeEmpresa, 10)
if self.logo:
img = get_image(self.logo, width=10 * mm)
img.drawOn(self.canvas, 5, 830)
cEnd = tagtext(oNode=elem_emit, cTag="xNome") + '<br />'
cEnd += "CNPJ: %s " % (format_cnpj_cpf(
tagtext(oNode=elem_emit, cTag='CNPJ')))
cEnd += "IE: %s" % (tagtext(oNode=elem_emit, cTag="IE")) + '<br />'
cEnd += tagtext(oNode=elem_emit, cTag='xLgr') + ', ' + tagtext(
oNode=elem_emit, cTag='nro') + ' - '
cEnd += tagtext(oNode=elem_emit, cTag='xBairro') + '<br />' + tagtext(
oNode=elem_emit, cTag='xMun') + ' - '
cEnd += tagtext(oNode=elem_emit, cTag='UF') + ' - ' + tagtext(
oNode=elem_emit, cTag='CEP') + '<br />'
cEnd += 'Fone: ' + format_telefone(tagtext(
oNode=elem_emit, cTag='fone'))
self._drawCenteredParagraph(cEnd)
self.drawLine()
def danfce_information(self):
self.drawTitle(
"DANFE NFC-e - Documento Auxiliar da Nota Fiscal de",
7, 'NimbusSanL-Bold')
self.drawTitle("Consumidor Eletrônica", 7, 'NimbusSanL-Bold')
self.drawString(
"NFC-e não permite aproveitamento de crédito de ICMS", True)
self.drawLine()
def produtos(self, oXML=None, el_det=None, oPaginator=None,
list_desc=None, list_cod_prod=None):
rows = [['Cód', 'Descrição', 'Qtde', 'Un', 'Unit.', 'Total']]
colWidths = (25, 90, 15, 15, 25, 25)
rowHeights = [7]
for id in range(oPaginator[0], oPaginator[1]):
item = el_det[id]
el_prod = item.find(".//{http://www.portalfiscal.inf.br/nfe}prod")
cod = tagtext(oNode=el_prod, cTag='cProd')
descricao = tagtext(oNode=el_prod, cTag='xProd')
descricao = (descricao[:20] + '..') if len(descricao) > 20 else descricao
Un = tagtext(oNode=el_prod, cTag='uCom')
Un = (Un[:2]) if len(Un) > 2 else Un
qtde = format_number(tagtext(oNode=el_prod, cTag='qCom'),
precision=2)
vl_unit = format_number(tagtext(oNode=el_prod, cTag='vUnCom'),
precision=2)
vl_total = format_number(
tagtext(oNode=el_prod, cTag='vProd'), precision=2)
new_row = [cod, descricao, qtde, Un, vl_unit, vl_total]
rows.append(new_row)
rowHeights.append(self.current_font_size + 2)
self._draw_product_table(rows, colWidths, rowHeights)
def _draw_product_table(self, rows, colWidths, rowHeights):
table = Table(rows, colWidths, tuple(rowHeights))
table.setStyle(TableStyle([
('FONTSIZE', (0, 0), (-1, -1), 7),
('FONT', (0, 1), (-1, -1), 'NimbusSanL-Regu'),
('FONT', (0, 0), (-1, 0), 'NimbusSanL-Bold'),
('ALIGN', (0, 0), (-1, 0), "LEFT"),
('ALIGN', (1, 0), (-1, 0), "LEFT"),
('ALIGN', (2, 0), (-1, 0), "CENTER"),
('ALIGN', (3, 0), (-1, 0), "CENTER"),
('ALIGN', (0, 1), (-1, -1), "LEFT"),
('ALIGN', (1, 1), (-1, -1), "LEFT"),
('ALIGN', (2, 1), (-1, -1), "CENTER"),
('ALIGN', (3, 1), (-1, -1), "CENTER"),
]))
w, h = table.wrapOn(self.canvas, 200, 450)
table.drawOn(self.canvas, 0, self.current_height - (h * 1.2))
self.current_height -= (h * 1.1)
def totais(self, oXML=None):
# Impostos
el_total = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}total")
total_tributo = format_number(tagtext(oNode=el_total, cTag='vTotTrib'),
precision=2)
valor_total = format_number(tagtext(oNode=el_total, cTag='vProd'),
precision=2)
desconto = format_number(tagtext(oNode=el_total, cTag='vDesc'),
precision=2)
valor_a_pagar = format_number(tagtext(oNode=el_total, cTag='vNF'),
precision=2)
el_pag = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}pag")
troco = format_number(tagtext(oNode=el_pag, cTag="vTroco"))
payment_method_list = {'01': 'Dinheiro',
'02': 'Cheque',
'03': 'Cartão de Crédito',
'04': 'Cartão de Débito',
"05": "Crédito Loja",
'10': 'Vale Alimentação',
'11': 'Vale Refeição',
'12': 'Vale Presente',
'13': 'Vale Combustível',
'14': 'Duplicata Mercantil',
'15': 'Boleto Bancario',
'90': 'Sem Pagamento',
'99': 'Outros'}
quant_produtos = len(oXML.findall(
".//{http://www.portalfiscal.inf.br/nfe}det"))
payment_methods = []
for pagId, item in enumerate(el_pag):
if 'tPag' not in item.tag:
continue
payment = []
method = payment_method_list[item.text]
payment.append(method)
payment.append(format_number(item.getnext().text, precision=2))
payment_methods.append(payment)
values = {'quantidade_itens': quant_produtos,
'total_tributo': total_tributo,
'valor_total': valor_total,
'desconto': desconto,
'valor_a_pagar': valor_a_pagar,
'formas_de_pagamento': payment_methods,
'troco': troco,
}
self.draw_totals_table(values)
self.drawLine()
def draw_totals_table(self, values):
rowHeights = [7, 7, 7, 7, 10]
data = [['QTD.TOTAL DE ITENS', values['quantidade_itens']],
['VALOR TOTAL R$', values['valor_total']],
['DESCONTO R$', values['desconto']],
['VALOR A PAGAR R$', values['valor_a_pagar']],
['FORMA DE PAGAMENTO', 'VALOR PAGO R$'],
]
for item in values['formas_de_pagamento']:
data.append([item[0], item[1]])
rowHeights.append(7)
data.append(['TROCO', format_number(values['troco'], precision=2)])
rowHeights.append(7)
table2 = Table(data, colWidths=(150, 50), rowHeights=tuple(rowHeights))
table2.setStyle(TableStyle([
('FONTSIZE', (0, 0), (-1, -1), 7),
('FONT', (0, 0), (1, -1), 'NimbusSanL-Regu'),
('FONT', (0, 4), (1, 4), 'NimbusSanL-Bold'),
('ALIGN', (1, 0), (1, -1), "RIGHT")
]))
w, h = table2.wrapOn(self.canvas, 200, 450)
table2.drawOn(self.canvas, 0, self.current_height - (h * 1.1))
self.current_height -= h
def inf_authentication(self, oXML=None):
el_infNFe = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}infNFe")
# n nfce, serie e data de solicitacao
el_ide = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}ide")
el_NFeSupl = oXML.find(
".//{http://www.portalfiscal.inf.br/nfe}infNFeSupl")
el_dest = el_infNFe.find(".//{http://www.portalfiscal.inf.br/nfe}dest")
# chave, n protocolo, data autorizacao
el_prot_nfe = oXML.find(
".//{http://www.portalfiscal.inf.br/nfe}protNFe")
el_infAdic = oXML.find(
".//{http://www.portalfiscal.inf.br/nfe}infAdic")
url_chave = tagtext(oNode=el_NFeSupl, cTag='urlChave')
access_key = tagtext(oNode=el_prot_nfe, cTag="chNFe")
frase_chave_acesso = 'Consulte pela Chave de Acesso em:<br />\
%s<br />%s' % (url_chave, access_key)
qrcode = tagtext(oNode=el_NFeSupl, cTag='qrCode')
cnpj = tagtext(oNode=el_dest, cTag='CNPJ')
cpf = tagtext(oNode=el_dest, cTag='CPF')
if cnpj:
cnpj_cpf = format_cnpj_cpf(cnpj)
cnpj_cpf = "CONSUMIDOR CNPJ: %s" % (cnpj)
elif cpf:
cnpj_cpf = format_cnpj_cpf(cpf)
cnpj_cpf = "CONSUMIDOR CPF: %s" % (cpf)
else:
cnpj_cpf = u"CONSUMIDOR NÃO IDENTIFICADO"
nNFC = tagtext(oNode=el_ide, cTag="nNF")
serie = tagtext(oNode=el_ide, cTag='serie')
dataSolicitacao = getdateUTC(tagtext(oNode=el_ide, cTag="dhEmi"))
dataSolicitacao = dataSolicitacao[0] + " " + dataSolicitacao[1]
numProtocolo = tagtext(oNode=el_prot_nfe, cTag="nProt")
dataAutorizacao = getdateUTC(tagtext(oNode=el_prot_nfe,
cTag='dhRecbto'))
dataAutorizacao = dataAutorizacao[0] + " " + dataAutorizacao[1]
text = u"%s <br />%s <br />NFC-e nº%s Série %s %s<br />\
Protocolo de autorização: %s<br />Data de autorização %s<br />\
" % (frase_chave_acesso, cnpj_cpf, nNFC, serie, dataSolicitacao,
numProtocolo, dataAutorizacao)
self._drawCenteredParagraph(text)
self.draw_qr_code(qrcode)
infAdFisco = tagtext(oNode=el_infAdic, cTag='infAdFisco')
self._drawCenteredParagraph(infAdFisco)
infCpl = tagtext(oNode=el_infAdic, cTag='infCpl')
self._drawCenteredParagraph(infCpl)
def _drawCenteredParagraph(self, text):
style = ParagraphStyle(
name='Normal',
fontName='NimbusSanL-Regu',
fontSize=7,
alignment=TA_CENTER,
leading=7,
)
paragraph = Paragraph(text, style=style)
w, h = paragraph.wrapOn(self.canvas, 180, 300)
paragraph.drawOn(self.canvas, 10, self.current_height - h)
self.current_height -= (h*1.1)
def drawString(self, string, centered=False):
if centered:
self.canvas.drawCentredString(
self.max_width / 2, self.current_height, string)
self.current_height -= self.current_font_size
else:
self.canvas.drawString(self.min_width, self.current_height, string)
self.current_height -= self.current_font_size
def drawTitle(self, string, size, font='NimbusSanL-Regu'):
self.canvas.setFont(font, size)
self.canvas.drawCentredString(
self.max_width / 2, self.current_height, string)
self.current_height -= self.current_font_size
self.canvas.setFont(self.current_font_name, self.current_font_size)
def drawLine(self):
self.canvas.line(self.min_width, self.current_height,
self.max_width, self.current_height)
self.current_height -= self.current_font_size
def draw_qr_code(self, string):
qr_code = qr.QrCodeWidget(string)
drawing = Drawing(23 * mm, 23 * mm)
drawing.add(qr_code)
renderPDF.draw(drawing, self.canvas, 20 * mm, self.current_height - 85)
self.current_height -= 85
def newpage(self):
self.current_height = self.max_height
self.Page += 1
self.canvas.showPage()
def nfce_generate(self):
for oXML in self.list_xml:
oXML_cobr = oXML.find(
".//{http://www.portalfiscal.inf.br/nfe}cobr")
self.NrPages = 1
self.Page = 1
# Calculando total linhas usadas para descrições dos itens
# Com bloco fatura, apenas 29 linhas para itens na primeira folha
nNr_Lin_Pg_1 = 34 if oXML_cobr is None else 30
# [ rec_ini , rec_fim , lines , limit_lines ]
oPaginator = [[0, 0, 0, nNr_Lin_Pg_1]]
el_det = oXML.findall(".//{http://www.portalfiscal.inf.br/nfe}det")
if el_det is not None:
list_desc = []
list_cod_prod = []
nPg = 0
for nId, item in enumerate(el_det):
el_prod = item.find(
".//{http://www.portalfiscal.inf.br/nfe}prod")
infAdProd = item.find(
".//{http://www.portalfiscal.inf.br/nfe}infAdProd")
list_ = wrap(tagtext(oNode=el_prod, cTag='xProd'), 56)
if infAdProd is not None:
list_.extend(wrap(infAdProd.text, 56))
list_desc.append(list_)
list_cProd = wrap(tagtext(oNode=el_prod, cTag='cProd'), 14)
list_cod_prod.append(list_cProd)
# Nr linhas necessárias p/ descrição item
nLin_Itens = len(list_)
if (oPaginator[nPg][2] + nLin_Itens) >= oPaginator[nPg][3]:
oPaginator.append([0, 0, 0, 77])
nPg += 1
oPaginator[nPg][0] = nId
oPaginator[nPg][1] = nId + 1
oPaginator[nPg][2] = nLin_Itens
else:
# adiciona-se 1 pelo funcionamento de xrange
oPaginator[nPg][1] = nId + 1
oPaginator[nPg][2] += nLin_Itens
self.NrPages = len(oPaginator) # Calculando nr. páginas
self.ide_emit(oXML=oXML)
# self.destinatario(oXML=oXML)
self.danfce_information()
self.produtos(oXML=oXML, el_det=el_det, oPaginator=oPaginator[0],
list_desc=list_desc, list_cod_prod=list_cod_prod)
self.drawLine()
self.totais(oXML=oXML)
self.inf_authentication(oXML=oXML)
# Gera o restante das páginas do XML
for oPag in oPaginator[1:]:
if oPag:
self.newpage()
self.ide_emit(oXML=oXML)
# self.destinatario(oXML=oXML)
self.produtos(oXML=oXML, el_det=el_det, oPaginator=oPag,
list_desc=list_desc,
list_cod_prod=list_cod_prod)
self.totais(oXML=oXML)
self.inf_authentication(oXML=oXML)
self.newpage()
self.canvas.save()
def writeto_pdf(self, fileObj):
pdf_out = self.oPDF_IO.getvalue()
self.oPDF_IO.close()
fileObj.write(pdf_out)

12
pytrustnfe/nfe/danfe.py

@ -323,7 +323,7 @@ class danfe(object):
P = Paragraph(tagtext(oNode=elem_emit, cTag='xNome'), styleN)
w, h = P.wrap(55 * mm, 40 * mm)
P.drawOn(self.canvas, (self.nLeft + 30) * mm,
(self.height - self.nlin - ((5*h + 12)/12)) * mm)
(self.height - self.nlin - ((4.3*h + 12)/12)) * mm)
if self.logo:
img = get_image(self.logo, width=2 * cm)
@ -347,7 +347,7 @@ class danfe(object):
P = Paragraph(cEnd, styleN)
w, h = P.wrap(55 * mm, 30 * mm)
P.drawOn(self.canvas, (self.nLeft + 30) * mm,
(self.height - self.nlin - 31) * mm)
(self.height - self.nlin - 33) * mm)
# Homologação
if tagtext(oNode=elem_ide, cTag='tpAmb') == '2':
@ -584,6 +584,8 @@ obsCont[@xCampo='NomeVendedor']")
def transportes(self, oXML=None):
el_transp = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}transp")
veic_transp = oXML.find(
".//{http://www.portalfiscal.inf.br/nfe}veicTransp")
nMr = self.width - self.nRight
self.canvas.setFont('NimbusSanL-Bold', 7)
@ -627,6 +629,12 @@ obsCont[@xCampo='NomeVendedor']")
tagtext(oNode=el_transp, cTag='xNome')[:40])
self.string(self.nLeft + 71, self.nlin + 7.7,
self.oFrete[tagtext(oNode=el_transp, cTag='modFrete')])
self.string(self.nLeft + 99, self.nlin + 7.7,
tagtext(oNode=el_transp, cTag='RNTC'))
self.string(self.nLeft + 116, self.nlin + 7.7,
tagtext(oNode=el_transp, cTag='placa'))
self.string(self.nLeft + 142, self.nlin + 7.7,
tagtext(oNode=veic_transp, cTag='UF'))
self.string(nMr - 39, self.nlin + 7.7,
format_cnpj_cpf(tagtext(oNode=el_transp, cTag='CNPJ')))
self.string(self.nLeft + 1, self.nlin + 14.2,

12
pytrustnfe/nfe/templates/NFeDistribuicaoDFe.xml

@ -1,8 +1,4 @@
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<nfeDistDFeInteresse xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/NFeDistribuicaoDFe">
<nfeDadosMsg>
<distDFeInt xmlns="http://www.portalfiscal.inf.br/nfe" versao="1.01">
<distDFeInt xmlns="http://www.portalfiscal.inf.br/nfe" versao="1.01">
<tpAmb>{{ ambiente }}</tpAmb>
<cUFAutor>{{ estado }}</cUFAutor>
<CNPJ>{{ cnpj_cpf }}</CNPJ>
@ -12,8 +8,4 @@
<consChNFe>
<chNFe>{{ chave_nfe }}</chNFe>
</consChNFe>
</distDFeInt>
</nfeDadosMsg>
</nfeDistDFeInteresse>
</Body>
</Envelope>
</distDFeInt>

91
pytrustnfe/nfe/templates/NfeAutorizacao.xml

@ -1,15 +1,14 @@
<enviNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="3.10">
<enviNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="4.00">
<idLote>{{ idLote }}</idLote>
<indSinc>{{ indSinc }}</indSinc>
{% for NFe in NFes %}
<NFe xmlns="http://www.portalfiscal.inf.br/nfe">
<infNFe versao="3.10" Id="{{ NFe.infNFe.Id }}">
<infNFe versao="4.00" Id="{{ NFe.infNFe.Id }}">
<ide>
{% with ide = NFe.infNFe.ide %}
<cUF>{{ ide.cUF }}</cUF>
<cNF>{{ ide.cNF }}</cNF>
<natOp>{{ ide.natOp }}</natOp>
<indPag>{{ ide.indPag }}</indPag>
<mod>{{ ide.mod }}</mod>
<serie>{{ ide.serie }}</serie>
<nNF>{{ ide.nNF }}</nNF>
@ -182,6 +181,9 @@
<NCM>{{ prod.NCM }}</NCM>
<NVE>{{ prod.NVE }}</NVE>
<CEST>{{ prod.CEST }}</CEST>
<indEscala>{{ prod.indEscala }}</indEscala>
<CNPJFab>{{ prod.CNPJFab }}</CNPJFab>
<cBenef>{{ prod.cBenef }}</cBenef>
<EXTIPI>{{ prod.EXTIPI }}</EXTIPI>
<CFOP>{{ prod.CFOP }}</CFOP>
<uCom>{{ prod.uCom }}</uCom>
@ -244,6 +246,21 @@
<xPed>{{ prod.xPed }}</xPed>
<nItemPed>{{ prod.nItemPed }}</nItemPed>
<nFCI>{{ prod.nFCI }}</nFCI>
{% for rastro in prod.rastro %}
<rastro>
<nLote>{{ rastro.nLote }}</nLote>
<qLote>{{ rastro.qLote }}</qLote>
<dFab>{{ rastro.dFab }}</dFab>
<dVal>{{ rastro.dVal }}</dVal>
<cAgreg>{{ rastro.cAgreg }}</cAgreg>
</rastro>
{% endfor %}
{% for med in prod.med %}
<med>
<cProdANVISA>{{ med.cProdANVISA }}</cProdANVISA>
<vPMC>{{ med.vPMC }}</vPMC>
</med>
{% endfor %}
{% endwith %}
</prod>
<imposto>
@ -258,6 +275,8 @@
<vBC>{{ imposto.ICMS.vBC }}</vBC>
<pICMS>{{ imposto.ICMS.pICMS }}</pICMS>
<vICMS>{{ imposto.ICMS.vICMS }}</vICMS>
<pFCP>{{ imposto.ICMS.pFCP }}</pFCP>
<vFCP>{{ imposto.ICMS.vFCP }}</vFCP>
</ICMS00>
{% endif %}
{% if imposto.ICMS.CST == '10' -%}
@ -268,12 +287,18 @@
<vBC>{{ imposto.ICMS.vBC }}</vBC>
<pICMS>{{ imposto.ICMS.pICMS }}</pICMS>
<vICMS>{{ imposto.ICMS.vICMS }}</vICMS>
<vBCFCP>{{ imposto.ICMS.vBCFCP }}</vBCFCP>
<pFCP>{{ imposto.ICMS.pFCP }}</pFCP>
<vFCP>{{ imposto.ICMS.vFCP }}</vFCP>
<modBCST>{{ imposto.ICMS.modBCST }}</modBCST>
<pMVAST>{{ imposto.ICMS.pMVAST }}</pMVAST>
<pRedBCST>{{ imposto.ICMS.pRedBCST }}</pRedBCST>
<vBCST>{{ imposto.ICMS.vBCST }}</vBCST>
<pICMSST>{{ imposto.ICMS.pICMSST }}</pICMSST>
<vICMSST>{{ imposto.ICMS.vICMSST }}</vICMSST>
<vBCFCPST>{{ imposto.ICMS.vBCFCPST }}</vBCFCPST>
<pFCPST>{{ imposto.ICMS.pFCPST }}</pFCPST>
<vFCPST>{{ imposto.ICMS.vFCPST }}</vFCPST>
</ICMS10>
{% endif %}
{% if imposto.ICMS.CST == '20' -%}
@ -285,6 +310,9 @@
<vBC>{{ imposto.ICMS.vBC }}</vBC>
<pICMS>{{ imposto.ICMS.pICMS }}</pICMS>
<vICMS>{{ imposto.ICMS.vICMS }}</vICMS>
<vBCFCP>{{ imposto.ICMS.vBCFCP }}</vBCFCP>
<pFCP>{{ imposto.ICMS.pFCP }}</pFCP>
<vFCP>{{ imposto.ICMS.vFCP }}</vFCP>
<vICMSDeson>{{ imposto.ICMS.vICMSDeson }}</vICMSDeson>
<motDesICMS>{{ imposto.ICMS.motDesICMS }}</motDesICMS>
</ICMS20>
@ -299,6 +327,9 @@
<vBCST>{{ imposto.ICMS.vBCST }}</vBCST>
<pICMSST>{{ imposto.ICMS.pICMSST }}</pICMSST>
<vICMSST>{{ imposto.ICMS.vICMSST }}</vICMSST>
<vBCFCPST>{{ imposto.ICMS.vBCFCPST }}</vBCFCPST>
<pFCPST>{{ imposto.ICMS.pFCPST }}</pFCPST>
<vFCPST>{{ imposto.ICMS.vFCPST }}</vFCPST>
<vICMSDeson>{{ imposto.ICMS.vICMSDeson }}</vICMSDeson>
<motDesICMS>{{ imposto.ICMS.motDesICMS }}</motDesICMS>
</ICMS30>
@ -323,6 +354,9 @@
<pDif>{{ imposto.ICMS.pDif }}</pDif>
<vICMSDif>{{ imposto.ICMS.vICMSDif }}</vICMSDif>
<vICMS>{{ imposto.ICMS.vICMS }}</vICMS>
<vBCFCP>{{ imposto.ICMS.vBCFCP }}</vBCFCP>
<pFCP>{{ imposto.ICMS.pFCP }}</pFCP>
<vFCP>{{ imposto.ICMS.vFCP }}</vFCP>
</ICMS51>
{% endif %}
{% if imposto.ICMS.CST == '60' -%}
@ -330,7 +364,11 @@
<orig>{{ imposto.ICMS.orig }}</orig>
<CST>{{ imposto.ICMS.CST }}</CST>
<vBCSTRet>{{ imposto.ICMS.vBCSTRet }}</vBCSTRet>
<pST>{{ imposto.ICMS.pST }}</pST>
<vICMSSTRet>{{ imposto.ICMS.vICMSSTRet }}</vICMSSTRet>
<vBCFCPSTRet>{{ imposto.ICMS.vBCFCPSTRet }}</vBCFCPSTRet>
<pFCPSTRet>{{ imposto.ICMS.pFCPSTRet }}</pFCPSTRet>
<vFCPSTRet>{{ imposto.ICMS.vFCPSTRet }}</vFCPSTRet>
</ICMS60>
{% endif %}
{% if imposto.ICMS.CST == '70' -%}
@ -342,12 +380,18 @@
<vBC>{{ imposto.ICMS.vBC }}</vBC>
<pICMS>{{ imposto.ICMS.pICMS }}</pICMS>
<vICMS>{{ imposto.ICMS.vICMS }}</vICMS>
<vBCFCP>{{ imposto.ICMS.vBCFCP }}</vBCFCP>
<pFCP>{{ imposto.ICMS.pFCP }}</pFCP>
<vFCP>{{ imposto.ICMS.vFCP }}</vFCP>
<modBCST>{{ imposto.ICMS.modBCST }}</modBCST>
<pMVAST>{{ imposto.ICMS.pMVAST }}</pMVAST>
<pRedBCST>{{ imposto.ICMS.pRedBCST }}</pRedBCST>
<vBCST>{{ imposto.ICMS.vBCST }}</vBCST>
<pICMSST>{{ imposto.ICMS.pICMSST }}</pICMSST>
<vICMSST>{{ imposto.ICMS.vICMSST }}</vICMSST>
<vBCFCPST>{{ imposto.ICMS.vBCFCPST }}</vBCFCPST>
<pFCPST>{{ imposto.ICMS.pFCPST }}</pFCPST>
<vFCPST>{{ imposto.ICMS.vFCPST }}</vFCPST>
<vICMSDeson>{{ imposto.ICMS.vICMSDeson }}</vICMSDeson>
<motDesICMS>{{ imposto.ICMS.motDesICMS }}</motDesICMS>
</ICMS70>
@ -361,12 +405,18 @@
<pRedBC>{{ imposto.ICMS.pRedBC }}</pRedBC>
<pICMS>{{ imposto.ICMS.pICMS }}</pICMS>
<vICMS>{{ imposto.ICMS.vICMS }}</vICMS>
<vBCFCP>{{ imposto.ICMS.vBCFCP }}</vBCFCP>
<pFCP>{{ imposto.ICMS.pFCP }}</pFCP>
<vFCP>{{ imposto.ICMS.pFCP }}</vFCP>
<modBCST>{{ imposto.ICMS.modBCST }}</modBCST>
<pMVAST>{{ imposto.ICMS.pMVAST }}</pMVAST>
<pRedBCST>{{ imposto.ICMS.pRedBCST }}</pRedBCST>
<vBCST>{{ imposto.ICMS.vBCST }}</vBCST>
<pICMSST>{{ imposto.ICMS.pICMSST }}</pICMSST>
<vICMSST>{{ imposto.ICMS.vICMSST }}</vICMSST>
<vBCFCPST>{{ imposto.ICMS.vBCFCPST }}</vBCFCPST>
<pFCPST>{{ imposto.ICMS.pFCPST }}</pFCPST>
<vFCPST>{{ imposto.ICMS.vFCPST }}</vFCPST>
<vICMSDeson>{{ imposto.ICMS.vICMSDeson }}</vICMSDeson>
<motDesICMS>{{ imposto.ICMS.motDesICMS }}</motDesICMS>
</ICMS90>
@ -380,12 +430,10 @@
<pRedBC>{{ imposto.ICMSPart.pRedBC }}</pRedBC>
<pICMS>{{ imposto.ICMSPart.pICMS }}</pICMS>
<vICMS>{{ imposto.ICMSPart.vICMS }}</vICMS>
<vBCST>{{ imposto.ICMS.vBCST }}</vBCST>
<modBCST>{{ imposto.ICMSPart.modBCST }}</modBCST>
<pMVAST>{{ imposto.ICMSPart.pMVAST }}</pMVAST>
<pRedBCST>{{ imposto.ICMSPart.pRedBCST }}</pRedBCST>
<vBCST>{{ imposto.ICMSPart.vBCST }}</vBCST>
<pICMSST>{{ imposto.ICMSPart.pICMSST }}</pICMSST>
<vICMSST>{{ imposto.ICMSPart.vICMSST }}</vICMSST>
<pBCOp>{{ imposto.ICMSPart.pBCOp }}</pBCOp>
<UFST>{{ imposto.ICMSPart.UFST }}</UFST>
</ICMSPart>
@ -424,6 +472,9 @@
<vBCST>{{ imposto.ICMS.vBCST }}</vBCST>
<pICMSST>{{ imposto.ICMS.pICMSST }}</pICMSST>
<vICMSST>{{ imposto.ICMS.vICMSST }}</vICMSST>
<vBCFCPST>{{ imposto.ICMS.vBCFCPST }}</vBCFCPST>
<pFCPST>{{ imposto.ICMS.pFCPST }}</pFCPST>
<vFCPST>{{ imposto.ICMS.vFCPST }}</vFCPST>
<pCredSN>{{ imposto.ICMS.pCredSN }}</pCredSN>
<vCredICMSSN>{{ imposto.ICMS.vCredICMSSN }}</vCredICMSSN>
</ICMSSN201>
@ -438,6 +489,9 @@
<vBCST>{{ imposto.ICMS.vBCST }}</vBCST>
<pICMSST>{{ imposto.ICMS.pICMSST }}</pICMSST>
<vICMSST>{{ imposto.ICMS.vICMSST }}</vICMSST>
<vBCFCPST>{{ imposto.ICMS.vBCFCPST }}</vBCFCPST>
<pFCPST>{{ imposto.ICMS.pFCPST }}</pFCPST>
<vFCPST>{{ imposto.ICMS.vFCPST }}</vFCPST>
</ICMSSN202>
{% endif %}
{% if imposto.ICMS.CST == '500' -%}
@ -445,7 +499,11 @@
<orig>{{ imposto.ICMS.orig }}</orig>
<CSOSN>{{ imposto.ICMS.CST }}</CSOSN>
<vBCSTRet>{{ imposto.ICMS.vBCSTRet }}</vBCSTRet>
<pST>{{ imposto.ICMS.pST }}</pST>
<vICMSSTRet>{{ imposto.ICMS.vICMSSTRet }}</vICMSSTRet>
<vBCFCPSTRet>{{ imposto.ICMS.vBCFCPSTRet }}</vBCFCPSTRet>
<pFCPSTRet>{{ imposto.ICMS.pFCPSTRet }}</pFCPSTRet>
<pFCPSTRet>{{ imposto.ICMS.pFCPSTRet }}</pFCPSTRet>
</ICMSSN500>
{% endif %}
{% if imposto.ICMS.CST == '900' -%}
@ -463,6 +521,9 @@
<vBCST>{{ imposto.ICMS.vBCST }}</vBCST>
<pICMSST>{{ imposto.ICMS.pICMSST }}</pICMSST>
<vICMSST>{{ imposto.ICMS.vICMSST }}</vICMSST>
<vBCFCPST>{{ imposto.ICMS.vBCFCPST }}</vBCFCPST>
<pFCPST>{{ imposto.ICMS.pFCPST }}</pFCPST>
<vFCPST>{{ imposto.ICMS.vFCPST }}</vFCPST>
<pCredSN>{{ imposto.ICMS.pCredSN }}</pCredSN>
<vCredICMSSN>{{ imposto.ICMS.vCredICMSSN }}</vCredICMSSN>
</ICMSSN900>
@ -491,7 +552,6 @@
</IPINT>
{% endif %}
</IPI>
{% endif %}
{% if imposto.II is defined %}
<II>
<vBC>{{ imposto.II.vBC }}</vBC>
@ -500,6 +560,7 @@
<vIOF>{{ imposto.II.vIOF }}</vIOF>
</II>
{% endif %}
{% endif %}
<PIS>
{% if imposto.PIS.CST in ('01', '02') %}
<PISAliq>
@ -607,8 +668,9 @@
{% if imposto.ICMSUFDest is defined %}
<ICMSUFDest>
<vBCUFDest>{{ imposto.ICMSUFDest.vBCUFDest }}</vBCUFDest>
<vBCFCPUFDest>{{ imposto.ICMSUFDest.vBCFCPUFDest }}</vBCFCPUFDest>
<pFCPUFDest>{{ imposto.ICMSUFDest.pFCPUFDest }}</pFCPUFDest>
<pICMSUFDest>{{ imposto.ICMSUFDest.pICMSInter }}</pICMSUFDest>
<pICMSUFDest>{{ imposto.ICMSUFDest.pICMSUFDest }}</pICMSUFDest>
<pICMSInter>{{ imposto.ICMSUFDest.pICMSInter }}</pICMSInter>
<pICMSInterPart>{{ imposto.ICMSUFDest.pICMSInterPart }}</pICMSInterPart>
<vFCPUFDest>{{ imposto.ICMSUFDest.vFCPUFDest }}</vFCPUFDest>
@ -639,14 +701,18 @@
<vFCPUFDest>{{ total.vFCPUFDest }}</vFCPUFDest>
<vICMSUFDest>{{ total.vICMSUFDest }}</vICMSUFDest>
<vICMSUFRemet>{{ total.vICMSUFRemet }}</vICMSUFRemet>
<vFCP>{{ total.vFCP }}</vFCP>
<vBCST>{{ total.vBCST }}</vBCST>
<vST>{{ total.vST }}</vST>
<vFCPST>{{ total.vFCPST }}</vFCPST>
<vFCPSTRet>{{ total.vFCPSTRet }}</vFCPSTRet>
<vProd>{{ total.vProd }}</vProd>
<vFrete>{{ total.vFrete }}</vFrete>
<vSeg>{{ total.vSeg }}</vSeg>
<vDesc>{{ total.vDesc }}</vDesc>
<vII>{{ total.vII }}</vII>
<vIPI>{{ total.vIPI }}</vIPI>
<vIPIDevol>{{ total.vIPIDevol }}</vIPIDevol>
<vPIS>{{ total.vPIS }}</vPIS>
<vCOFINS>{{ total.vCOFINS }}</vCOFINS>
<vOutro>{{ total.vOutro }}</vOutro>
@ -750,19 +816,24 @@
{% endif %}
{% endif %}
{% if NFe.infNFe.pag is defined %}
{% for pag in NFe.infNFe.pag %}
<pag>
{% for pag in NFe.infNFe.pag %}
<detPag>
<indPag>{{ pag.indPag }}</indPag>
<tPag>{{ pag.tPag }}</tPag>
<vPag>{{ pag.vPag }}</vPag>
{% if pag.card is defined %}
<card>
<tpIntegra>{{ pag.card.tpIntegra }}</tpIntegra>
<CNPJ>{{ pag.card.CNPJ }}</CNPJ>
<tBand>{{ pag.card.tBand }}</tBand>
<cAut>{{ pag.card.cAut }}</cAut>
</card>
{% endif %}
</pag>
<vTroco>{{ pag.vTroco }}</vTroco>
</detPag>
{% endfor %}
</pag>
{% endif %}
<infAdic>
<infAdFisco>{{ NFe.infNFe.infAdic.infAdFisco|normalize|escape }}</infAdFisco>

3
pytrustnfe/nfe/templates/NfeConsultaProtocolo.xml

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="UTF-8" ?>
<consSitNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="2.01">
<consSitNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="4.00">
<tpAmb>{{ obj.ambiente }}</tpAmb>
<xServ>CONSULTAR</xServ>
<chNFe>{{ obj.chave_nfe }}</chNFe>

2
pytrustnfe/nfe/templates/NfeInutilizacao.xml

@ -1,4 +1,4 @@
<inutNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="3.10">
<inutNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="4.00">
<infInut Id="{{ obj.id }}">
<tpAmb>{{ obj.ambiente }}</tpAmb>
<xServ>INUTILIZAR</xServ>

2
pytrustnfe/nfe/templates/NfeRetAutorizacao.xml

@ -1,4 +1,4 @@
<consReciNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="3.10">
<consReciNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="4.00">
<tpAmb>{{ obj.ambiente }}</tpAmb>
<nRec>{{ obj.numero_recibo }}</nRec>
</consReciNFe>

2
pytrustnfe/nfe/templates/NfeStatusServico.xml

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<consStatServ xmlns="http://www.portalfiscal.inf.br/nfe" versao="3.10">
<consStatServ xmlns="http://www.portalfiscal.inf.br/nfe" versao="4.00">
<tpAmb>{{ obj.ambiente }}</tpAmb>
<cUF>{{ obj.estado }}</cUF>
<xServ>STATUS</xServ>

6
pytrustnfe/nfe/templates/RecepcaoEventoCancelamento.xml → pytrustnfe/nfe/templates/RecepcaoEvento.xml

@ -8,13 +8,15 @@
<CNPJ>{{ evento.CNPJ }}</CNPJ>
<chNFe>{{ evento.chNFe }}</chNFe>
<dhEvento>{{ evento.dhEvento }}</dhEvento>
<tpEvento>110111</tpEvento>
<tpEvento>{{ evento.tpEvento }}</tpEvento>
<nSeqEvento>{{ evento.nSeqEvento }}</nSeqEvento>
<verEvento>1.00</verEvento>
<detEvento versao="1.00">
<descEvento>Cancelamento</descEvento>
<descEvento>{{ evento.descEvento }}</descEvento>
<nProt>{{ evento.nProt }}</nProt>
<xJust>{{ evento.xJust|normalize|escape }}</xJust>
<xCorrecao>{{ evento.xCorrecao|normalize|escape }}</xCorrecao>
<xCondUso>{{ evento.xCondUso }}</xCondUso>
</detEvento>
</infEvento>
</evento>

21
pytrustnfe/nfe/templates/RecepcaoEventoCarta.xml

@ -1,21 +0,0 @@
<envEvento xmlns="http://www.portalfiscal.inf.br/nfe" versao="1.00">
<idLote>{{ idLote }}</idLote>
<evento xmlns="http://www.portalfiscal.inf.br/nfe" versao="1.00">
<infEvento Id="{{ Id }}">
<cOrgao>{{ cOrgao }}</cOrgao>
<tpAmb>{{ tpAmb }}</tpAmb>
<CNPJ>{{ CNPJ }}</CNPJ>
<CPF>{{ CPF }}</CPF>
<chNFe>{{ chNFe }}</chNFe>
<dhEvento>{{ dhEvento }}</dhEvento>
<tpEvento>{{ tpEvento }}</tpEvento>
<nSeqEvento>{{ nSeqEvento }}</nSeqEvento>
<verEvento>1.00</verEvento>
<detEvento versao="1.00">
<descEvento>Carta de Correcao</descEvento>
<xCorrecao>{{ xCorrecao|normalize|escape }}</xCorrecao>
<xCondUso>A Carta de Correcao e disciplinada pelo paragrafo 1o-A do art. 7o do Convenio S/N, de 15 de dezembro de 1970 e pode ser utilizada para regularizacao de erro ocorrido na emissao de documento fiscal, desde que o erro nao esteja relacionado com: I - as variaveis que determinam o valor do imposto tais como: base de calculo, aliquota, diferenca de preco, quantidade, valor da operacao ou da prestacao; II - a correcao de dados cadastrais que implique mudanca do remetente ou do destinatario; III - a data de emissao ou de saida.</xCondUso>
</detEvento>
</infEvento>
</evento>
</envEvento>

31
pytrustnfe/nfe/templates/RecepcaoEventoEPEC.xml

@ -1,31 +0,0 @@
<envEvento xmlns="http://www.portalfiscal.inf.br/nfe" versao="1.00">
<idLote>00106151340701</idLote>
<evento xmlns="http://www.portalfiscal.inf.br/nfe" versao="1.00">
<infEvento Id="ID1101403514081014278500019055001001061513407959995201">
<cOrgao>91</cOrgao>
<tpAmb>2</tpAmb>
<CNPJ>10142785000190</CNPJ>
<chNFe>35140810142785000190550010010615134079599952</chNFe>
<dhEvento>2014-08-07T04:52:51-03:00</dhEvento>
<tpEvento>110140</tpEvento>
<nSeqEvento>1</nSeqEvento>
<verEvento>1.00</verEvento>
<detEvento versao="1.00">
<descEvento>EPEC</descEvento>
<cOrgaoAutor>35</cOrgaoAutor>
<tpAutor>1</tpAutor>
<verAplic>1.26</verAplic>
<dhEmi>2014-08-07T00:00:00-03:00</dhEmi>
<tpNF>1</tpNF>
<IE>495171423115</IE>
<dest>
<UF>SP</UF>
<CPF>00000000191</CPF>
<vNF>86.00</vNF>
<vICMS>6.02</vICMS>
<vST>0</vST>
</dest>
</detEvento>
</infEvento>
</evento>
</envEvento>

2
pytrustnfe/nfe/templates/RecepcaoEventoManifesto.xml

@ -1,7 +1,7 @@
<envEvento xmlns="http://www.portalfiscal.inf.br/nfe" versao="1.00">
<idLote>{{ lote }}</idLote>
<evento xmlns="http://www.portalfiscal.inf.br/nfe" versao="1.00">
<infEvento Id="{{ manifesto.identificador }}">
<infEvento Id="{{ evento.Id }}">
<cOrgao>91</cOrgao>
<tpAmb>{{ ambiente }}</tpAmb>
<CNPJ>{{ manifesto.cnpj_empresa }}</CNPJ>

18
pytrustnfe/nfse/bh/__init__.py

@ -2,14 +2,14 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import os
from lxml import etree
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
from pytrustnfe.nfse.bh.assinatura import Assinatura
def _render(certificado, method, **kwargs):
@ -18,12 +18,14 @@ def _render(certificado, method, **kwargs):
reference = ''
if method == 'GerarNfse':
reference = 'r%s' % kwargs['rps']['numero']
reference = 'rps:%s' % kwargs['rps']['numero']
ref_lote = 'lote%s' % kwargs['rps']['numero_lote']
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)
xml_send = signer.assina_xml(etree.fromstring(xml_send), ref_lote)
return xml_send.encode('utf-8')
@ -35,7 +37,9 @@ def _send(certificado, method, **kwargs):
base_url = 'https://bhisshomologa.pbh.gov.br/bhiss-ws/nfse?wsdl'
xml_send = kwargs["xml"].decode('utf-8')
xml_cabecalho = ''
xml_cabecalho = '<?xml version="1.0" encoding="UTF-8"?>\
<cabecalho xmlns="http://www.abrasf.org.br/nfse.xsd" versao="1.00">\
<versaoDados>1.00</versaoDados></cabecalho>'
cert, key = extract_cert_and_key_from_pfx(
certificado.pfx, certificado.password)
@ -50,10 +54,10 @@ def _send(certificado, method, **kwargs):
response = client.service[method](xml_cabecalho, xml_send)
response, obj = sanitize_response(response)
response, obj = sanitize_response(response.encode('utf-8'))
return {
'sent_xml': str(xml_send),
'received_xml': str(response),
'sent_xml': xml_send,
'received_xml': response.decode('utf-8'),
'object': obj
}

44
pytrustnfe/nfse/bh/assinatura.py

@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
# © 2016 Danimar Ribeiro, Trustcode
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import signxml
from lxml import etree
from pytrustnfe.certificado import extract_cert_and_key_from_pfx
from signxml import XMLSigner
class Assinatura(object):
def __init__(self, arquivo, senha):
self.arquivo = arquivo
self.senha = senha
def assina_xml(self, xml_element, reference):
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=signxml.methods.enveloped, signature_algorithm="rsa-sha1",
digest_algorithm='sha1',
c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
ns = {}
ns[None] = signer.namespaces['ds']
signer.namespaces = ns
ref_uri = ('#%s' % reference) if reference else None
signed_root = signer.sign(
xml_element, key=key.encode(), cert=cert.encode(),
reference_uri=ref_uri)
if reference:
element_signed = signed_root.find(".//*[@Id='%s']" % reference)
signature = signed_root.find(".//*[@URI='#%s']" % reference).getparent().getparent()
if element_signed is not None and signature is not None:
parent = element_signed.getparent()
parent.append(signature)
return etree.tostring(signed_root, encoding=str)

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

@ -1,8 +1,8 @@
<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>
<LoteRps Id="lote{{ rps.numero_lote }}" versao="1.00">
<NumeroLote>{{ rps.numero_lote }}</NumeroLote>
<Cnpj>{{ rps.prestador.cnpj }}</Cnpj>
<InscricaoMunicipal>{{ rps.prestador.inscricao_municipal }}</InscricaoMunicipal>
<QuantidadeRps>1</QuantidadeRps>
<ListaRps xmlns="http://www.abrasf.org.br/nfse.xsd">
{% include 'Rps.xml' %}

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

@ -1,5 +1,5 @@
<Rps>
<InfRps xmlns="http://www.abrasf.org.br/ABRASF/arquivos/nfse.xsd" Id="r{{ rps.numero }}">
<InfRps xmlns="http://www.abrasf.org.br/nfse.xsd" Id="rps:{{ rps.numero }}">
<IdentificacaoRps>
<Numero>{{ rps.numero }}</Numero>
<Serie>{{ rps.serie }}</Serie>

31
pytrustnfe/nfse/ginfes/__init__.py

@ -3,9 +3,12 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import os
import suds
from requests import Session
from zeep import Client
from zeep.transports import Transport
from requests.packages.urllib3 import disable_warnings
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.nfe.assinatura import Assinatura
@ -33,19 +36,21 @@ def _send(certificado, method, **kwargs):
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:
xml_send = kwargs['xml']
header = '<ns2:cabecalho xmlns:ns2="http://www.ginfes.com.br/cabecalho_v03.xsd" versao="3"><versaoDados>3</versaoDados></ns2:cabecalho>' #noqa
response = getattr(client.service, method)(header, xml_send)
except suds.WebFault as e:
return {
'sent_xml': xml_send,
'received_xml': e.fault.faultstring,
'object': None
}
response, obj = sanitize_response(response)
disable_warnings()
session = Session()
session.cert = (cert, key)
session.verify = False
transport = Transport(session=session)
client = Client(base_url, transport=transport)
xml_send = kwargs['xml']
response = client.service[method](header, xml_send)
response, obj = sanitize_response(response.encode('utf-8'))
return {
'sent_xml': xml_send,
'received_xml': response,

75
pytrustnfe/nfse/mga/__init__.py

@ -0,0 +1,75 @@
# © 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.nfse.mga.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 = 'rps:%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://isse.maringa.pr.gov.br/ws/?wsdl'
else:
base_url = 'https://isseteste.maringa.pr.gov.br/ws/?wsdl'
xml_send = kwargs["xml"].decode('utf-8')
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_send)
response, obj = sanitize_response(response.encode('utf-8'))
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)

45
pytrustnfe/nfse/mga/assinatura.py

@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
# © 2016 Danimar Ribeiro, Trustcode
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import signxml
from lxml import etree
from pytrustnfe.certificado import extract_cert_and_key_from_pfx
from signxml import XMLSigner
class Assinatura(object):
def __init__(self, arquivo, senha):
self.arquivo = arquivo
self.senha = senha
def assina_xml(self, xml_element, reference):
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=signxml.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_to_be_signed = xml_element.getchildren()[0].getchildren()[0]
signed_root = signer.sign(
element_to_be_signed, key=key.encode(), cert=cert.encode())
if reference:
element_signed = signed_root.find(".//*[@Id='%s']" % reference)
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)

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

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

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

@ -0,0 +1,3 @@
<GerarNfseEnvio xmlns="http://www.abrasf.org.br/nfse.xsd">
{% include 'Rps.xml' %}
</GerarNfseEnvio>

81
pytrustnfe/nfse/mga/templates/Rps.xml

@ -0,0 +1,81 @@
<Rps>
<InfDeclaracaoPrestacaoServico>
<Rps Id="rps:{{ rps.numero }}">
<IdentificacaoRps>
<Numero>{{ rps.numero }}</Numero>
<Serie>{{ rps.serie }}</Serie>
<Tipo>{{ rps.tipo_rps }}</Tipo>
</IdentificacaoRps>
<DataEmissao>{{ rps.data_emissao }}</DataEmissao>
<Status>{{ rps.status }}</Status>
</Rps>
<Competencia>{{ rps.data_emissao }}</Competencia>
<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>
<OutrasRetencoes>{{ rps.outras_retencoes }}</OutrasRetencoes>
<ValorIss>{{ rps.valor_iss }}</ValorIss>
<Aliquota>{{ rps.aliquota_issqn }}</Aliquota>
<DescontoIncondicionado>{{ rps.desconto_incondicionado }}</DescontoIncondicionado>
<DescontoCondicionado>{{ rps.desconto_condicionado }}</DescontoCondicionado>
</Valores>
<IssRetido>{{ rps.iss_retido }}</IssRetido>
<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>
<CodigoPais>{{ rps.codigo_pais }}</CodigoPais>
<ExigibilidadeISS>{{ rps.exigibilidade_iss}}</ExigibilidadeISS>
</Servico>
<Prestador>
<CpfCnpj>
<Cnpj>{{ rps.prestador.cnpj }}</Cnpj>
</CpfCnpj>
<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>
<CodigoPais>{{ rps.tomador.codigo_pais }}</CodigoPais>
<Cep>{{ rps.tomador.cep }}</Cep>
</Endereco>
<Contato>
<Telefone>{{ rps.tomador.telefone }}</Telefone>
<Email>{{ rps.tomador.email }}</Email>
</Contato>
</Tomador>
{% if rps.construcao_civil is defined -%}
<ContrucaoCivil>
<CodigoObra>{{ rps.construcao_civil.codigo_obra }}</CodigoObra>
<Art>{{ rps.construcao_civil.art }}</Art>
</ContrucaoCivil>
{% endif %}
<RegimeEspecialTributacao>{{ rps.regime_tributacao }}</RegimeEspecialTributacao>
<OptanteSimplesNacional>{{ rps.optante_simples }}</OptanteSimplesNacional>
<IncentivoFiscal>{{ rps.incentivador_cultural }}</IncentivoFiscal>
</InfDeclaracaoPrestacaoServico>
</Rps>

4
pytrustnfe/nfse/paulistana/__init__.py

@ -54,10 +54,10 @@ def _send(certificado, method, **kwargs):
'object': None
}
response, obj = sanitize_response(response.encode('utf-8'))
response, obj = sanitize_response(response)
return {
'sent_xml': xml_send,
'received_xml': response.decode(),
'received_xml': response,
'object': obj
}

11
pytrustnfe/utils.py

@ -8,15 +8,6 @@ from datetime import date, datetime
import lxml.etree as ET
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', '')
class ChaveNFe(object):
def __init__(self, **kwargs):
@ -85,7 +76,7 @@ def _find_node(xml, node):
def gerar_nfeproc(envio, recibo):
NSMAP = {None: 'http://www.portalfiscal.inf.br/nfe'}
root = ET.Element("nfeProc", versao="3.10", nsmap=NSMAP)
root = ET.Element("nfeProc", versao="4.00", nsmap=NSMAP)
parser = ET.XMLParser(encoding='utf-8')
docEnvio = ET.fromstring(envio.encode('utf-8'), parser=parser)
docRecibo = ET.fromstring(recibo.encode('utf-8'), parser=parser)

15
pytrustnfe/xml/__init__.py

@ -15,18 +15,6 @@ def recursively_empty(e):
return all((recursively_empty(c) for c in e.iterchildren()))
def recursively_normalize(vals):
for item in vals:
if type(vals[item]) is str:
vals[item] = vals[item].strip()
elif type(vals[item]) is dict:
recursively_normalize(vals[item])
elif type(vals[item]) is list:
for a in vals[item]:
recursively_normalize(a)
return vals
def render_xml(path, template_name, remove_empty, **nfe):
nfe = recursively_normalize(nfe)
env = Environment(
@ -58,7 +46,8 @@ def render_xml(path, template_name, remove_empty, **nfe):
def sanitize_response(response):
tree = etree.fromstring(response)
parser = etree.XMLParser(encoding='utf-8')
tree = etree.fromstring(response.encode('UTF-8'), parser=parser)
# Remove namespaces inuteis na resposta
for elem in tree.getiterator():
if not hasattr(elem.tag, 'find'):

2
pytrustnfe/xml/schemas/enviNFe_v3.10.xsd → pytrustnfe/xml/schemas/enviNFe_v4.00.xsd

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.portalfiscal.inf.br/nfe" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" targetNamespace="http://www.portalfiscal.inf.br/nfe" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:include schemaLocation="leiauteNFe_v3.10.xsd"/>
<xs:include schemaLocation="leiauteNFe_v4.00.xsd"/>
<xs:element name="enviNFe" type="TEnviNFe">
<xs:annotation>
<xs:documentation>Schema XML de validação do Pedido de Concessão de Autorização da Nota Fiscal Eletrônica</xs:documentation>

1104
pytrustnfe/xml/schemas/leiauteNFe_v4.00.xsd
File diff suppressed because it is too large
View File

2
pytrustnfe/xml/schemas/nfe_v3.10.xsd → pytrustnfe/xml/schemas/nfe_v4.00.xsd

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.portalfiscal.inf.br/nfe" targetNamespace="http://www.portalfiscal.inf.br/nfe" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:include schemaLocation="leiauteNFe_v3.10.xsd"/>
<xs:include schemaLocation="leiauteNFe_v4.00.xsd"/>
<xs:element name="NFe" type="TNFe">
<xs:annotation>
<xs:documentation>Nota Fiscal Eletrônica</xs:documentation>

22
pytrustnfe/xml/schemas/tiposBasico_v3.10.xsd → pytrustnfe/xml/schemas/tiposBasico_v4.00.xsd

@ -135,6 +135,15 @@
<xs:pattern value="[0-9]{3,11}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TDec_0104v">
<xs:annotation>
<xs:documentation>Tipo Decimal com até 1 dígitos inteiros, podendo ter de 1 até 4 decimais</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:pattern value="0|0\.[0-9]{1,4}|[1-9]{1}(\.[0-9]{1,4})?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TDec_0204v">
<xs:annotation>
<xs:documentation>Tipo Decimal com até 2 dígitos inteiros, podendo ter de 1 até 4 decimais</xs:documentation>
@ -171,13 +180,22 @@
<xs:pattern value="0(\.[0-9]{2})?|100(\.00)?|[1-9]{1}[0-9]{0,1}(\.[0-9]{2})?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TDec_0304Max100">
<xs:annotation>
<xs:documentation>Tipo Decimal com 3 inteiros (no máximo 100), com 4 decimais</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:pattern value="0(\.[0-9]{4})?|100(\.00)?|[1-9]{1}[0-9]{0,1}(\.[0-9]{4})?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TDec_0302a04Max100">
<xs:annotation>
<xs:documentation>Tipo Decimal com 3 inteiros (no máximo 100), com até 4 decimais</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:pattern value="[1-9]{1}(\.[0-9]{2,4})?|[1-9]{1}[0-9]{1}(\.[0-9]{2,4})?|100(\.0{2,4})?"/>
<xs:pattern value="0(\.[0-9]{2,4})?|[1-9]{1}[0-9]{0,1}(\.[0-9]{2,4})?|100(\.0{2,4})?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TDec_0803v">
@ -494,7 +512,7 @@
</xs:annotation>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:pattern value="[!-ÿ]{1}[ -ÿ]{0,}[!-ÿ]{1}|[!-ÿ]{1}|[!-ÿ]{2}"/>
<xs:pattern value="[!-ÿ]{1}[ -ÿ]{0,}[!-ÿ]{1}|[!-ÿ]{1}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TData">

2
pytrustnfe/xml/validate.py

@ -7,7 +7,7 @@ import os
from lxml import etree
PATH = os.path.dirname(os.path.abspath(__file__))
SCHEMA = os.path.join(PATH, 'schemas/enviNFe_v3.10.xsd')
SCHEMA = os.path.join(PATH, 'schemas/enviNFe_v4.00.xsd')
def valida_nfe(xml_nfe):

1
requirements.txt

@ -15,3 +15,4 @@ reportlab
pytest
pytest-cov
pytz
zeep

5
setup.py

@ -2,7 +2,7 @@
from setuptools import setup, find_packages
VERSION = "0.9.20"
VERSION = "0.10.4"
setup(
@ -37,6 +37,8 @@ later (LGPLv2+)',
'nfse/imperial/templates/*xml',
'nfse/floripa/templates/*xml',
'nfse/carioca/templates/*xml',
'nfse/bh/templates/*xml',
'nfse/mga/templates/*xml',
'xml/schemas/*xsd',
]},
url='https://github.com/danimaribeiro/PyTrustNFe',
@ -52,6 +54,7 @@ later (LGPLv2+)',
'suds-jurko-requests >= 1.2',
'reportlab',
'pytz',
'zeep',
],
tests_require=[
'pytest',

20
tests/test_comunicacao.py

@ -1,20 +0,0 @@
# coding=utf-8
'''
Created on Jun 16, 2015
@author: danimar
'''
import unittest
import os.path
XML_RETORNO = '<retEnviNFe><cStat>103</cStat>' \
'<cUF>42</cUF></retEnviNFe>'
class test_comunicacao(unittest.TestCase):
caminho = os.path.dirname(__file__)
def test_envio_nfe(self):
pass

19
tests/test_consulta_cadastro.py

@ -1,19 +0,0 @@
# coding=utf-8
import mock
import os.path
import unittest
from pytrustnfe.certificado import Certificado
from pytrustnfe.nfe import consulta_cadastro
class test_consulta_cadastro(unittest.TestCase):
caminho = os.path.dirname(__file__)
def test_conta_de_cadastro(self):
pfx_source = open(os.path.join(self.caminho, 'teste.pfx'), 'rb').read()
pfx = Certificado(pfx_source, '123456')
obj = {'cnpj': '12345678901234', 'estado': '42'}
consulta_cadastro(pfx, obj=obj, ambiente=1, estado='42')

12
tests/test_servidores.py

@ -7,22 +7,22 @@ Created on Jun 14, 2015
import unittest
from pytrustnfe.Servidores import localizar_url, localizar_qrcode
url_ba = 'https://nfe.sefaz.ba.gov.br/webservices/NfeAutorizacao/NfeAutoriza\
cao.asmx'
url_ba = 'https://nfe.sefaz.ba.gov.br/webservices/NFeAutorizacao4/NFeAutoriza\
cao4.asmx?wsdl'
url_sp = 'https://nfe.fazenda.sp.gov.br/ws/nfeautorizacao.asmx'
url_sp = 'https://nfe.fazenda.sp.gov.br/ws/nfeautorizacao4.asmx?wsdl'
url_qrcode_homologacao_sp = 'https://homologacao.nfce.fazenda.sp.gov.br/NFCEConsultaPublica/Paginas/ConstultaQRCode.aspx'
url_sc = 'https://nfe.svrs.rs.gov.br/ws/NfeAutorizacao/NfeAutorizacao.asmx'
url_sc = 'https://nfe.svrs.rs.gov.br/ws/NfeAutorizacao/NFeAutorizacao4.asmx?wsdl'
url_rs = 'https://nfe.sefazrs.rs.gov.br/ws/NfeAutorizacao/NFeAutorizacao.asmx'
url_cad_rs = 'https://cad.sefazrs.rs.gov.br/ws/cadconsultacadastro/cadcon\
sultacadastro2.asmx'
url_cad_sc = 'https://cad.svrs.rs.gov.br/ws/CadConsultaCadastro/CadConsult\
aCadastro2.asmx'
url_cad_sc = 'https://cad.svrs.rs.gov.br/ws/cadconsultacadastro/cadconsulta\
cadastro2.asmx?wsdl'
class test_servidores(unittest.TestCase):

8
tests/test_utils.py

@ -8,7 +8,7 @@ import unittest
import datetime
from pytrustnfe.utils import date_tostring, datetime_tostring, \
gerar_chave
from pytrustnfe.utils import ChaveNFe, CabecalhoSoap
from pytrustnfe.utils import ChaveNFe
class test_utils(unittest.TestCase):
@ -18,12 +18,6 @@ class test_utils(unittest.TestCase):
'tipo': 0, 'codigo': '26730161'
}
def test_cabecalho_soap(self):
head = CabecalhoSoap(versao=1, estado='SC', soap_action='Autorizacao')
self.assertEqual(head.versao, 1)
self.assertEqual(head.estado, 'SC')
self.assertEqual(head.soap_action, 'Autorizacao')
def test_date_tostring(self):
hoje = datetime.date.today()
data = date_tostring(hoje)

Loading…
Cancel
Save