Browse Source

ajustes no schema xml

pull/1/head
Junior Tada 11 years ago
parent
commit
4745d63036
  1. 1
      pynfe/entidades/notafiscal.py
  2. 9
      pynfe/processamento/assinatura.py
  3. 53
      pynfe/processamento/comunicacao.py
  4. 22
      pynfe/processamento/serializacao.py
  5. 17
      pynfe/utils/webservices.py

1
pynfe/entidades/notafiscal.py

@ -382,6 +382,7 @@ class NotaFiscal(Entidade):
remainder = key_sum % 11
if remainder == 0 or remainder == 1:
self.dv_codigo_numerico_aleatorio = '0'
return '0'
self.dv_codigo_numerico_aleatorio = str(11 - remainder)
return str(self.dv_codigo_numerico_aleatorio)

9
pynfe/processamento/assinatura.py

@ -26,7 +26,7 @@ class AssinaturaA1(Assinatura):
"""Classe responsavel por efetuar a assinatura do certificado
digital no XML informado. Passar XML como string."""
def assinar(self, xml):
def assinar(self, xml, retona_string=True):
arquivo_cert = CertificadoA1(self.certificado)
chave, cert = arquivo_cert.separar_arquivo(self.senha)
@ -44,6 +44,7 @@ class AssinaturaA1(Assinatura):
#root.findall('.//{http://www.w3.org/2000/09/xmldsig#}Reference')[0] \
# .attrib['URI'] = '#chaveteste'
result = etree.tostring(root, encoding="unicode", pretty_print=True)
return result
if retona_string:
return etree.tostring(root, encoding="unicode", pretty_print=True)
else:
return root

53
pynfe/processamento/comunicacao.py

@ -31,19 +31,21 @@ class ComunicacaoSefaz(Comunicacao):
def autorizacao(self, modelo, nota_fiscal):
# url do serviço
url = self._get_url(modelo=modelo, consulta='AUTORIZACAO')
parser = etree.XMLParser(remove_blank_text=True)
# Monta XML do corpo da requisição
raiz = etree.Element('enviNFe')
etree.SubElement(raiz, 'versaoDados').text = self._versao
raiz = etree.Element('enviNFe', versao=VERSAO_PADRAO)
#etree.SubElement(raiz, 'versao').text = self._versao
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, 'NFe').text = nota_fiscal # conjunto de nfe tramistidas (max 50)
dados = etree.tostring(raiz, encoding="unicode") # BUG < retorna caracteres ASCII
#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
# Monta XML para envio da requisição
xml = self._construir_xml_status_pr(cabecalho=self._cabecalho_soap(), dados=dados, url=url)
xml = str(xml).replace('&amp;','').replace('lt;','<').replace('gt;','>').replace('&','')
return self._post(url, xml, self._post_header())
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)
def cancelar(self, modelo, xml):
""" Envia um evento de cancelamento de nota fiscal """
@ -65,17 +67,17 @@ class ComunicacaoSefaz(Comunicacao):
xml = self._construir_xml_status_pr(cabecalho=self._cabecalho_soap(), dados=dados, url=url)
xml = str(xml).replace('&amp;','').replace('lt;','<').replace('gt;','>').replace('&','')
return xml
#return self._post(url, xml, self._post_header())
#return self._post(url, xml)
def situacao_nfe(self, nota_fiscal):
pass
def status_servico(self, tipo):
def status_servico(self, modelo):
""" Verifica status do servidor da receita. """
""" tipo é a string com tipo de serviço que deseja consultar
Ex: nfe ou nfce
"""
url = self._get_url(tipo=tipo, consulta='STATUS')
url = self._get_url(modelo=modelo, consulta='STATUS')
# Monta XML do corpo da requisição
raiz = etree.Element('consStatServ', versao='3.10', xmlns=NAMESPACE_NFE)
@ -85,12 +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, url=url)
xml = self._construir_xml_status_pr(cabecalho=self._cabecalho_soap(), dados=dados)
else:
xml = self._construir_xml_soap(cabecalho=self._cabecalho_soap(), metodo='nfeRecepcao2', tag_metodo='nfeStatusServicoNF2', dados=dados)
xml = str(xml, 'utf-8').replace('&lt;', '<').replace('&gt;', '>').replace('\'', '"').replace('\n', '')
xml = str(xml).replace('&lt;', '<').replace('&gt;', '>').replace('\'', '"').replace('\n', '')
# Chama método que efetua a requisição POST no servidor SOAP
return self._post(url, xml, self._post_header())
return self._post(url, xml)
def consultar_cadastro(self, instancia):
#post = '/nfeweb/services/cadconsultacadastro.asmx'
@ -183,7 +185,7 @@ class ComunicacaoSefaz(Comunicacao):
body = etree.SubElement(raiz, '{%s}Body'%NAMESPACE_SOAP)
met = etree.SubElement(
body, tag_metodo, xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/%s"%metodo,
body, tag_metodo, xmlns=metodo,
)
etree.SubElement(met, 'nfeCabecMsg').text = cabecalho
@ -191,15 +193,15 @@ class ComunicacaoSefaz(Comunicacao):
return etree.tostring(raiz, encoding="utf-8", xml_declaration=True)
def _construir_xml_status_pr(self, cabecalho, dados, url):
def _construir_xml_status_pr(self, cabecalho, dados):
u"""Mota o XML para o envio via SOAP"""
raiz = etree.Element('{%s}Envelope'%NAMESPACE_SOAP, nsmap={'soap': NAMESPACE_SOAP}, xmlns=url)
raiz = etree.Element('{%s}Envelope'%NAMESPACE_SOAP, nsmap={'soap': NAMESPACE_SOAP}, xmlns=NAMESPACE_NFE)
etree.SubElement(raiz, '{%s}Header'%NAMESPACE_SOAP).text = cabecalho
body = etree.SubElement(raiz, '{%s}Body'%NAMESPACE_SOAP)
etree.SubElement(body, 'nfeDadosMsg').text = dados
return etree.tostring(raiz, encoding="UTF-8", xml_declaration=True).decode('utf-8')
return etree.tostring(raiz, encoding='unicode')
def _post_header(self):
u"""Retorna um dicionário com os atributos para o cabeçalho da requisição HTTP"""
@ -210,22 +212,25 @@ class ComunicacaoSefaz(Comunicacao):
u'Accept': u'application/soap+xml; charset=utf-8',
}
def _post(self, url, xml, header):
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 = 'key.pem'
#caminho_cert = 'cert.pem'
caminho_chave = '/home/junior/Documentos/Certificados/key.pem'
caminho_cert = '/home/junior/Documentos/Certificados/cert.pem'
# Abre a conexão HTTPS
cert = (caminho_cert, caminho_chave)
#headers = {'content-type': 'text/xml'}
try:
print (url)
result = requests.post(url, xml, headers=self._post_header(), cert=cert, verify=False)
print (result.content)
if result == 200:
return result.text
else:
return result
except Exception:
raise
except requests.exceptions.ConnectionError as e:
raise e

22
pynfe/processamento/serializacao.py

@ -6,7 +6,7 @@ from pynfe.entidades import NotaFiscal
from pynfe.utils import etree, so_numeros, obter_municipio_por_codigo, \
obter_pais_por_codigo, obter_municipio_e_codigo, \
formatar_decimal, safe_str, obter_uf_por_codigo, obter_codigo_por_municipio
from pynfe.utils.flags import CODIGOS_ESTADOS, VERSAO_PADRAO
from pynfe.utils.flags import CODIGOS_ESTADOS, VERSAO_PADRAO, NAMESPACE_NFE
class Serializacao(object):
"""Classe abstrata responsavel por fornecer as funcionalidades basicas para
@ -49,7 +49,7 @@ class SerializacaoXML(Serializacao):
armazenado(s) em cache local."""
# No raiz do XML de saida
raiz = etree.Element('NFe', xmlns="http://www.portalfiscal.inf.br/nfe")
raiz = etree.Element('NFe', xmlns=NAMESPACE_NFE)
# Carrega lista de Notas Fiscais
notas_fiscais = self._fonte_dados.obter_lista(_classe=NotaFiscal, **kwargs)
@ -75,8 +75,6 @@ class SerializacaoXML(Serializacao):
etree.SubElement(raiz, 'CNPJ').text = so_numeros(emitente.cnpj)
etree.SubElement(raiz, 'xNome').text = emitente.razao_social
etree.SubElement(raiz, 'xFant').text = emitente.nome_fantasia
etree.SubElement(raiz, 'IE').text = emitente.inscricao_estadual
# Endereço
endereco = etree.SubElement(raiz, 'enderEmit')
etree.SubElement(endereco, 'xLgr').text = emitente.endereco_logradouro
@ -91,7 +89,11 @@ class SerializacaoXML(Serializacao):
etree.SubElement(endereco, 'cPais').text = emitente.endereco_pais
etree.SubElement(endereco, 'xPais').text = obter_pais_por_codigo(emitente.endereco_pais)
etree.SubElement(endereco, 'fone').text = emitente.endereco_telefone
etree.SubElement(raiz, 'IE').text = emitente.inscricao_estadual
etree.SubElement(raiz, 'IEST').text = emitente.inscricao_estadual_subst_tributaria
etree.SubElement(raiz, 'IM').text = emitente.inscricao_municipal
etree.SubElement(raiz, 'CNAE').text = emitente.cnae_fiscal
etree.SubElement(raiz, 'CRT').text = emitente.codigo_de_regime_tributario
if retorna_string:
return etree.tostring(raiz, encoding="unicode", pretty_print=True)
else:
@ -254,18 +256,20 @@ class SerializacaoXML(Serializacao):
"""
if nota_fiscal.modelo == 65:
etree.SubElement(ide, 'idDest').text = str(1)
etree.SubElement(ide, 'indPres').text = str(1)
etree.SubElement(ide, 'indFinal').text = str(1)
else:
etree.SubElement(ide, 'idDest').text = str(nota_fiscal.indicador_destino)
etree.SubElement(ide, 'indPres').text = str(nota_fiscal.indicador_presencial)
etree.SubElement(ide, 'indFinal').text = str(nota_fiscal.cliente_final)
etree.SubElement(ide, 'cMunFG').text = nota_fiscal.municipio
etree.SubElement(ide, 'tpImp').text = str(nota_fiscal.tipo_impressao_danfe)
etree.SubElement(ide, 'tpEmis').text = str(nota_fiscal.forma_emissao)
etree.SubElement(ide, 'cDV').text = nota_fiscal.dv_codigo_numerico_aleatorio
etree.SubElement(ide, 'tpAmb').text = str(self._ambiente)
etree.SubElement(ide, 'finNFe').text = str(nota_fiscal.finalidade_emissao)
if nota_fiscal.modelo == 65:
etree.SubElement(ide, 'indFinal').text = str(1)
etree.SubElement(ide, 'indPres').text = str(1)
else:
etree.SubElement(ide, 'indFinal').text = str(nota_fiscal.cliente_final)
etree.SubElement(ide, 'indPres').text = str(nota_fiscal.indicador_presencial)
etree.SubElement(ide, 'procEmi').text = str(nota_fiscal.processo_emissao)
etree.SubElement(ide, 'verProc').text = '%s %s'%(self._nome_aplicacao, nota_fiscal.versao_processo_emissao)
### CONTINGENCIA ###

17
pynfe/utils/webservices.py

@ -424,13 +424,16 @@ NFE = {
'CADASTRO': ''
},
'RS': {
'STATUS': '',
'AUTORIZACAO': '',
'RECIBO': '',
'CHAVE': '',
'INUTILIZACAO': '',
'EVENTOS': '',
'CADASTRO': ''
'STATUS': 'nfe.sefaz.rs.gov.br/ws/NfeStatusServico/NfeStatusServico2.asmx',
'AUTORIZACAO': 'nfe.sefaz.rs.gov.br/ws/NfeAutorizacao/NFeAutorizacao.asmx',
'RECIBO': 'nfe.sefaz.rs.gov.br/ws/NfeRetAutorizacao/NFeRetAutorizacao.asmx',
'CHAVE': 'nfe.sefaz.rs.gov.br/ws/NfeConsulta/NfeConsulta2.asmx',
'INUTILIZACAO': 'nfe.sefaz.rs.gov.br/ws/NfeInutilizacao/NfeInutilizacao2.asmx',
'EVENTOS': 'nfe.sefaz.rs.gov.br/ws/recepcaoevento/recepcaoevento.asmx',
'CADASTRO': 'nfe.sefaz.rs.gov.br/ws/cadconsultacadastro/cadconsultacadastro2.asmx',
'EVENTOS': 'nfe.sefaz.rs.gov.br/ws/recepcaoevento/recepcaoevento.asmx',
'DOWNLOAD': 'nfe.sefaz.rs.gov.br/ws/nfeDownloadNF/nfeDownloadNF.asmx',
'DESTINADAS': 'nfe.sefaz.rs.gov.br/ws/nfeConsultaDest/nfeConsultaDest.asmx'
},
'MS': {
'STATUS': '',

Loading…
Cancel
Save