Browse Source

Remoção de .tostring na construção do soap

pull/1/head
Junior Tada 11 years ago
parent
commit
223fd7bc3c
  1. 2
      pynfe/entidades/certificado.py
  2. 2
      pynfe/processamento/assinatura.py
  3. 82
      pynfe/processamento/comunicacao.py
  4. 2
      pynfe/utils/flags.py

2
pynfe/entidades/certificado.py

@ -27,7 +27,7 @@ class CertificadoA1(Certificado):
def __init__(self, caminho_arquivo=None): def __init__(self, caminho_arquivo=None):
self.caminho_arquivo = caminho_arquivo self.caminho_arquivo = caminho_arquivo
def separar_arquivo(self, senha, caminho_chave=None, caminho_cert=None):
def separar_arquivo(self, senha):
"""Separa o arquivo de certificado em dois: de chave e de certificado, """Separa o arquivo de certificado em dois: de chave e de certificado,
e retorna a string.""" e retorna a string."""

2
pynfe/processamento/assinatura.py

@ -28,7 +28,7 @@ class AssinaturaA1(Assinatura):
def assinar(self, xml, retona_string=True): def assinar(self, xml, retona_string=True):
arquivo_cert = CertificadoA1(self.certificado) arquivo_cert = CertificadoA1(self.certificado)
chave, cert = arquivo_cert.separar_arquivo(self.senha)
chave, cert = arquivo_cert.separar_arquivo(self.senha, caminho=True)
#root = etree.parse(xml).getroot() # caminho #root = etree.parse(xml).getroot() # caminho
root = etree.fromstring(xml) # string root = etree.fromstring(xml) # string

82
pynfe/processamento/comunicacao.py

@ -6,6 +6,7 @@ from pynfe.utils import etree, so_numeros
from pynfe.utils.flags import NAMESPACE_NFE, NAMESPACE_SOAP, NAMESPACE_XSI, NAMESPACE_XSD, NAMESPACE_METODO, VERSAO_PADRAO, CODIGOS_ESTADOS from pynfe.utils.flags import NAMESPACE_NFE, NAMESPACE_SOAP, NAMESPACE_XSI, NAMESPACE_XSD, NAMESPACE_METODO, VERSAO_PADRAO, CODIGOS_ESTADOS
from pynfe.utils.webservices import NFCE, NFE from pynfe.utils.webservices import NFCE, NFE
from .assinatura import AssinaturaA1 from .assinatura import AssinaturaA1
from pynfe.entidades.certificado import CertificadoA1
class Comunicacao(object): class Comunicacao(object):
u"""Classe abstrata responsavel por definir os metodos e logica das classes u"""Classe abstrata responsavel por definir os metodos e logica das classes
@ -15,6 +16,7 @@ class Comunicacao(object):
uf = None uf = None
certificado = None certificado = None
certificado_senha = None certificado_senha = None
url = None
def __init__(self, uf, certificado, certificado_senha, homologacao=False): def __init__(self, uf, certificado, certificado_senha, homologacao=False):
self.uf = uf self.uf = uf
@ -31,21 +33,17 @@ class ComunicacaoSefaz(Comunicacao):
def autorizacao(self, modelo, nota_fiscal): def autorizacao(self, modelo, nota_fiscal):
# url do serviço # url do serviço
url = self._get_url(modelo=modelo, consulta='AUTORIZACAO') url = self._get_url(modelo=modelo, consulta='AUTORIZACAO')
parser = etree.XMLParser(remove_blank_text=True)
# Monta XML do corpo da requisição # Monta XML do corpo da requisição
raiz = etree.Element('enviNFe', versao=VERSAO_PADRAO) raiz = etree.Element('enviNFe', versao=VERSAO_PADRAO)
#etree.SubElement(raiz, 'versao').text = self._versao #etree.SubElement(raiz, 'versao').text = self._versao
etree.SubElement(raiz, 'idLote').text = str(1) # numero autoincremental gerado pelo sistema etree.SubElement(raiz, 'idLote').text = str(1) # numero autoincremental gerado pelo sistema
etree.SubElement(raiz, 'indSinc').text = str(1) # 0 para assincrono, 1 para sincrono etree.SubElement(raiz, 'indSinc').text = str(1) # 0 para assincrono, 1 para sincrono
#etree.SubElement(raiz, 'NFe').text = nota_fiscal # conjunto de nfe tramistidas (max 50) #etree.SubElement(raiz, 'NFe').text = nota_fiscal # conjunto de nfe tramistidas (max 50)
raiz.append(etree.fromstring(nota_fiscal))
elem = etree.XML(etree.tostring(raiz, encoding='unicode'), parser=parser)
dados = etree.tostring(elem, encoding="unicode") # BUG < retorna caracteres ASCII
raiz.append(nota_fiscal)
# Monta XML para envio da requisição # Monta XML para envio da requisição
xml = self._construir_xml_status_pr(cabecalho=self._cabecalho_soap(metodo='NfeAutorizacao'), metodo='NfeAutorizacao', dados=dados)
xml = str(xml).replace('lt;','<').replace('gt;','>').replace('&','').replace('ds:','').replace('\\\'','"').replace('\\n','')
print (xml)
#return self._post(url, xml)
xml = self._construir_xml_status_pr(cabecalho=self._cabecalho_soap(metodo='NfeAutorizacao'), metodo='NfeAutorizacao', dados=raiz)
#print (xml)
return self._post(url, xml)
def cancelar(self, modelo, xml): def cancelar(self, modelo, xml):
""" Envia um evento de cancelamento de nota fiscal """ """ Envia um evento de cancelamento de nota fiscal """
@ -74,7 +72,7 @@ class ComunicacaoSefaz(Comunicacao):
def status_servico(self, modelo): def status_servico(self, modelo):
""" Verifica status do servidor da receita. """ """ Verifica status do servidor da receita. """
""" tipo é a string com tipo de serviço que deseja consultar
""" modelo é a string com tipo de serviço que deseja consultar
Ex: nfe ou nfce Ex: nfe ou nfce
""" """
url = self._get_url(modelo=modelo, consulta='STATUS') url = self._get_url(modelo=modelo, consulta='STATUS')
@ -84,15 +82,9 @@ class ComunicacaoSefaz(Comunicacao):
etree.SubElement(raiz, 'tpAmb').text = str(self._ambiente) etree.SubElement(raiz, 'tpAmb').text = str(self._ambiente)
etree.SubElement(raiz, 'cUF').text = CODIGOS_ESTADOS[self.uf.upper()] etree.SubElement(raiz, 'cUF').text = CODIGOS_ESTADOS[self.uf.upper()]
etree.SubElement(raiz, 'xServ').text = 'STATUS' etree.SubElement(raiz, 'xServ').text = 'STATUS'
dados = etree.tostring(raiz, encoding="utf-8").decode('utf-8')
# Monta XML para envio da requisição # Monta XML para envio da requisição
if self.uf.upper() == 'PR':
xml = self._construir_xml_status_pr(cabecalho=self._cabecalho_soap(metodo='NfeStatusServico3'), metodo='NfeStatusServico3', dados=dados)
else:
xml = self._construir_xml_soap(cabecalho=self._cabecalho_soap(metodo='NfeStatusServico3'), metodo='NfeStatusServico3', dados=dados)
xml = str(xml).replace('&lt;', '<').replace('&gt;', '>').replace('\\\'', '"').replace('\\n', '')
xml = self._construir_xml_status_pr(cabecalho=self._cabecalho_soap(metodo='NfeStatusServico2'), metodo='NfeStatusServico2', dados=raiz)
# Chama método que efetua a requisição POST no servidor SOAP # Chama método que efetua a requisição POST no servidor SOAP
#print (xml)
return self._post(url, xml) return self._post(url, xml)
def consultar_cadastro(self, instancia): def consultar_cadastro(self, instancia):
@ -162,23 +154,22 @@ class ComunicacaoSefaz(Comunicacao):
ambiente = 'https://homologacao.' ambiente = 'https://homologacao.'
if modelo == 'nfe': if modelo == 'nfe':
# nfe Ex: https://nfe.fazenda.pr.gov.br/nfe/NFeStatusServico3 # nfe Ex: https://nfe.fazenda.pr.gov.br/nfe/NFeStatusServico3
url = ambiente + NFE[self.uf.upper()][consulta]
self.url = ambiente + NFE[self.uf.upper()][consulta]
elif modelo == 'nfce': elif modelo == 'nfce':
# nfce Ex: https://homologacao.nfce.fazenda.pr.gov.br/nfce/NFeStatusServico3 # nfce Ex: https://homologacao.nfce.fazenda.pr.gov.br/nfce/NFeStatusServico3
url = ambiente + NFCE[self.uf.upper()][consulta]
self.url = ambiente + NFCE[self.uf.upper()][consulta]
else: else:
# TODO implementar outros tipos de notas como NFS-e # TODO implementar outros tipos de notas como NFS-e
pass pass
return url
return self.url
def _cabecalho_soap(self, metodo): def _cabecalho_soap(self, metodo):
u"""Monta o XML do cabeçalho da requisição SOAP""" u"""Monta o XML do cabeçalho da requisição SOAP"""
raiz = etree.Element('nfeCabecMsg', xmlns=NAMESPACE_METODO+metodo)
raiz = etree.Element('nfeCabecMsg')
etree.SubElement(raiz, 'cUF').text = CODIGOS_ESTADOS[self.uf.upper()] etree.SubElement(raiz, 'cUF').text = CODIGOS_ESTADOS[self.uf.upper()]
etree.SubElement(raiz, 'versaoDados').text = VERSAO_PADRAO etree.SubElement(raiz, 'versaoDados').text = VERSAO_PADRAO
return etree.tostring(raiz, encoding="unicode")
return raiz
def _construir_xml_soap(self, cabecalho, metodo, dados): def _construir_xml_soap(self, cabecalho, metodo, dados):
"""Mota o XML para o envio via SOAP""" """Mota o XML para o envio via SOAP"""
@ -186,54 +177,41 @@ class ComunicacaoSefaz(Comunicacao):
raiz = etree.Element('{%s}Envelope'%NAMESPACE_SOAP, nsmap={'xsi': NAMESPACE_XSI, 'xsd': NAMESPACE_XSD, 'soap12': NAMESPACE_SOAP}) raiz = etree.Element('{%s}Envelope'%NAMESPACE_SOAP, nsmap={'xsi': NAMESPACE_XSI, 'xsd': NAMESPACE_XSD, 'soap12': NAMESPACE_SOAP})
etree.SubElement(raiz, '{%s}Header'%NAMESPACE_SOAP).text = cabecalho etree.SubElement(raiz, '{%s}Header'%NAMESPACE_SOAP).text = cabecalho
body = etree.SubElement(raiz, '{%s}Body'%NAMESPACE_SOAP) body = etree.SubElement(raiz, '{%s}Body'%NAMESPACE_SOAP)
etree.SubElement(body, 'nfeDadosMsg', xmlns=NAMESPACE_METODO+metodo).text = dados
return etree.tostring(raiz, encoding="utf-8", xml_declaration=True)
etree.SubElement(body, 'nfeDadosMsg').text = dados
return raiz
def _construir_xml_status_pr(self, cabecalho, metodo, dados): def _construir_xml_status_pr(self, cabecalho, metodo, dados):
u"""Mota o XML para o envio via SOAP""" u"""Mota o XML para o envio via SOAP"""
raiz = etree.Element('{%s}Envelope'%NAMESPACE_SOAP, nsmap={'xsi': NAMESPACE_XSI, 'xsd': NAMESPACE_XSD, 'soap12': NAMESPACE_SOAP})
etree.SubElement(raiz, '{%s}Header'%NAMESPACE_SOAP).text = cabecalho
raiz = etree.Element('{%s}Envelope'%NAMESPACE_SOAP, nsmap={'soap': NAMESPACE_SOAP}, xmlns=NAMESPACE_METODO+metodo)
c = etree.SubElement(raiz, '{%s}Header'%NAMESPACE_SOAP)
c.append(cabecalho)
body = etree.SubElement(raiz, '{%s}Body'%NAMESPACE_SOAP) body = etree.SubElement(raiz, '{%s}Body'%NAMESPACE_SOAP)
etree.SubElement(body, 'nfeDadosMsg', xmlns=NAMESPACE_METODO+metodo).text = dados
return etree.tostring(raiz, encoding="utf-8", xml_declaration=True)
a = etree.SubElement(body, 'nfeDadosMsg', xmlns=NAMESPACE_METODO+metodo)
a.append(dados)
return raiz
def _post_header(self): def _post_header(self):
u"""Retorna um dicionário com os atributos para o cabeçalho da requisição HTTP""" u"""Retorna um dicionário com os atributos para o cabeçalho da requisição HTTP"""
return { return {
u'content-type': u'application/soap+xml; charset=utf-8',
#u'content-type': u'text/xml; charset=utf-8',
#u'Accept': u'text/xml; charset=utf-8',
u'Accept': u'application/soap+xml; charset=utf-8',
u'content-type': u'application/soap+xml; charset=utf-8;',
u'Accept': u'application/soap+xml; charset=utf-8;',
} }
def _post(self, url, xml): def _post(self, url, xml):
# Separa arquivos de certificado para chave e certificado (sozinho)
#caminho_chave, caminho_cert = self.certificado.separar_arquivo(senha=self.certificado_senha)
#caminho_chave = 'key.pem'
#caminho_cert = 'cert.pem'
caminho_chave = '/home/junior/Documentos/Certificados/key.pem'
caminho_cert = '/home/junior/Documentos/Certificados/cert.pem'
certificadoA1 = CertificadoA1(self.certificado)
chave, cert = certificadoA1.separar_arquivo(self.certificado_senha, caminho=True)
cert = (cert, chave)
# Abre a conexão HTTPS # Abre a conexão HTTPS
cert = (caminho_cert, caminho_chave)
#headers = {'content-type': 'text/xml'}
try: try:
print (url)
# Passa o lxml.etree para string
xml = etree.tostring(xml, encoding='unicode', pretty_print=False)
# Faz o request com o servidor
result = requests.post(url, xml, headers=self._post_header(), cert=cert, verify=False) result = requests.post(url, xml, headers=self._post_header(), cert=cert, verify=False)
print (result.content)
if result == 200: if result == 200:
result.encoding='utf-8' result.encoding='utf-8'
print (result)
print (result.content)
return result.text
return result
else: else:
return result return result
print (result)
print (result.content)
print (result.text)
except requests.exceptions.ConnectionError as e: except requests.exceptions.ConnectionError as e:
raise e raise e

2
pynfe/utils/flags.py

@ -5,7 +5,7 @@ NAMESPACE_SIG = 'http://www.w3.org/2000/09/xmldsig#'
NAMESPACE_SOAP = 'http://www.w3.org/2003/05/soap-envelope' NAMESPACE_SOAP = 'http://www.w3.org/2003/05/soap-envelope'
NAMESPACE_XSI = 'http://www.w3.org/2001/XMLSchema-instance' NAMESPACE_XSI = 'http://www.w3.org/2001/XMLSchema-instance'
NAMESPACE_XSD = 'http://www.w3.org/2001/XMLSchema' NAMESPACE_XSD = 'http://www.w3.org/2001/XMLSchema'
NAMESPACE_METODO = 'http://www.portalfiscal.inf.br/sce/wsdl/'
NAMESPACE_METODO = 'http://www.portalfiscal.inf.br/nfe/wsdl/'
VERSAO_PADRAO = '3.10' VERSAO_PADRAO = '3.10'

Loading…
Cancel
Save