feat: enlaces de formulario sin vencimiento + PDF descargable sin sesión vía token público
This commit is contained in:
@@ -67,7 +67,7 @@ try {
|
|||||||
$nomForm = $plantilla['nombre'];
|
$nomForm = $plantilla['nombre'];
|
||||||
$mensajeWa = "Hola $nomPac, le enviamos el formulario *\"$nomForm\"* para que lo complete y firme digitalmente.\n\n"
|
$mensajeWa = "Hola $nomPac, le enviamos el formulario *\"$nomForm\"* para que lo complete y firme digitalmente.\n\n"
|
||||||
. "👉 Accede aquí:\n$url\n\n"
|
. "👉 Accede aquí:\n$url\n\n"
|
||||||
. "El enlace expira en 7 días. Si tiene dudas contáctenos.";
|
. "Si tiene dudas contáctenos.";
|
||||||
|
|
||||||
$telPac = $prefilled['__paciente']['telefono'] ?? '';
|
$telPac = $prefilled['__paciente']['telefono'] ?? '';
|
||||||
$waUrl = 'https://wa.me/' . preg_replace('/\D/', '', $telPac)
|
$waUrl = 'https://wa.me/' . preg_replace('/\D/', '', $telPac)
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ class Formulario {
|
|||||||
*/
|
*/
|
||||||
public function crearEnvio(array $datos, int $enviadoPor): int {
|
public function crearEnvio(array $datos, int $enviadoPor): int {
|
||||||
$token = bin2hex(random_bytes(32));
|
$token = bin2hex(random_bytes(32));
|
||||||
$expira = date('Y-m-d H:i:s', strtotime('+7 days'));
|
$expira = null; // El enlace no expira
|
||||||
|
|
||||||
$id = $this->db->insert('lab_form_envios', [
|
$id = $this->db->insert('lab_form_envios', [
|
||||||
'formulario_id' => (int)$datos['formulario_id'],
|
'formulario_id' => (int)$datos['formulario_id'],
|
||||||
|
|||||||
+4
-4
@@ -853,8 +853,8 @@ const formCliente = {
|
|||||||
show('yf-firma-thumb');
|
show('yf-firma-thumb');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link al PDF (requiere sesión admin, se muestra de todas formas)
|
// Link al PDF (acceso público vía token, no requiere sesión)
|
||||||
$('yf-pdf-btn').href = 'ver_formulario_enviado.php?id=' + env.id;
|
$('yf-pdf-btn').href = 'ver_formulario_enviado.php?t=' + encodeURIComponent(TOKEN);
|
||||||
|
|
||||||
if (env.hash_verificacion) {
|
if (env.hash_verificacion) {
|
||||||
$('yf-hash').textContent = env.hash_verificacion;
|
$('yf-hash').textContent = env.hash_verificacion;
|
||||||
@@ -1080,10 +1080,10 @@ const formCliente = {
|
|||||||
$('success-hash').textContent = d.hash;
|
$('success-hash').textContent = d.hash;
|
||||||
show('success-hash-box');
|
show('success-hash-box');
|
||||||
}
|
}
|
||||||
// Link al PDF
|
// Link al PDF (acceso público vía token, no requiere sesión)
|
||||||
if (d.envio_id) {
|
if (d.envio_id) {
|
||||||
const pdfBtn = $('success-pdf-btn');
|
const pdfBtn = $('success-pdf-btn');
|
||||||
pdfBtn.href = 'ver_formulario_enviado.php?id=' + d.envio_id;
|
pdfBtn.href = 'ver_formulario_enviado.php?t=' + encodeURIComponent(TOKEN);
|
||||||
show('success-pdf-row');
|
show('success-pdf-row');
|
||||||
}
|
}
|
||||||
show('success-screen');
|
show('success-screen');
|
||||||
|
|||||||
+54
-24
@@ -1,39 +1,69 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* ver_formulario_enviado.php — Ver respuesta de un formulario (imprimible / PDF)
|
* ver_formulario_enviado.php — Ver respuesta de un formulario (imprimible / PDF)
|
||||||
* Requiere: admin o enfermero autenticado
|
* Acceso admin/enfermero: ver_formulario_enviado.php?id=ENVIO_ID (requiere sesión)
|
||||||
* URL: ver_formulario_enviado.php?id=ENVIO_ID
|
* Acceso público cliente: ver_formulario_enviado.php?t=TOKEN (sin sesión, solo firmado/completado)
|
||||||
*/
|
*/
|
||||||
require_once 'config/config.php';
|
require_once 'config/config.php';
|
||||||
if (!isUserLoggedIn()) { header('Location: login.php'); exit; }
|
|
||||||
|
|
||||||
$id = (int)($_GET['id'] ?? 0);
|
$tokenPublico = trim($_GET['t'] ?? '');
|
||||||
if (!$id) { http_response_code(400); die('ID requerido'); }
|
$modoPublico = ($tokenPublico !== '');
|
||||||
|
|
||||||
|
if (!$modoPublico && !isUserLoggedIn()) {
|
||||||
|
header('Location: login.php'); exit;
|
||||||
|
}
|
||||||
|
|
||||||
// ── Cargar datos ──────────────────────────────────────────────────────
|
// ── Cargar datos ──────────────────────────────────────────────────────
|
||||||
$db = Database::getInstance();
|
$db = Database::getInstance();
|
||||||
|
|
||||||
$envio = $db->fetch(
|
if ($modoPublico) {
|
||||||
"SELECT e.*, f.nombre AS form_nombre, f.categoria, f.descripcion AS form_descripcion,
|
// Acceso por token: solo si el formulario ya fue firmado/completado
|
||||||
f.esquema, f.permite_firma, f.requiere_firma,
|
if (!preg_match('/^[a-f0-9]{64}$/i', $tokenPublico)) {
|
||||||
f.doc_encabezado, f.doc_subtitulo, f.doc_logo_base64, f.doc_color, f.doc_pie_pagina,
|
http_response_code(400); die('Token inválido');
|
||||||
p.nombre_completo AS paciente_nombre, p.numero_documento, p.tipo_documento,
|
}
|
||||||
p.fecha_nacimiento, p.telefono AS paciente_telefono, p.eps,
|
$envio = $db->fetch(
|
||||||
u.full_name AS enviado_por_nombre, u.email AS enviado_por_email
|
"SELECT e.*, f.nombre AS form_nombre, f.categoria, f.descripcion AS form_descripcion,
|
||||||
FROM lab_form_envios e
|
f.esquema, f.permite_firma, f.requiere_firma,
|
||||||
JOIN lab_formularios f ON f.id = e.formulario_id
|
f.doc_encabezado, f.doc_subtitulo, f.doc_logo_base64, f.doc_color, f.doc_pie_pagina,
|
||||||
LEFT JOIN lab_pacientes p ON p.id = e.paciente_id
|
p.nombre_completo AS paciente_nombre, p.numero_documento, p.tipo_documento,
|
||||||
LEFT JOIN admin_users u ON u.id = e.enviado_por
|
p.fecha_nacimiento, p.telefono AS paciente_telefono, p.eps,
|
||||||
WHERE e.id = ?",
|
u.full_name AS enviado_por_nombre, u.email AS enviado_por_email
|
||||||
[$id]
|
FROM lab_form_envios e
|
||||||
);
|
JOIN lab_formularios f ON f.id = e.formulario_id
|
||||||
|
LEFT JOIN lab_pacientes p ON p.id = e.paciente_id
|
||||||
|
LEFT JOIN admin_users u ON u.id = e.enviado_por
|
||||||
|
WHERE e.token = ?",
|
||||||
|
[$tokenPublico]
|
||||||
|
);
|
||||||
|
if (!$envio) { http_response_code(404); die('Formulario no encontrado'); }
|
||||||
|
if (!in_array($envio['estado'], ['firmado', 'completado'])) {
|
||||||
|
http_response_code(403); die('El formulario aún no ha sido completado.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$id = (int)($_GET['id'] ?? 0);
|
||||||
|
if (!$id) { http_response_code(400); die('ID requerido'); }
|
||||||
|
|
||||||
if (!$envio) { http_response_code(404); die('Formulario no encontrado'); }
|
$envio = $db->fetch(
|
||||||
|
"SELECT e.*, f.nombre AS form_nombre, f.categoria, f.descripcion AS form_descripcion,
|
||||||
|
f.esquema, f.permite_firma, f.requiere_firma,
|
||||||
|
f.doc_encabezado, f.doc_subtitulo, f.doc_logo_base64, f.doc_color, f.doc_pie_pagina,
|
||||||
|
p.nombre_completo AS paciente_nombre, p.numero_documento, p.tipo_documento,
|
||||||
|
p.fecha_nacimiento, p.telefono AS paciente_telefono, p.eps,
|
||||||
|
u.full_name AS enviado_por_nombre, u.email AS enviado_por_email
|
||||||
|
FROM lab_form_envios e
|
||||||
|
JOIN lab_formularios f ON f.id = e.formulario_id
|
||||||
|
LEFT JOIN lab_pacientes p ON p.id = e.paciente_id
|
||||||
|
LEFT JOIN admin_users u ON u.id = e.enviado_por
|
||||||
|
WHERE e.id = ?",
|
||||||
|
[$id]
|
||||||
|
);
|
||||||
|
if (!$envio) { http_response_code(404); die('Formulario no encontrado'); }
|
||||||
|
|
||||||
// Enfermero solo puede ver sus propios envíos
|
// Enfermero solo puede ver sus propios envíos
|
||||||
if (isEnfermero()) {
|
if (isEnfermero()) {
|
||||||
$uid = (int)($_SESSION['admin_user']['id'] ?? 0);
|
$uid = (int)($_SESSION['admin_user']['id'] ?? 0);
|
||||||
if ($envio['enviado_por'] != $uid) { http_response_code(403); die('Sin acceso'); }
|
if ($envio['enviado_por'] != $uid) { http_response_code(403); die('Sin acceso'); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Config global del lab ─────────────────────────────────────────────
|
// ── Config global del lab ─────────────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user