'''
Created on 19 jul. 2017
@author: luis
'''
from pyfva.soap.validador_certificado import ValideElServicio as ValideServicioCertificado,\
ValidadorDeCertificadoSoapServiceStub,\
SoliciteLaValidacionDelCertificadoDeAutenticacion
from pyfva.soap.validador_documento import ValideElServicio as ValideServicioDocumento,\
ValidadorDeDocumentoSoapServiceStub, ValideElDocumentoXmlEnvelopedCoFirma,\
ValideElDocumentoXmlEnvelopedContraFirma, ValideElDocumentoMSOffice, ValideElDocumentoOdf, \
ValideElDocumentoPdf
from pyfva.soap import settings
from pyfva.constants import get_text_representation, ERRORES_VALIDA_CERTIFICADO,\
ERRORES_VALIDAR_ODF, ERRORES_VALIDAR_MSOFFICE,\
ERRORES_VALIDAR_XMLCONTRAFIRMA, ERRORES_VALIDAR_XMLCOFIRMA,\
ERRORES_VALIDAR_PDF
import traceback
from pyfva import logger
[docs]class ClienteValidador(object):
"""Permite validar una firma o un documento utilizando los servicios del BCCR
Los documentos que se pueden validar son:
* Certificados digitales (CA nacional)
* XML: con cofirma y contrafirma
* MSOffice: .docx, .xlsx y .pptx
* ODF: .odt, .ods y .odp
* PDF: .pdf
.. note::
Los parámetros negocio y entidad de momento no son requeridos, pero puede que en un futuro cercano
lo sean, por lo que se recomienda suministrarlos.
:param negocio: número de identificación del negocio (provisto por el BCCR)
:param entidad: número de identificación de la entidad (provisto por el BCCR)
"""
DEFAULT_CERTIFICATE_ERROR = {
'codigo_error': 1,
'texto_codigo_error': get_text_representation(
ERRORES_VALIDA_CERTIFICADO, 1),
'exitosa': False,
'certificado': None
}
[docs] def DEFAULT_DOCUMENT_ERROR(self, ERRORES_VALIDA):
return {
'exitosa': False,
'codigo_error': 1,
'texto_codigo_error': get_text_representation(ERRORES_VALIDA, 1),
'advertencias': None,
'errores_encontrados': None,
'firmantes': None,
}
def __init__(self,
negocio=settings.DEFAULT_BUSSINESS,
entidad=settings.DEFAULT_ENTITY):
self.negocio = negocio
self.entidad = entidad
[docs] def validar_documento(self, documento, formato):
"""Valida si el documento está firmado correctamente.
**NOTA:** Esta versión está obsoleta y tiene problemas de validación de algunos documentos, usar la versión V2
disponible ene este paquete.
:param documento: documento xml en base64
:param formato: tipo de documento a validar (cofirma, contrafirma, msoffice, odf).
Retorna una diccionario con los siguientes elementos, en caso de error retorna
**DEFAULT_DOCUMENT_ERROR**.
.. note::
Observe que en caso de no ser exitosa la operación los atributos 'advertencias', 'errores_encontrados' y 'firmantes' retornarán None
:returns:
**codigo_error:** Número con el código de error 0 es éxito
**texto_codigo_error:** Descripción del error
**exitosa:** True si fue exitoso el verificado del documento, False si no lo fue
**advertencias:** Lista de advertencias encontradas durante el proceso de validadación, algo como: ["adv1", "adv2"]
**errores_encontrados:** Lista de errores encontrados y su respectivo detalle, ej
[("código de error", "Detalle del error"), ...]
**firmantes:** Lista de información del los firmantes, ej
[ {'identificacion': "8-0888-0888", 'fecha_firma': datetime.now(),
'nombre': "Juanito Mora Porras"}, ... ]
"""
logger.debug({'message':"Validador: validar_documento", 'data':
{'format': formato, 'data': repr(locals())}, 'location': __file__})
try:
if formato == 'cofirma':
dev = self._validar_documento_cofirma(documento)
elif formato == 'contrafirma':
dev = self._validar_documento_contrafirma(documento)
elif formato == 'msoffice':
dev = self._validar_documento_msoffice(documento)
elif formato == 'odf':
dev = self._validar_documento_odf(documento)
elif formato == 'pdf':
dev = self._validar_documento_pdf(documento)
else:
logger.error({'message':"Validador: validando documento", 'data':
{'format': formato,
'message':"No existe formato especificado"}, 'location': __file__})
dev = self.DEFAULT_DOCUMENT_ERROR(ERRORES_VALIDAR_XMLCOFIRMA)
except Exception as e:
logger.error({'message':"Validador: validando documento",
'data': {'format': formato, 'message': e}, 'location': __file__})
dev = self.DEFAULT_DOCUMENT_ERROR(ERRORES_VALIDAR_XMLCOFIRMA)
logger.info({'message': "Validador: validar_documento", 'data':
{'format': formato, 'result': dev}, 'location': __file__})
return dev
[docs] def validar_certificado_autenticacion(self, certificado):
"""Valida si el certificado de autenticación es válido y no está revocado.
:param certificado: Certificado en base64
Retorna una diccionario con los siguientes elementos, en caso de error retorna
**DEFAULT_CERTIFICATE_ERROR**.
:returns:
**codigo_error:** Número con el código de error 0 es éxito
**texto_codigo_error:** Descripción del error
**exitosa:** True si fue exitosa, False si no lo fue
**certificado:** Si la operación no fue exitosa retorna None, si lo fue retorna un diccionario con:
**identificacion:** Número de identificación del suscriptor dueño del certificado
**nombre:** Nombre completo del suscriptor dueño del certificado
**inicio_vigencia:** Fecha de inicio del vigencia del certificado
**fin_vigencia:** Fecha de finalización de la vigencia del certificado
"""
logger.debug({'message':
"Validador: validar_certificado_autenticacion", 'data': repr(locals()),
'location': __file__})
try:
dev = self._validar_certificado_autenticacion(certificado)
except Exception as e:
logger.error({'message': "Validador: validando certificado",
'data': e, 'location': __file__})
dev = self.DEFAULT_CERTIFICATE_ERROR
logger.info({'message':
"Validador: validar_certificado_autenticacion result ", 'data': dev, 'location': __file__})
return dev
[docs] def validar_servicio(self, servicio):
"""Valida si el servicio está disponible.
:param servicio: tipo de servicio a validar, puede ser 'certificado' o 'documento'
:returns: True si lo está o False si ocurrió algún error contactando al BCCR o el servicio no está disponible
"""
dev = False
if servicio.lower() == 'certificado':
dev = self._validar_servicio_certificado()
elif servicio.lower() == 'documento':
dev = self._validar_servicio_documento()
logger.info({'message': "Validador: Validar servicio",
'data': {'servicio':servicio, 'result':dev}, 'location': __file__})
return dev
# Private methods
def _validar_documento_cofirma(self, documento):
stub = ValidadorDeDocumentoSoapServiceStub()
options = ValideElDocumentoXmlEnvelopedCoFirma()
options.elDocumentoXml = documento
try:
status = stub.ValideElDocumentoXmlEnvelopedCoFirma(options)
dev = self._extract_documento_xml(
status.soap_body.ValideElDocumentoXmlEnvelopedCoFirmaResult,
ERRORES_VALIDAR_XMLCOFIRMA)
except Exception as e:
logger.error({'message':"Validador: validando cofirma", 'data': e, 'location': __file__})
dev = self.DEFAULT_DOCUMENT_ERROR(ERRORES_VALIDAR_XMLCOFIRMA)
return dev
def _validar_documento_contrafirma(self, documento):
stub = ValidadorDeDocumentoSoapServiceStub()
options = ValideElDocumentoXmlEnvelopedContraFirma()
options.elDocumentoXml = documento
try:
status = stub.ValideElDocumentoXmlEnvelopedContraFirma(options)
dev = self._extract_documento_xml(
status.soap_body.ValideElDocumentoXmlEnvelopedContraFirmaResult,
ERRORES_VALIDAR_XMLCONTRAFIRMA)
except Exception as e:
traceback.print_exc()
logger.error({'message':"Validador: validando contrafirma", 'data': e, 'location': __file__})
dev = self.DEFAULT_DOCUMENT_ERROR(ERRORES_VALIDAR_XMLCONTRAFIRMA)
return dev
def _validar_documento_msoffice(self, documento):
stub = ValidadorDeDocumentoSoapServiceStub()
options = ValideElDocumentoMSOffice()
options.elDocumentoOffice = documento
try:
status = stub.ValideElDocumentoMSOffice(options)
dev = self._extract_documento_xml(
status.soap_body.ValideElDocumentoMSOfficeResult,
ERRORES_VALIDAR_MSOFFICE)
except Exception as e:
logger.error({'message':"Validador: validando MSOffice",
'data': e, 'location': __file__})
dev = self.DEFAULT_DOCUMENT_ERROR(ERRORES_VALIDAR_MSOFFICE)
return dev
def _validar_documento_odf(self, documento):
stub = ValidadorDeDocumentoSoapServiceStub()
options = ValideElDocumentoOdf()
options.elDocumentoOdf = documento
try:
status = stub.ValideElDocumentoOdf(options)
dev = self._extract_documento_xml(
status.soap_body.ValideElDocumentoOdfResult,
ERRORES_VALIDAR_ODF)
except Exception as e:
logger.error({'message':"Validador: validando ODF", 'data':e, 'location': __file__})
dev = self.DEFAULT_DOCUMENT_ERROR(ERRORES_VALIDAR_ODF)
return dev
def _validar_documento_pdf(self, documento):
stub = ValidadorDeDocumentoSoapServiceStub()
options = ValideElDocumentoPdf()
options.elDocumentoPdf = documento
try:
status = stub.ValideElDocumentoPdf(options)
dev = self._extract_documento_xml(
status.soap_body.ValideElDocumentoPdfResult,
ERRORES_VALIDAR_PDF)
except Exception as e:
logger.error({'message':"Validador: validando PDF", 'data': e, 'location': __file__})
dev = self.DEFAULT_DOCUMENT_ERROR(ERRORES_VALIDAR_PDF)
return dev
def _extract_documento_xml(self, result, ERRORES_VALIDACION):
dev = {}
#dev.update(self.DEFAULT_DOCUMENT_ERROR(ERRORES_VALIDACION))
dev['codigo_error'] = 0 if result.FueExitosa else 1
dev['texto_codigo_error'] = get_text_representation(
ERRORES_VALIDACION, dev['codigo_error']),
dev['exitosa'] = result.FueExitosa
dev['advertencias'] = None
dev['errores_encontrados'] = None
dev['firmantes'] = None
if result.Advertencias:
dev['advertencias'] = result.Advertencias.string
if result.ErroresEncontrados:
dev['errores_encontrados'] = [(error.Codigo, error.Detalle)
for error in result.ErroresEncontrados.ErrorDeDocumento]
if result.Firmantes:
dev['firmantes'] = [
{'identificacion': x.Cedula,
'fecha_firma': x.FechaDeFirma,
'nombre': x.NombreCompleto} for x in
result.Firmantes.Firmante]
return dev
def _validar_certificado_autenticacion(self, certificado):
stub = ValidadorDeCertificadoSoapServiceStub()
options = SoliciteLaValidacionDelCertificadoDeAutenticacion()
options.elCertificadoDeAutenticacion = certificado
status = stub.SoliciteLaValidacionDelCertificadoDeAutenticacion(
options)
result = status.soap_body.SoliciteLaValidacionDelCertificadoDeAutenticacionResult
return self._extract_certificado_autenticacion(result)
def _extract_certificado_autenticacion(self, result):
dev = {
'codigo_error': result.CodigoDeError,
'texto_codigo_error': get_text_representation(
ERRORES_VALIDA_CERTIFICADO, result.CodigoDeError),
'exitosa': result.FueExitosa,
'certificado': None
}
if result.FueExitosa:
cert = result.InformacionDelCertificado
dev['certificado'] = {
'tipo_identificacion': cert.TipoDeIdentificacion,
'identificacion': cert.Identificacion or 'N/D',
'nombre': cert.NombreCompleto or 'N/D',
'inicio_vigencia': cert.FechaInicioDeLaVigencia,
'fin_vigencia': cert.FechaFinalDeLaVigencia}
return dev
def _validar_servicio_certificado(self):
stub = ValidadorDeCertificadoSoapServiceStub()
option = ValideServicioCertificado()
try:
status = stub.ValideElServicio(option)
dev = status.soap_body.ValideElServicioResult
except Exception as e:
logger.error({'message': "Validador: Servicio de validado de certificado fallando",
'data': e, 'location': __file__})
dev = False
return dev
def _validar_servicio_documento(self):
stub = ValidadorDeDocumentoSoapServiceStub()
option = ValideServicioDocumento()
try:
status = stub.ValideElServicio(option)
dev = status.soap_body.ValideElServicioResult
except Exception as e:
logger.error({'message':
"Validador: Servicio de validado de documentos fallando", 'data': e, 'location': __file__})
dev = False
return dev