Browse Source

ajuste xml soap

pull/1/head
Junior Tada 11 years ago
parent
commit
36c6843ce0
  1. 6
      pynfe/entidades/cliente.py
  2. 53
      pynfe/processamento/comunicacao.py
  3. 26
      pynfe/processamento/serializacao.py
  4. 3
      pynfe/utils/flags.py

6
pynfe/entidades/cliente.py

@ -17,9 +17,15 @@ class Cliente(Entidade):
# - Numero do Documento (obrigatorio)
numero_documento = str()
# - Indicador da IE do destinatário: 1 – Contribuinte ICMSpagamento à vista; 2 – Contribuinte isento de inscrição; 9 – Não Contribuinte
indicador_ie = int()
# - Inscricao Estadual
inscricao_estadual = str()
# - Inscricao Municial
inscricao_municipal = str()
# - Inscricao SUFRAMA
inscricao_suframa = str()

53
pynfe/processamento/comunicacao.py

@ -3,7 +3,7 @@ import datetime
import time
import requests
from pynfe.utils import etree, so_numeros
from pynfe.utils.flags import NAMESPACE_NFE, NAMESPACE_SOAP, 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 .assinatura import AssinaturaA1
@ -42,10 +42,10 @@ class ComunicacaoSefaz(Comunicacao):
elem = etree.XML(etree.tostring(raiz, encoding='unicode'), parser=parser)
dados = etree.tostring(elem, encoding="unicode") # BUG < retorna caracteres ASCII
# Monta XML para envio da requisição
xml = self._construir_xml_status_pr(cabecalho=self._cabecalho_soap(), dados=dados)
xml = str(xml).replace('lt;','<').replace('gt;','>').replace('&','').replace('ds:','')
#print (xml)
return self._post(url, xml)
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)
def cancelar(self, modelo, xml):
""" Envia um evento de cancelamento de nota fiscal """
@ -64,7 +64,7 @@ class ComunicacaoSefaz(Comunicacao):
etree.SubElement(evento, 'versao').text = '1' # versao do leiaute do evento (cancelamento = 1)
etree.SubElement(raiz, 'infEvento').text = xml # Evento, um lote pode conter até 20 eventos
dados = etree.tostring(raiz, encoding="unicode")
xml = self._construir_xml_status_pr(cabecalho=self._cabecalho_soap(), dados=dados, url=url)
xml = self._construir_xml_status_pr(cabecalho=self._cabecalho_soap(metodo='RecepcaoEvento'), metodo='RecepcaoEvento', dados=dados)
xml = str(xml).replace('&amp;','').replace('lt;','<').replace('gt;','>').replace('&','')
return xml
#return self._post(url, xml)
@ -87,11 +87,12 @@ class ComunicacaoSefaz(Comunicacao):
dados = etree.tostring(raiz, encoding="utf-8").decode('utf-8')
# Monta XML para envio da requisição
if self.uf.upper() == 'PR':
xml = self._construir_xml_status_pr(cabecalho=self._cabecalho_soap(), dados=dados)
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='nfeRecepcao2', tag_metodo='nfeStatusServicoNF2', dados=dados)
xml = str(xml).replace('&lt;', '<').replace('&gt;', '>').replace('\'', '"').replace('\n', '')
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', '')
# Chama método que efetua a requisição POST no servidor SOAP
#print (xml)
return self._post(url, xml)
def consultar_cadastro(self, instancia):
@ -100,6 +101,7 @@ class ComunicacaoSefaz(Comunicacao):
def inutilizar_faixa_numeracao(self, numero_inicial, numero_final, emitente, certificado, senha, ano=None, serie='1', justificativa=''):
post = '/nfeweb/services/nfestatusservico.asmx'
metodo = 'NfeInutilizacao2'
# Valores default
ano = str(ano or datetime.date.today().year)[-2:]
@ -169,39 +171,34 @@ class ComunicacaoSefaz(Comunicacao):
pass
return url
def _cabecalho_soap(self):
def _cabecalho_soap(self, metodo):
u"""Monta o XML do cabeçalho da requisição SOAP"""
raiz = etree.Element('nfeCabecMsg')
etree.SubElement(raiz, 'cUF').text = str(41)
raiz = etree.Element('nfeCabecMsg', xmlns=NAMESPACE_METODO+metodo)
etree.SubElement(raiz, 'cUF').text = CODIGOS_ESTADOS[self.uf.upper()]
etree.SubElement(raiz, 'versaoDados').text = VERSAO_PADRAO
return etree.tostring(raiz, encoding="unicode")
def _construir_xml_soap(self, cabecalho, metodo, tag_metodo, dados):
def _construir_xml_soap(self, cabecalho, metodo, dados):
"""Mota o XML para o envio via SOAP"""
raiz = etree.Element('{%s}Envelope'%NAMESPACE_SOAP, nsmap={'soap': 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
body = etree.SubElement(raiz, '{%s}Body'%NAMESPACE_SOAP)
met = etree.SubElement(
body, tag_metodo, xmlns=metodo,
)
etree.SubElement(met, 'nfeCabecMsg').text = cabecalho
etree.SubElement(met, 'nfeDadosMsg').text = dados
etree.SubElement(body, 'nfeDadosMsg', xmlns=NAMESPACE_METODO+metodo).text = dados
return etree.tostring(raiz, encoding="utf-8", xml_declaration=True)
def _construir_xml_status_pr(self, cabecalho, dados):
def _construir_xml_status_pr(self, cabecalho, metodo, dados):
u"""Mota o XML para o envio via SOAP"""
raiz = etree.Element('{%s}Envelope'%NAMESPACE_SOAP, nsmap={'soap': NAMESPACE_SOAP}, xmlns=NAMESPACE_NFE)
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
body = etree.SubElement(raiz, '{%s}Body'%NAMESPACE_SOAP)
etree.SubElement(body, 'nfeDadosMsg').text = dados
etree.SubElement(body, 'nfeDadosMsg', xmlns=NAMESPACE_METODO+metodo).text = dados
return etree.tostring(raiz, encoding='unicode')
return etree.tostring(raiz, encoding="utf-8", xml_declaration=True)
def _post_header(self):
u"""Retorna um dicionário com os atributos para o cabeçalho da requisição HTTP"""
@ -229,8 +226,14 @@ class ComunicacaoSefaz(Comunicacao):
result = requests.post(url, xml, headers=self._post_header(), cert=cert, verify=False)
print (result.content)
if result == 200:
result.encoding='utf-8'
print (result)
print (result.content)
return result.text
else:
return result
print (result)
print (result.content)
print (result.text)
except requests.exceptions.ConnectionError as e:
raise e

26
pynfe/processamento/serializacao.py

@ -105,10 +105,6 @@ class SerializacaoXML(Serializacao):
# Dados do cliente (distinatario)
etree.SubElement(raiz, cliente.tipo_documento).text = so_numeros(cliente.numero_documento)
etree.SubElement(raiz, 'xNome').text = cliente.razao_social
# nfc-e nao possui IE mesmo que seja uma empresa
if modelo == 55:
etree.SubElement(raiz, 'IE').text = cliente.inscricao_estadual
# Endereço
endereco = etree.SubElement(raiz, 'enderDest')
etree.SubElement(endereco, 'xLgr').text = cliente.endereco_logradouro
etree.SubElement(endereco, 'nro').text = cliente.endereco_numero
@ -122,7 +118,24 @@ class SerializacaoXML(Serializacao):
etree.SubElement(endereco, 'cPais').text = cliente.endereco_pais
etree.SubElement(endereco, 'xPais').text = obter_pais_por_codigo(cliente.endereco_pais)
etree.SubElement(endereco, 'fone').text = cliente.endereco_telefone
#Indicador da IE do destinatário: 1 – Contribuinte ICMSpagamento à vista; 2 – Contribuinte isento de inscrição; 9 – Não Contribuinte
if cliente.isento_icms or cliente.inscricao_estadual.upper() == 'ISENTO':
etree.SubElement(raiz, 'indIEDest').text = str(2)
etree.SubElement(raiz, 'IE').text = 'ISENTO'
elif cliente.indicador_ie == 9:
# 9 – Não Contribuinte
etree.SubElement(raiz, 'indIEDest').text = str(9)
else:
# Indicador da IE do destinatário: 1 – Contribuinte ICMSpagamento à vista;
etree.SubElement(raiz, 'indIEDest').text = cliente.indicador_ie
etree.SubElement(raiz, 'IE').text = cliente.inscricao_estadual
# Suframa
if cliente.inscricao_suframa:
etree.SubElement(raiz, 'ISUF').text = cliente.inscricao_suframa
# Inscrição Municipal do tomador do serviço
if cliente.inscricao_municipal:
etree.SubElement(raiz, 'IM').text = cliente.inscricao_municipal
etree.SubElement(raiz, 'email').text = cliente.email
if retorna_string:
return etree.tostring(raiz, encoding="unicode", pretty_print=True)
else:
@ -179,6 +192,9 @@ class SerializacaoXML(Serializacao):
etree.SubElement(prod, 'cProd').text = str(produto_servico.codigo)
etree.SubElement(prod, 'cEAN').text = produto_servico.ean
etree.SubElement(prod, 'xProd').text = produto_servico.descricao
etree.SubElement(prod, 'NCM').text = produto_servico.ncm
# Codificação opcional que detalha alguns NCM. Formato: duas letras maiúsculas e 4 algarismos. Se a mercadoria se enquadrar em mais de uma codificação, informar até 8 codificações principais.
#etree.SubElement(prod, 'NVE').text = ''
etree.SubElement(prod, 'CFOP').text = produto_servico.cfop
etree.SubElement(prod, 'uCom').text = produto_servico.unidade_comercial
etree.SubElement(prod, 'qCom').text = str(produto_servico.quantidade_comercial or 0)

3
pynfe/utils/flags.py

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

Loading…
Cancel
Save