{"id":6,"date":"2026-03-25T15:34:11","date_gmt":"2026-03-25T15:34:11","guid":{"rendered":"https:\/\/testweb.larueca.org\/?page_id=6"},"modified":"2026-03-25T15:39:53","modified_gmt":"2026-03-25T15:39:53","slug":"pasarela-firma-admin","status":"publish","type":"page","link":"https:\/\/testweb.larueca.org\/","title":{"rendered":"pasarela-firma-admin"},"content":{"rendered":"        <div id=\"fps-admin-app\" style=\"max-width:760px;margin:30px auto;padding:24px;border:1px solid #ddd;border-radius:12px;background:#fff;font-family:Arial,sans-serif;box-sizing:border-box;\">\n            <h2 style=\"margin-top:0;\">Pasarela de firma presencial<\/h2>\n            <p style=\"margin-top:0;\">Pega aqu\u00ed la URL \u00fanica de firma generada en Sinergia y env\u00edala a la tablet.<\/p>\n\n            <label for=\"fps-sign-url\" style=\"display:block;font-weight:600;margin-bottom:8px;\">URL de firma<\/label>\n            <input\n                type=\"url\"\n                id=\"fps-sign-url\"\n                placeholder=\"https:\/\/...\"\n                style=\"width:100%;padding:12px;border:1px solid #ccc;border-radius:8px;margin-bottom:16px;box-sizing:border-box;\"\n            >\n\n            <label for=\"fps-expiry-minutes\" style=\"display:block;font-weight:600;margin-bottom:8px;\">Caducidad del enlace (minutos)<\/label>\n            <input\n                type=\"number\"\n                id=\"fps-expiry-minutes\"\n                min=\"1\"\n                max=\"120\"\n                value=\"15\"\n                style=\"width:120px;padding:12px;border:1px solid #ccc;border-radius:8px;margin-bottom:16px;box-sizing:border-box;\"\n            >\n\n            <div style=\"display:flex;gap:12px;flex-wrap:wrap;\">\n                <button id=\"fps-send-btn\" style=\"padding:12px 18px;border:none;border-radius:8px;cursor:pointer;background:#1d4ed8;color:#fff;\">\n                    Enviar a tablet\n                <\/button>\n\n                <button id=\"fps-clear-btn\" style=\"padding:12px 18px;border:none;border-radius:8px;cursor:pointer;background:#6b7280;color:#fff;\">\n                    Vaciar tablet\n                <\/button>\n            <\/div>\n\n            <div id=\"fps-admin-message\" style=\"margin-top:16px;\"><\/div>\n\n            <div id=\"fps-admin-status\" style=\"margin-top:20px;padding:16px;border:1px solid #e5e7eb;border-radius:10px;background:#f9fafb;\">\n                <strong>Estado actual:<\/strong>\n                <div id=\"fps-status-content\" style=\"margin-top:8px;\">Comprobando\u2026<\/div>\n            <\/div>\n        <\/div>\n\n        <script>\n        (function(){\n            const sendBtn = document.getElementById('fps-send-btn');\n            const clearBtn = document.getElementById('fps-clear-btn');\n            const input = document.getElementById('fps-sign-url');\n            const minutesInput = document.getElementById('fps-expiry-minutes');\n            const msg = document.getElementById('fps-admin-message');\n            const status = document.getElementById('fps-status-content');\n\n            function showMessage(text, ok = true) {\n                msg.innerHTML =\n                    '<div style=\"padding:12px;border-radius:8px;background:' +\n                    (ok ? '#e8f7ec' : '#fdeaea') +\n                    ';color:' +\n                    (ok ? '#1f6b38' : '#8a1f1f') +\n                    ';\">' + text + '<\/div>';\n            }\n\n            function formatDate(unixTs) {\n                if (!unixTs) return '-';\n                return new Date(unixTs * 1000).toLocaleString('es-ES');\n            }\n\n            async function refreshStatus() {\n                try {\n                    const res = await fetch('https:\/\/testweb.larueca.org\/index.php\/wp-json\/fps\/v1\/get-url?t=' + Date.now(), {\n                        cache: 'no-store'\n                    });\n\n                    const raw = await res.text();\n\n                    let data;\n                    try {\n                        data = JSON.parse(raw);\n                    } catch (e) {\n                        status.innerHTML =\n                            '<div style=\"margin-top:8px;\">No se ha podido interpretar la respuesta del servidor.<\/div>';\n                        return;\n                    }\n\n                    if (data.success && data.url) {\n                        status.innerHTML =\n                            '<div style=\"margin-top:8px;\">URL activa<\/div>' +\n                            '<div style=\"word-break:break-all;margin-top:6px;\">' + data.url + '<\/div>' +\n                            '<div style=\"margin-top:8px;\">Caduca: ' + formatDate(data.expires_at) + '<\/div>';\n                    } else {\n                        status.innerHTML =\n                            '<div style=\"margin-top:8px;\">No hay ninguna firma activa.<\/div>';\n                    }\n                } catch (e) {\n                    status.innerHTML =\n                        '<div style=\"margin-top:8px;\">No se ha podido comprobar.<\/div>';\n                }\n            }\n\n            sendBtn.addEventListener('click', async function() {\n                const url = input.value.trim();\n                let minutes = parseInt(minutesInput.value, 10);\n\n                if (!url) {\n                    showMessage('Debes pegar una URL.', false);\n                    return;\n                }\n\n                if (!minutes || minutes < 1) {\n                    minutes = 15;\n                }\n\n                try {\n                    const res = await fetch('https:\/\/testweb.larueca.org\/index.php\/wp-json\/fps\/v1\/set-url', {\n                        method: 'POST',\n                        headers: {\n                            'Content-Type': 'application\/json'\n                        },\n                        body: JSON.stringify({\n                            url: url,\n                            minutes: minutes\n                        })\n                    });\n\n                    const raw = await res.text();\n\n                    let data;\n                    try {\n                        data = JSON.parse(raw);\n                    } catch (e) {\n                        showMessage('Respuesta no v\u00e1lida del servidor.', false);\n                        return;\n                    }\n\n                    if (data.success) {\n                        showMessage('URL enviada a la tablet correctamente.');\n                        refreshStatus();\n                    } else {\n                        showMessage(data.message || 'Error al guardar la URL.', false);\n                    }\n                } catch(e) {\n                    showMessage('Error de conexi\u00f3n.', false);\n                }\n            });\n\n            clearBtn.addEventListener('click', async function() {\n                try {\n                    const res = await fetch('https:\/\/testweb.larueca.org\/index.php\/wp-json\/fps\/v1\/clear-url', {\n                        method: 'POST',\n                        headers: {\n                            'Content-Type': 'application\/json'\n                        },\n                        body: JSON.stringify({})\n                    });\n\n                    const raw = await res.text();\n\n                    let data;\n                    try {\n                        data = JSON.parse(raw);\n                    } catch (e) {\n                        showMessage('Respuesta no v\u00e1lida del servidor.', false);\n                        return;\n                    }\n\n                    if (data.success) {\n                        input.value = '';\n                        showMessage('Tablet vaciada correctamente.');\n                        refreshStatus();\n                    } else {\n                        showMessage(data.message || 'No se pudo vaciar.', false);\n                    }\n                } catch(e) {\n                    showMessage('Error de conexi\u00f3n.', false);\n                }\n            });\n\n            refreshStatus();\n            setInterval(refreshStatus, 10000);\n        })();\n        <\/script>\n        \n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-6","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/testweb.larueca.org\/index.php\/wp-json\/wp\/v2\/pages\/6","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/testweb.larueca.org\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/testweb.larueca.org\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/testweb.larueca.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/testweb.larueca.org\/index.php\/wp-json\/wp\/v2\/comments?post=6"}],"version-history":[{"count":2,"href":"https:\/\/testweb.larueca.org\/index.php\/wp-json\/wp\/v2\/pages\/6\/revisions"}],"predecessor-version":[{"id":11,"href":"https:\/\/testweb.larueca.org\/index.php\/wp-json\/wp\/v2\/pages\/6\/revisions\/11"}],"wp:attachment":[{"href":"https:\/\/testweb.larueca.org\/index.php\/wp-json\/wp\/v2\/media?parent=6"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}