Saltar al contenido principal

Firma Electronica

¿Para qué sirve?​

Permite firmar digitalmente cualquier PDF del sistema sin imprimir ni escanear. El firmante dibuja su firma con el dedo o el mouse, y el sistema guarda esa imagen junto con la fecha, la hora, la IP y un registro de auditoría de todo lo que pasó.

Hay dos niveles disponibles:

  • Simple: quien recibe el enlace firma directamente. Sirve como consentimiento bajo la Ley 19.799 art. 2.f (recepciones, aceptaciones de términos, actas internas).
  • Simple + código al correo: antes de ver el documento, el firmante recibe un código de 6 dígitos en su correo y lo tiene que ingresar. Sube la certeza de "quien tenga el enlace" a "quien controle ese buzón en este momento". Mismo valor legal, más difícil de suplantar.
Firma avanzada con ClaveÚnica: todavía no disponible

El módulo contempla un tercer nivel —firma electrónica avanzada con ClaveÚnica vía firma.digital.gob.cl, equivalente legal a la firma manuscrita (Ley 19.799 art. 3)—, pero no está implementado: falta la verificación criptográfica del PDF que devuelve el gobierno.

La opción no se ofrece en el panel y el sistema rechaza crear documentos en ese modo, para no generar solicitudes que nadie podría completar. Si necesitas firma avanzada hoy, el trámite se hace fuera del sistema.

¿Cuándo lo necesitas?​

  • Actas de reunión, autorizaciones, permisos internos.
  • Recepciones de pedidos o de documentos con constancia.
  • Consentimientos de política de privacidad o términos de servicio.
  • Aceptación de cotizaciones y presupuestos.
  • Cualquier flujo donde hoy imprimes → firmas a mano → escaneas → subes.
Para contratos laborales

Un contrato de trabajo admite firma simple, pero si necesitas la equivalencia plena con la firma manuscrita, hoy tienes que usar ClaveÚnica por fuera del sistema (ver aviso más arriba).

Cómo activarlo​

  1. Registra el plugin firma-electronica (viene registrado por defecto en plugins/plugins-registry.php).

  2. Ejecuta el instalador:

    FirmaElectronicaController::install();

    Es idempotente: correrlo varias veces no rompe nada y aplica lo que falte.

  3. Aparece Firma Electronica (ícono ✒️) en el menú lateral del CMS.

Para el modo con código al correo necesitas el correo configurado en el CMS (Configuración → Correo), porque el código viaja por ahí.

Configuración inicial​

En plugins/firma-electronica/config.php (cópialo desde config.example.php):

'signing' => [
'default_mode' => 'simple', // simple | simple_otp
'max_pdf_mb' => 20, // tamaño máximo del PDF a firmar
'watermark' => 'Firmado electronicamente via Web Framework',
],

'otp' => [ // solo aplica al modo simple_otp
'code_length' => 6, // dígitos del código
'expiry_seconds' => 300,// cuánto vive el código (5 minutos)
'max_attempts' => 3, // intentos antes de invalidarlo
'resend_cooldown_secs' => 60, // espera mínima entre dos envíos
'email_subject' => 'Tu codigo de verificacion para firmar',
],

'tokens' => [
'expiry_days' => 14, // días que vive un enlace de firma (0 = sin límite)
],

'access' => [
// Roles que pueden usar el módulo, además de superadmin/admin
'roles_manage' => ['contador', 'rrhh', 'ventas'],
],

'public' => [
// Déjalo en null salvo que los enlaces de correo salgan con un dominio
// equivocado (proxy, enlaces simbólicos). Ejemplo: 'https://mi-empresa.cl'
'base_url' => null,
],
El pie del documento firmado se arma solo

Si dejas watermark como viene, el documento firmado termina con el nombre de tu panel y el dominio donde se firmó — por ejemplo «Firmado electrónicamente en Jensen + (jensenmas.cl)», que es lo que necesita ver quien recibe el contrato. Antes decía el nombre del software, justo el dato que a nadie le sirve.

Escribe tu propia frase ahí para reemplazarla, o null para que no salga nada.

Instalar librerías PDF (recomendado)​

Para que el documento firmado se selle como PDF:

cd plugins/firma-electronica && composer require setasign/fpdi tecnickcom/tcpdf

Sin estas librerías el módulo sigue funcionando, pero en vez del PDF sellado guarda un archivo JSON con las firmas. Nada se pierde: al instalar las librerías, los documentos que se firmen desde entonces salen como PDF.

Cómo se usa día a día​

Crear un documento a firmar​

  1. Ve a Firma Electronica → + Nuevo documento.
  2. Escribe el título (ej. "Acta de recepción - Pedido 1042").
  3. Elige el nivel de firma: simple, o simple + código al correo.
  4. Opcional: pon una fecha de vencimiento. Después de esa fecha el enlace deja de funcionar y el documento queda marcado como vencido.
  5. Adjunta el PDF (se sube desde tu computador).
  6. Agrega los firmantes con su correo y nombre.
  7. Crear y enviar: a cada firmante externo le llega automáticamente un correo con su enlace único.

Firmar (firmante externo)​

Le llega un correo con un botón Firmar documento. No necesita crear cuenta:

  • Modo simple: ve el PDF y dibuja su firma.
  • Modo con código: primero pide el código, lo recibe en su correo, lo ingresa, y recién entonces se muestra el documento y el área de firma. El código dura 5 minutos, se usa una sola vez y se bloquea a los 3 intentos fallidos.

Al firmar, la pestaña se cierra sola y el listado del CMS se actualiza en el momento.

Firmar (usuario interno del CMS)​

Hoy un firmante interno firma desde la línea de comandos:

php plugins/firma-electronica/tools/cli.php sign-admin <id-firmante> --png=firma.png

El botón para firmar desde el panel está pendiente. Mientras tanto, si quieres que alguien de tu equipo firme desde el navegador, agrégalo como firmante externo con su correo.

Ver el estado​

El listado muestra cada documento con:

  • Estado: Sin enviar, Esperando firmas, Firmado, Rechazado o Venció.
  • Cuántos firmantes ya firmaron (3/5).
  • Fecha de creación.

Click en Ver abre el detalle: el estado de cada firmante, la bitácora completa —qué pasó, cuándo y quién, con el nombre de la persona y no su número— y el botón para descargar el documento firmado.

De cada firmante que todavía no firma tienes tres acciones: copiar su enlace, abrirlo, y reenviarle el correo con el mismo enlace de siempre.

El enlace de firma es la identidad de esa persona

Quien tenga ese enlace puede firmar haciéndose pasar por ella. Por eso no se muestra escrito en pantalla —donde queda a la vista de cualquiera que pase por detrás o mire una captura—: se copia con el botón y se pega donde haga falta. Mándalo sólo a su dueño, y por un medio privado.

Los documentos firmados son privados

La descarga pasa siempre por el CMS y verifica quién la pide. Los archivos no son accesibles por URL directa, ni siquiera conociendo el nombre.

¿Qué queda registrado?​

EventoCuándo ocurre
creadoSe creó la solicitud de firma
invite-enviadoSalió el correo con el enlace
vistoEl firmante abrió su enlace por primera vez
otp-enviado / otp-validadoSe envió y se validó el código (modo con correo)
otp-expirado / otp-fallidoEl código venció o se agotaron los intentos
firmadoUn firmante completó su firma
documento-firmadoFirmaron todos y se selló el documento
acuse-enviado / copia-enviadaAcuse parcial y copia final por correo
recordatorio-enviadoSe reenvió automáticamente la invitación al firmante
vencidoSe intentó usar un enlace fuera de plazo

Automatizar recordatorios y limpieza​

Si tenés instalado el módulo Automatizaciones, esta firma publica dos acciones en el catálogo para que decidas cuándo se ejecutan:

Recordar firmas pendientes​

Reenvía el correo de invitación a firmantes externos que llevan más de 24 horas sin firmar. Útil para clientes que reciben el enlace y lo dejan pasar sin querer.

  • Cadencia sugerida: 0 9 * * * (todos los días a las 9:00). Es el default_cron que ves al elegir la acción desde "Nueva tarea".
  • Garantía: manda como máximo un recordatorio por firmante por día calendario, aunque programes la tarea varias veces al día o el worker reintente por fallo intermedio. La deduplicación se hace consultando el firma_audit_log: si ya hay un recordatorio-enviado de ese firmante hoy, se lo saltea.
  • Qué omite: firmantes cuyo enlace ya venció (vigencia_firmante decidió expired) y documentos que ya no están en estado enviado.
  • Trazabilidad: cada envío escribe un evento recordatorio-enviado en la auditoría del documento, con el email del destinatario y el ID de la corrida de Automations en detalle_log. Podés ver en el detalle del documento a quién y cuándo se le recordó.
  • Techo por corrida: 500 firmantes por invocación, para respetar el time_limit del worker. Si tenés más, los restantes se procesan en el próximo tick del cron.

Limpiar códigos OTP vencidos​

Borra filas de la tabla firma_otp_challenges más antiguas que otp.challenges_retention_days (por defecto 7 días). La ventana en la que un código es útil son 5 minutos, así que una fila de más de una semana no aporta nada al debugging y sólo hace crecer la tabla.

  • Cadencia sugerida: 7 3 * * * (nightly, 3:07 am).
  • Qué NO borra: los eventos otp-enviado y otp-validado del audit log, que viven en su propia tabla. La traza histórica ("a este firmante se le envió un código y lo validó") se conserva completa.

Cómo activarlas​

  1. Andá a Automatizaciones → Nueva tarea.
  2. Elegí firma-electronica.recordar-pendientes (o firma-electronica.limpiar-otp-vencidos) del catálogo.
  3. Aceptá o modificá el cron sugerido y guardá.

Si desinstalás Firma Electrónica, Automatizaciones remueve automáticamente cualquier tarea programada que apunte a estos handlers.

Uso desde otros plugins​

Cualquier plugin puede pedir firmas llamando a FirmaElectronicaController. No necesitas construir UI ni tocar tablas: los correos, el sellado y la auditoría los maneja el módulo.

$res = FirmaElectronicaController::solicitarFirma([
'titulo' => 'Acta de recepcion - ' . $pedido->numero,
'modo_firma' => 'simple_otp', // simple | simple_otp
'pdf_original' => $rutaPdf,
'firmantes' => [
['tipo' => 'externo', 'email' => $cliente->email,
'nombre' => $cliente->nombre, 'orden' => 1],
],
'origen_tipo' => 'ventas', // deja rastro de qué plugin lo pidió
'origen_id' => $pedidoId,
'vencimiento' => '2026-09-30', // opcional
]);

if ($res['ok']) {
// Al firmante externo ya le llegó el correo con su enlace.
// Cuando firmen todos, el plugin le manda el PDF firmado adjunto.
}

modo_firma => 'avanzada' devuelve ok => false con un mensaje explicando que ese modo no está disponible.

Si prefieres mandar tu propio correo, pasa 'skip_email' => true y usa $res['tokens'] para armar la URL.

Otros métodos​

// Reenviar el correo si el firmante lo perdió (no cambia el enlace)
FirmaElectronicaController::enviarEmailSolicitudFirma($firmanteId);

// Reenviar la copia firmada
FirmaElectronicaController::enviarEmailCopiaFirmada($docId, $pdfFirmadoPath);

Para saber cuándo se completó una firma, consulta firma_audit_log filtrando por documento_log y evento_log = 'documento-firmado'. Los avisos automáticos hacia otros plugins están en el roadmap.

Integraciones concretas
  • HR Manager — próximamente: envío de documentos laborales a la cola de firma.
  • Contabilidad PyMe — próximamente: cotizaciones firmables antes de emitir factura.
  • CRM / Legal / Ventas — cualquier flujo con "el cliente tiene que firmar esto" encaja acá.

CLI para operadores y automatización​

# Listar documentos pendientes
php plugins/firma-electronica/tools/cli.php list --estado=enviado

# Ver el detalle completo (firmantes + auditoría)
php plugins/firma-electronica/tools/cli.php show 42

# Crear un documento con dos firmantes
php plugins/firma-electronica/tools/cli.php create \
--titulo="Acta de recepcion" \
--pdf=/uploads/acta.pdf \
--firmante="cliente@empresa.cl:Cliente,legal@empresa.cl:Legal" \
--modo=simple_otp

# Reenviar correos
php plugins/firma-electronica/tools/cli.php resend-invite 12
php plugins/firma-electronica/tools/cli.php send-copy 42

Todos los comandos aceptan --json. Corre cli.php help para la lista completa.

Se conecta con​

  • Automatizaciones — si está activo, los recordatorios a quienes no han firmado y la limpieza de documentos vencidos corren solos, sin que tengas que programar nada en el servidor.
  • Configuración → Correo — los mensajes que recibe el firmante (invitación, código de verificación, recordatorio) son plantillas editables, con vista previa, como el resto de los correos del sistema.
  • Log de auditoría — cada envío, apertura, firma y anulación queda registrada; es lo que se muestra en el historial de cada documento.
  • Cualquier módulo del CMS — desde otro plugin puedes mandar un documento a firmar llamando al controlador (ver "Uso desde otros plugins" más arriba).

Una copia en Google Drive​

El documento firmado se guarda en este servidor y de ahí se descarga: es la prueba de que alguien aceptó algo, y no puede depender de una cuenta ajena.

Si además llevas el archivo de la oficina en Drive, el botón de nube que está junto a Nuevo documento deja una copia de cada documento ya firmado y sellado. Necesita el módulo Google Drive con su cuenta conectada; mientras no lo esté, el interruptor no se puede encender y la pantalla dice qué falta.

La copia va siempre privada —un documento firmado lleva nombres, RUT y direcciones— y se sube después de que la firma quedó registrada: una caída de Google nunca puede costar una firma.

Preguntas frecuentes​

¿Tiene validez legal en Chile? Los dos modos disponibles valen como consentimiento según la Ley 19.799 art. 2.f: sirven para acreditar que una persona aceptó algo. El modo con código al correo agrega evidencia de que quien firmó controlaba ese buzón. La firma avanzada del art. 3 —la equivalente a la manuscrita— todavía no está implementada acá.

¿Sirve fuera de Chile? Sí. El canvas y el código por correo son genéricos; no dependen de ninguna institución chilena.

¿Se puede usar sin instalar librerías composer? Sí, pero el documento firmado queda como archivo JSON con la firma en base64 en vez de PDF. Instala setasign/fpdi y tecnickcom/tcpdf para obtener el PDF sellado.

¿Los enlaces a firmantes externos vencen? Sí, a los 14 días por defecto (tokens.expiry_days), contados desde que se invitó al firmante. Si el documento además tiene fecha de vencimiento, vale la que ocurra primero. Un enlace vencido muestra un aviso y el documento queda marcado como vencido; para retomarlo hay que crear una solicitud nueva.

¿Se puede reenviar el enlace a un firmante externo? Sí, desde el detalle del documento. Es el mismo enlace, así que sigue funcionando mientras no venza.

¿Qué pasa si alguien más consigue el enlace? En modo simple, quien tenga el enlace puede firmar: úsalo cuando eso sea aceptable. Si necesitas más certeza, usa el modo con código al correo, que exige acceso al buzón del firmante.

¿El documento firmado se puede alterar? El sistema guarda el hash SHA-256 del PDF original al crear la solicitud y lo registra en la auditoría, así que se puede comparar contra el archivo para detectar cambios posteriores. La comparación hoy es manual: la pantalla de verificación está en el roadmap.

¿Quién puede ver los documentos? superadmin, admin y los roles que listes en access.roles_manage, siempre que además tengan la sección concedida en Roles y Permisos. El resto no ve el módulo ni puede consultarlo.

Roadmap​

  • Firma avanzada con ClaveÚnica: verificación del PDF firmado (extraer PKCS#7, validar CRL, extraer RUT del certificado).
  • Botón de firma para usuarios internos desde el panel.
  • Rechazar un documento con motivo.
  • Pantalla de verificación de hash (original vs. firmado).
  • Reintentar el sellado cuando falló.
  • Avisos automáticos a otros plugins al completarse una firma.
  • Firma de varios documentos a la vez.

Firmar tú mismo, desde el panel​

Un firmante de la casa no recibe correo ni enlace: firma desde acá. Abre el documento con Ver y, en tu propia fila, pulsa Firmar: dibujas tu firma con el mouse (o con el dedo en un táctil) y listo.

El botón aparece sólo en tu fila, y sólo mientras no hayas firmado.

Nadie firma por otro

Ni siquiera el superadministrador. Si intentas firmar la fila de otra persona, el sistema responde «Solo puedes firmar lo que te corresponde a ti» — y la fila de un firmante externo no se puede firmar desde el panel en absoluto: ésa se firma con el enlace que le llegó a su correo. Una firma que cualquiera con una sesión pudiera poner no probaría nada.

Queda registrado con la fecha, tu cuenta y desde qué equipo se hizo, y aparece en Qué ha pasado. Cuando firman todos, el documento pasa a Firmado y aparece el botón para descargar el documento sellado.

¿Qué sigue?​