Browse Source

serialização nfse ginfes final

pull/7/head
Leonardo Tada 10 years ago
parent
commit
1614ae69e7
  1. 3
      pynfe/entidades/notafiscal.py
  2. 40
      pynfe/processamento/assinatura.py
  3. 27
      pynfe/processamento/autorizador_nfse.py
  4. 41
      pynfe/processamento/comunicacao.py
  5. 9
      pynfe/utils/https_nfse.py
  6. 2
      pynfe/utils/nfse/ginfes/cabecalho_v03.py
  7. 5
      pynfe/utils/nfse/ginfes/servico_enviar_lote_rps_envio_v03.py

3
pynfe/entidades/notafiscal.py

@ -907,8 +907,6 @@ class NotaFiscalEntregaRetirada(Entidade):
class NotaFiscalServico(Entidade):
# Empresa que implementa o webservice
autorizador = str() # betha
# id do rps
identificador = str()
# tag competencia
@ -934,4 +932,3 @@ class NotaFiscalServico(Entidade):
def __str__(self):
return ' '.join([str(self.identificador)])

40
pynfe/processamento/assinatura.py

@ -171,7 +171,45 @@ class AssinaturaA1(Assinatura):
# Escreve no arquivo depois de remover caracteres especiais e parse string
with open('nfse.xml', 'w') as arquivo:
arquivo.write(remover_acentos(etree.tostring(xml, encoding="unicode", pretty_print=False).replace('ns1:', '').replace(':ns1', '')))
arquivo.write(remover_acentos(etree.tostring(xml, encoding="unicode", pretty_print=False).replace('ns1:', '').replace(':ns1', '').replace('\n','')))
subprocess.call(['xmlsec1', '--sign', '--pkcs12', self.certificado, '--pwd', self.senha, '--crypto', 'openssl', '--output', 'funfa.xml', '--id-attr:Id', tag, 'nfse.xml'])
xml = etree.parse('funfa.xml').getroot()
if retorna_string:
return etree.tostring(xml, encoding="unicode", pretty_print=False)
else:
return xml
except Exception as e:
raise e
def assinarConsulta(self, xml, retorna_string=False):
try:
xml = etree.fromstring(xml)
# No raiz do XML de saida
tag = 'ConsultarNfseEnvio' # tag que será assinada
raiz = etree.Element('Signature', xmlns='http://www.w3.org/2000/09/xmldsig#')
siginfo = etree.SubElement(raiz, 'SignedInfo')
etree.SubElement(siginfo, 'CanonicalizationMethod', Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
etree.SubElement(siginfo, 'SignatureMethod', Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1')
# Consulta nao tem id
ref = etree.SubElement(siginfo, 'Reference', URI='')
trans = etree.SubElement(ref, 'Transforms')
etree.SubElement(trans, 'Transform', Algorithm='http://www.w3.org/2000/09/xmldsig#enveloped-signature')
etree.SubElement(trans, 'Transform', Algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
etree.SubElement(ref, 'DigestMethod', Algorithm='http://www.w3.org/2000/09/xmldsig#sha1')
etree.SubElement(ref, 'DigestValue')
etree.SubElement(raiz, 'SignatureValue')
keyinfo = etree.SubElement(raiz, 'KeyInfo')
etree.SubElement(keyinfo, 'X509Data')
consulta = xml.xpath('/ConsultarNfseEnvio', namespaces={'ns1': 'http://www.ginfes.com.br/servico_consultar_nfse_envio_v03.xsd', 'ns2':'http://www.ginfes.com.br/tipos_v03.xsd'})[0]
consulta.append(raiz)
# Escreve no arquivo depois de remover caracteres especiais e parse string
with open('nfse.xml', 'w') as arquivo:
arquivo.write(remover_acentos(etree.tostring(xml, encoding="unicode", pretty_print=False).replace('\n','')))
subprocess.call(['xmlsec1', '--sign', '--pkcs12', self.certificado, '--pwd', self.senha, '--crypto', 'openssl', '--output', 'funfa.xml', '--id-attr:Id', tag, 'nfse.xml'])
xml = etree.parse('funfa.xml').getroot()

27
pynfe/processamento/autorizador_nfse.py

@ -1,12 +1,12 @@
import ipdb
from pyxb import BIND
from importlib import import_module
import pynfe.utils.nfse.ginfes.servico_enviar_lote_rps_envio_v03 as servico_enviar_lote_rps_envio_v03
import pynfe.utils.nfse.ginfes._tipos as _tipos
# import pynfe.utils.nfse.ginfes.servico_enviar_lote_rps_envio_v03 as servico_enviar_lote_rps_envio_v03
# import pynfe.utils.nfse.ginfes._tipos as _tipos
class InterfaceAutorizador():
#TODO Colocar raise Exception Not Implemented nos metodos
def consultar(self):
def consultar_rps(self):
pass
def cancelar(self):
@ -88,7 +88,7 @@ class SerializacaoBetha(InterfaceAutorizador):
return gnfse.toxml(element_name='GerarNfseEnvio')
def consultar(self, nfse):
def consultar_rps(self, nfse):
"""Retorna string de um XML gerado a partir do
XML Schema (XSD). Binding gerado pelo modulo PyXB."""
@ -243,11 +243,13 @@ class SerializacaoGinfes(InterfaceAutorizador):
def __init__(self):
# importa
global _tipos, servico_consultar_nfse_envio_v03
global servico_enviar_lote_rps_envio_v03, cabecalho_v03
_tipos = import_module('pynfe.utils.nfse.ginfes._tipos')
servico_consultar_nfse_envio_v03 = import_module('pynfe.utils.nfse.ginfes.servico_consultar_nfse_envio_v03')
servico_enviar_lote_rps_envio_v03 = import_module('pynfe.utils.nfse.ginfes.servico_enviar_lote_rps_envio_v03')
cabecalho_v03 = import_module('pynfe.utils.nfse.ginfes.cabecalho_v03')
def consultar(self, nfse):
def consultar_rps(self, nfse):
"""Retorna string de um XML de consulta por Rps gerado a partir do
XML Schema (XSD). Binding gerado pelo modulo PyXB."""
@ -335,11 +337,11 @@ class SerializacaoGinfes(InterfaceAutorizador):
# inf rps
inf_rps = _tipos.tcInfRps()
inf_rps.IdentificacaoRps = id_rps
inf_rps.DataEmissao = nfse.data_emissao.strftime('%Y-%m-%d')
inf_rps.NaturezaOperacao = 'venda' # TODO
inf_rps.DataEmissao = nfse.data_emissao.strftime('%Y-%m-%dT%H:%M:%S')
inf_rps.NaturezaOperacao = 1 # tributacao no municipio
inf_rps.RegimeEspecialTributacao = None # opcional
inf_rps.OptanteSimplesNacional = nfse.simples
inf_rps.IncentivadorCultural = 2 # TODO
inf_rps.IncentivadorCultural = 2 # Nao
inf_rps.Status = 1
inf_rps.RpsSubstituido = None # opcional
inf_rps.Servico = servico
@ -363,4 +365,11 @@ class SerializacaoGinfes(InterfaceAutorizador):
enviarLote = servico_enviar_lote_rps_envio_v03.EnviarLoteRpsEnvio()
enviarLote.LoteRps = lote
return enviarLote.toxml(element_name='EnviarLoteRpsEnvio')
return enviarLote.toxml("UTF-8", element_name='ns1:EnviarLoteRpsEnvio')
def cabecalho(self):
# info
cabecalho = cabecalho_v03.cabecalho()
cabecalho.versao = '3'
cabecalho.versaoDados = '3'
return cabecalho.toxml(element_name='cabecalho')

41
pynfe/processamento/comunicacao.py

@ -197,6 +197,23 @@ class ComunicacaoSefaz(Comunicacao):
# Chama método que efetua a requisição POST no servidor SOAP
return self._post(url, xml)
def download(self, cnpj, chave):
# url do serviço
url = self._get_url_AN(consulta='DOWNLOAD')
# Monta XML do corpo da requisição
raiz = etree.Element('downloadNFe', versao='1.00', xmlns=NAMESPACE_NFE)
etree.SubElement(raiz, 'versao').text = '1.00'
etree.SubElement(raiz, 'tpAmb').text = str(self._ambiente)
etree.SubElement(raiz, 'xServ').text = 'DOWNLOAD NFE'
etree.SubElement(raiz, 'CNPJ').text = str(cnpj)
etree.SubElement(raiz, 'chNFe').text = str(chave)
# Monta XML para envio da requisição
xml = self._construir_xml_status_pr(cabecalho=self._cabecalho_soap(metodo='NfeDownloadNF'), metodo='NfeDownloadNF', dados=raiz)
print (url)
#return xml
return self._post(url, xml)
def inutilizar_faixa_numeracao(self, numero_inicial, numero_final, emitente, certificado, senha, ano=None, serie='1', justificativa=''):
post = '/nfeweb/services/nfestatusservico.asmx'
metodo = 'NfeInutilizacao2'
@ -303,6 +320,8 @@ class ComunicacaoSefaz(Comunicacao):
etree.SubElement(raiz, 'versaoDados').text = '1.00'
elif metodo == 'NfeConsultaDest':
etree.SubElement(raiz, 'versaoDados').text = '1.01'
elif metodo == 'NfeDownloadNF':
etree.SubElement(raiz, 'versaoDados').text = '1.00'
else:
etree.SubElement(raiz, 'versaoDados').text = VERSAO_PADRAO
etree.SubElement(raiz, 'cUF').text = CODIGOS_ESTADOS[self.uf.upper()]
@ -381,10 +400,12 @@ class ComunicacaoNfse(Comunicacao):
def consulta(self, autorizador, xml):
if autorizador.upper() == 'GINFES':
self._namespace = 'http://www.ginfes.com.br/servico_consultar_nfse_envio_v03.xsd'
self._versao = '3.00'
self._namespace = 'http://www.ginfes.com.br/cabecalho_v03.xsd'
self._versao = '3'
# url do serviço
url = self._get_url(autorizador)
# xml
xml = '<?xml version="1.0" encoding="UTF-8"?>' + xml
# comunica via wsdl
return self._post_https(url, xml, 'consulta')
@ -420,7 +441,7 @@ class ComunicacaoNfse(Comunicacao):
def _cabecalho(self, retorna_string=True):
u"""Monta o XML do cabeçalho da requisição wsdl"""
xml_declaration='<?xml version="1.0" encoding="UTF-8"?>'
xml_declaration='<?xml version="1.0" encoding="utf-8"?>'
# cabecalho
raiz = etree.Element('cabecalho', xmlns=self._namespace, versao=self._versao)
@ -433,6 +454,11 @@ class ComunicacaoNfse(Comunicacao):
else:
return raiz
def _cabecalho_ginfes(self):
""" Retorna o XML do cabeçalho gerado pelo xsd"""
from pynfe.processamento.autorizador_nfse import SerializacaoGinfes
return SerializacaoGinfes().cabecalho()
def _get_url(self, autorizador):
""" Retorna a url para comunicação com o webservice """
if self._ambiente == 1:
@ -469,7 +495,8 @@ class ComunicacaoNfse(Comunicacao):
def _post_https(self, url, xml, metodo):
# cabecalho
cabecalho = self._cabecalho()
#cabecalho = self._cabecalho()
cabecalho = self._cabecalho_ginfes()
# comunicacao wsdl
try:
from suds.client import Client
@ -484,9 +511,11 @@ class ComunicacaoNfse(Comunicacao):
if metodo == 'gerar':
return cliente.service.GerarNfse(cabecalho, xml)
elif metodo == 'consulta':
return cliente.service.ConsultarNfsePorRps(cabecalho, xml)
import ipdb
ipdb.set_trace()
return cliente.service.ConsultarNfseV3(cabecalho, xml)
elif metodo == 'consultaRps':
return cliente.service.ConsultarNfsePorRps(cabecalho, xml)
return cliente.service.ConsultarNfsePorRpsV3(cabecalho, xml)
elif metodo == 'consultaFaixa':
return cliente.service.ConsultarNfseFaixa(cabecalho, xml)
elif metodo == 'cancelar':

9
pynfe/utils/https_nfse.py

@ -33,6 +33,9 @@ class HttpAuthenticated(HttpTransport):
self.cert = cert
self.endereco = endereco
def open(self, request):
opener = urllib.request.build_opener(HTTPSClientAuthHandler(self.key, self.cert))
return opener.open(self.endereco)
# def open(self, request):
# opener = urllib.request.build_opener(HTTPSClientAuthHandler(self.key, self.cert))
# return opener.open(self.endereco)
def u2handlers(self):
return [HTTPSClientAuthHandler(self.key, self.cert)]

2
pynfe/utils/nfse/ginfes/cabecalho_v03.py

@ -24,7 +24,7 @@ if pyxb.__version__ != _PyXBVersion:
raise pyxb.PyXBVersionError(_PyXBVersion)
# Import bindings for namespaces imported into schema
import _tipos as _ImportedBinding__tipos
from pynfe.utils.nfse.ginfes import _tipos as _ImportedBinding__tipos
import pyxb.binding.datatypes
# NOTE: All namespace declarations are reserved within the binding

5
pynfe/utils/nfse/ginfes/servico_enviar_lote_rps_envio_v03.py

@ -24,8 +24,8 @@ if pyxb.__version__ != _PyXBVersion:
raise pyxb.PyXBVersionError(_PyXBVersion)
# Import bindings for namespaces imported into schema
import _tipos as _ImportedBinding__tipos
import _dsig as _ImportedBinding__dsig
from pynfe.utils.nfse.ginfes import _tipos as _ImportedBinding__tipos
from pynfe.utils.nfse.ginfes import _dsig as _ImportedBinding__dsig
import pyxb.binding.datatypes
# NOTE: All namespace declarations are reserved within the binding
@ -150,4 +150,3 @@ def _BuildAutomaton ():
st_1._set_transitionSet(transitions)
return fac.Automaton(states, counters, False, containing_state=None)
CTD_ANON._Automaton = _BuildAutomaton()
Loading…
Cancel
Save