Browse Source

Trabalhando na comunicação

tags/0.1
Marinho Brandão 16 years ago
parent
commit
536aecc273
  1. 57
      pynfe/processamento/assinatura.py
  2. 4
      pynfe/processamento/comunicacao.py
  3. 6
      pynfe/processamento/serializacao.py
  4. 2
      pynfe/utils/flags.py
  5. 2
      tests/03-processamento-01-serializacao-xml.txt

57
pynfe/processamento/assinatura.py

@ -61,16 +61,30 @@ class AssinaturaA1(Assinatura):
"""Classe abstrata responsavel por efetuar a assinatura do certificado
digital no XML informado."""
def assinar_arquivo(self, caminho_arquivo):
def assinar_arquivo(self, caminho_arquivo, salva=True):
# Carrega o XML do arquivo
raiz = etree.parse(caminho_arquivo)
return self.assinar_etree(raiz)
# Efetua a assinatura
xml = self.assinar_etree(raiz, retorna_xml=True)
raise Exception(xml)
# Grava XML assinado no arquivo
if salva:
fp = file(caminho_arquivo, 'w')
fp.write(xml)
fp.close()
return xml
def assinar_xml(self, xml):
raiz = etree.parse(StringIO(xml))
return self.assinar_etree(raiz)
def assinar_etree(self, raiz):
# Efetua a assinatura
return self.assinar_etree(raiz, retorna_xml=True)
def assinar_etree(self, raiz, retorna_xml=False):
# Extrai a tag do elemento raiz
tipo = extrair_tag(raiz.getroot())
@ -91,6 +105,24 @@ class AssinaturaA1(Assinatura):
URI=raiz.getroot().getchildren()[0].attrib['Id'],
nsmap={'sig': NAMESPACE_SIG},
)
signed_info = etree.SubElement(signature, '{%s}SignedInfo'%NAMESPACE_SIG)
etree.SubElement(signed_info, 'CanonicalizationMethod', Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315")
etree.SubElement(signed_info, 'SignatureMethod', Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1")
reference = etree.SubElement(signed_info, '{%s}Reference'%NAMESPACE_SIG, URI=raiz.getroot().getchildren()[0].attrib['Id'])
transforms = etree.SubElement(reference, 'Transforms', URI=raiz.getroot().getchildren()[0].attrib['Id'])
etree.SubElement(transforms, 'Transform', Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature")
etree.SubElement(transforms, 'Transform', Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315")
etree.SubElement(reference, '{%s}DigestMethod'%NAMESPACE_SIG, Algorithm="http://www.w3.org/2000/09/xmldsig#sha1")
digest_value = etree.SubElement(reference, '{%s}DigestValue'%NAMESPACE_SIG)
signature_value = etree.SubElement(signature, '{%s}SignatureValue'%NAMESPACE_SIG)
key_info = etree.SubElement(signature, '{%s}KeyInfo'%NAMESPACE_SIG)
x509_data = etree.SubElement(key_info, '{%s}X509Data'%NAMESPACE_SIG)
x509_certificate = etree.SubElement(x509_data, '{%s}X509Certificate'%NAMESPACE_SIG)
raiz.getroot().insert(0, signature)
# Acrescenta a tag de doctype (como o lxml nao suporta alteracao do doctype,
@ -108,21 +140,27 @@ class AssinaturaA1(Assinatura):
assinador.sign(noh_assinatura)
# Coloca na instância Signature os valores calculados
doc.Signature.DigestValue = ctxt.xpathEval(u'//sig:DigestValue')[0].content.replace(u'\n', u'')
doc.Signature.SignatureValue = ctxt.xpathEval(u'//sig:SignatureValue')[0].content.replace(u'\n', u'')
digest_value.text = ctxt.xpathEval(u'//sig:DigestValue')[0].content.replace(u'\n', u'')
signature_value.text = ctxt.xpathEval(u'//sig:SignatureValue')[0].content.replace(u'\n', u'')
# Provavelmente retornarão vários certificados, já que o xmlsec inclui a cadeia inteira
certificados = ctxt.xpathEval(u'//sig:X509Data/sig:X509Certificate')
doc.Signature.X509Certificate = certificados[len(certificados)-1].content.replace(u'\n', u'')
x509_certificate.text = certificados[len(certificados)-1].content.replace(u'\n', u'')
resultado = assinador.status == xmlsec.DSigStatusSucceeded
# Limpa objetos da memoria e desativa funções criptográficas
self._depois_de_assinar_ou_verificar(doc_xml, ctxt, assinador)
#print etree.tostring(raiz, pretty_print=True, xml_declaration=True, encoding='utf-8')
# Gera o XML para retornar
raise Exception(dir(doc_xml))
xml = doc_xml.serialize()
return resultado
if retorna_xml:
raise Exception(xml)
return xml
else:
return etree.parse(StringIO(xml))
def _ativar_funcoes_criptograficas(self):
# FIXME: descobrir forma de evitar o uso do libxml2 neste processo
@ -175,7 +213,6 @@ class AssinaturaA1(Assinatura):
return resultado
def _antes_de_assinar_ou_verificar(self, raiz):
raise Exception(dir(raiz))
# Converte etree para string
xml = etree.tostring(raiz, xml_declaration=True, encoding='utf-8')

4
pynfe/processamento/comunicacao.py

@ -3,7 +3,7 @@
from httplib import HTTPSConnection, HTTPResponse
from pynfe.utils import etree, StringIO
from pynfe.utils.flags import NAMESPACE_NFE, NAMESPACE_SOAP
from pynfe.utils.flags import NAMESPACE_NFE, NAMESPACE_SOAP, VERSAO_PADRAO
class Comunicacao(object):
u"""Classe abstrata responsavel por definir os metodos e logica das classes
@ -21,7 +21,7 @@ class Comunicacao(object):
class ComunicacaoSefaz(Comunicacao):
u"""Classe de comunicação que segue o padrão definido para as SEFAZ dos Estados."""
_versao = '1.01'
_versao = VERSAO_PADRAO
def transmitir(self, nota_fiscal):
pass

6
pynfe/processamento/serializacao.py

@ -7,7 +7,7 @@ except:
from pynfe.entidades import Emitente, Cliente, Produto, Transportadora, NotaFiscal
from pynfe.excecoes import NenhumObjetoEncontrado, MuitosObjetosEncontrados
from pynfe.utils import etree, so_numeros, obter_municipio_por_codigo, obter_pais_por_codigo
from pynfe.utils.flags import CODIGOS_ESTADOS
from pynfe.utils.flags import CODIGOS_ESTADOS, VERSAO_PADRAO
class Serializacao(object):
"""Classe abstrata responsavel por fornecer as funcionalidades basicas para
@ -43,6 +43,8 @@ class Serializacao(object):
raise Exception('Metodo nao implementado')
class SerializacaoXML(Serializacao):
_versao = VERSAO_PADRAO
def exportar(self, destino=None, retorna_string=False, **kwargs):
"""Gera o(s) arquivo(s) de Nofa Fiscal eletronica no padrao oficial da SEFAZ
e Receita Federal, para ser(em) enviado(s) para o webservice ou para ser(em)
@ -220,7 +222,7 @@ class SerializacaoXML(Serializacao):
return raiz
def _serializar_notas_fiscal(self, nota_fiscal, tag_raiz='infNFe', retorna_string=True):
raiz = etree.Element(tag_raiz, versao="2.00")
raiz = etree.Element(tag_raiz, versao=self._versao)
# Dados da Nota Fiscal
ide = etree.SubElement(raiz, 'ide')

2
pynfe/utils/flags.py

@ -4,6 +4,8 @@ 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'
VERSAO_PADRAO = '1.01'
TIPOS_DOCUMENTO = (
'CNPJ',
'CPF',

2
tests/03-processamento-01-serializacao-xml.txt

@ -268,7 +268,7 @@ Serializando por partes
NFe52100112345678000190550010000000011518005123
>>> print serializador._serializar_notas_fiscal(nota_fiscal)
<infNFe versao="2.00" Id="NFe52100112345678000190550010000000011518005123">
<infNFe versao="1.01" Id="NFe52100112345678000190550010000000011518005123">
<ide>
<cUF>52</cUF>
<cNF>51800512</cNF>

Loading…
Cancel
Save