diff --git a/src/pages/SettingsPage.js b/src/pages/SettingsPage.js
index be1bb8b..0de8739 100644
--- a/src/pages/SettingsPage.js
+++ b/src/pages/SettingsPage.js
@@ -2,7 +2,7 @@ import { isDarkTheme, toggleTheme } from '../services/theme.js';
import { icons } from '../services/icons.js';
import { apiGet, apiPut } from '../services/apiClient.js';
import { showToast } from '../services/toast.js';
-import { encryptVeriFactuPassword, formatVeriFactuError, getVeriFactuFormats, getVeriFactuHealth, registerVeriFactuCertificate, saveVeriFactuToken, getVeriFactuToken, clearVeriFactuToken } from '../services/verifactu.js';
+import { encryptVeriFactuPassword, formatVeriFactuError, getVeriFactuFormats, getVeriFactuHealth, getVeriFactuTokenStatus, initVeriFactuStatus, registerVeriFactuCertificate } from '../services/verifactu.js';
function decodeTokenPayload(token) {
try {
@@ -155,8 +155,7 @@ export function renderSettingsPage() {
-
-
+
@@ -203,27 +202,19 @@ export function renderSettingsPage() {
const verifactuCertName = container.querySelector('#verifactu-cert-name');
const verifactuCertFile = container.querySelector('#verifactu-cert-file');
const verifactuCertPassword = container.querySelector('#verifactu-cert-password');
- const clearTokenBtn = container.querySelector('#verifactu-clear-token-btn');
-
- const renderVeriFactuTokenStatus = () => {
- const token = getVeriFactuToken();
- if (token) {
- verifactuStatus.textContent = `Token activo: ${token.slice(0, 8)}...`;
- clearTokenBtn.style.display = '';
- } else {
- clearTokenBtn.style.display = 'none';
+ async function renderVeriFactuTokenStatus() {
+ try {
+ const status = await getVeriFactuTokenStatus();
+ verifactuStatus.textContent = status?.active
+ ? 'Certificado activo. El sistema está listo para facturar.'
+ : 'Sin certificado registrado.';
+ } catch {
+ verifactuStatus.textContent = '';
}
- };
+ }
renderVeriFactuTokenStatus();
- clearTokenBtn.addEventListener('click', () => {
- clearVeriFactuToken();
- verifactuStatus.textContent = 'Token eliminado.';
- clearTokenBtn.style.display = 'none';
- showToast('Token de VeriFactu eliminado', 'success');
- });
-
verifactuCertFile.addEventListener('change', () => {
const file = verifactuCertFile.files?.[0];
if (!file) return;
@@ -354,13 +345,9 @@ export function renderSettingsPage() {
return;
}
- if (result.token) {
- saveVeriFactuToken(result.token);
- renderVeriFactuTokenStatus();
- }
- const tokenHint = result.token ? ` Token: ${result.token.slice(0, 8)}...` : '';
- verifactuStatus.textContent = `Certificado registrado.${tokenHint}`;
+ verifactuStatus.textContent = 'Certificado registrado. El sistema está listo para facturar.';
showToast('Certificado registrado en VeriFactu', 'success');
+ initVeriFactuStatus();
} catch (error) {
const errorMessage = formatVeriFactuError(error);
verifactuStatus.textContent = `Error al registrar certificado: ${errorMessage}`;
diff --git a/src/services/session.js b/src/services/session.js
index 3b8be00..75e8b03 100644
--- a/src/services/session.js
+++ b/src/services/session.js
@@ -1,4 +1,5 @@
import { auth } from './auth.js';
+import { initVeriFactuStatus, resetVeriFactuStatus } from './verifactu.js';
const SESSION_TIMEOUT_MS = Number(import.meta.env.VITE_SESSION_TIMEOUT_MS || 15 * 60 * 1000);
const SESSION_WARNING_MS = Number(import.meta.env.VITE_SESSION_WARNING_MS || 60 * 1000);
@@ -166,11 +167,13 @@ function bindAuthListeners() {
window.addEventListener('auth:login', () => {
removeWarningOverlay();
resetSessionTimers();
+ initVeriFactuStatus();
});
window.addEventListener('auth:logout', () => {
removeWarningOverlay();
clearTimers();
+ resetVeriFactuStatus();
});
}
diff --git a/src/services/verifactu.js b/src/services/verifactu.js
index 80b510a..97ebdfa 100644
--- a/src/services/verifactu.js
+++ b/src/services/verifactu.js
@@ -1,22 +1,30 @@
import forge from 'node-forge';
-import { apiGet, apiPost } from './apiClient.js';
+import { apiGet, apiPost, apiRequest } from './apiClient.js';
+
+const VERIFACTU_URL = import.meta.env.VITE_VERIFACTU_URL ?? 'http://localhost:6789';
let cachedPublicKeyPem = null;
+let verifactuActive = false;
+let verifactuToken = null;
-const VERIFACTU_TOKEN_KEY = 'verifactu_cert_token';
+export function isVeriFactuActive() {
+ return verifactuActive;
+}
-export function saveVeriFactuToken(token) {
- if (token) {
- localStorage.setItem(VERIFACTU_TOKEN_KEY, token);
+export async function initVeriFactuStatus() {
+ try {
+ const data = await apiGet('/api/VeriFactu/token');
+ verifactuActive = data?.active === true;
+ verifactuToken = data?.token ?? null;
+ } catch {
+ verifactuActive = false;
+ verifactuToken = null;
}
}
-export function getVeriFactuToken() {
- return localStorage.getItem(VERIFACTU_TOKEN_KEY) || null;
-}
-
-export function clearVeriFactuToken() {
- localStorage.removeItem(VERIFACTU_TOKEN_KEY);
+export function resetVeriFactuStatus() {
+ verifactuActive = false;
+ verifactuToken = null;
}
const VERIFACTU_ERROR_MESSAGES = {
@@ -101,10 +109,26 @@ export function formatVeriFactuError(errorLike) {
return raw;
}
+export async function getVeriFactuTokenStatus() {
+ return apiGet('/api/VeriFactu/token-status');
+}
+
export async function sendVeriFactuInvoice(payload) {
- return apiPost('/api/VeriFactu/facturas', payload);
+ if (!verifactuToken) throw new Error('No hay token de VeriFactu activo');
+ return apiRequest(`${VERIFACTU_URL}/api/v1/facturas`, {
+ method: 'POST',
+ auth: false,
+ headers: { Authorization: `Bearer ${verifactuToken}` },
+ body: payload
+ });
}
export async function cancelVeriFactuInvoice(payload) {
- return apiPost('/api/VeriFactu/facturas/anular', payload);
+ if (!verifactuToken) throw new Error('No hay token de VeriFactu activo');
+ return apiRequest(`${VERIFACTU_URL}/api/v1/facturas/anular`, {
+ method: 'POST',
+ auth: false,
+ headers: { Authorization: `Bearer ${verifactuToken}` },
+ body: payload
+ });
}
\ No newline at end of file