Ir al contenido

Autorizar VeriFactu

Firma digitalmente el documento legal que autoriza a Factux a enviar tus registros de facturación a la AEAT.

  1. Ve a Configuración > VeriFactu — se abre el panel de autorización.
  2. Clic en “Crear Autorización” — el sistema genera el documento legal.
  3. Revisa el documento en el formulario embebido — aparece un PDF con tus datos fiscales.
  4. Completa los campos requeridos:
    • Nombre del negocio: Pre-rellenado (editable)
    • Documento de identidad (NIF): Pre-rellenado (editable)
    • Fecha: Pre-rellenada con fecha actual (editable)
  5. Firma en el recuadro designado — usa ratón, trackpad o pantalla táctil.
  6. Clic en “Completar” — el documento se envía a DocuSeal.
  7. Espera unos segundos — el estado se actualiza automáticamente a “Firmada”.
CampoOrigenEditable
Nombre del negociobusinesses.legal_name o businesses.name
NIFbusinesses.tax_id
Fecha de autorizaciónFecha actual
Firma digitalObligatorio
  • Badge cambia a Firmada (verde).
  • Aparece la fecha de firma: “Firmada el 16/02/2026”.
  • Botón “Descargar Documento” disponible.
  • Toast de confirmación: “Autorización completada”.
  • Las facturas emitidas se envían automáticamente a VeriFactu.
MensajeCausaSolución
”Only business owners can create VeriFactu authorizations”No eres owner del negocioSolo el propietario puede autorizar
”Business already has a valid authorization”Ya existe autorización firmadaNo es necesario crear otra
”DOCUSEAL_API_KEY not configured”Error de configuración del servidorContactar soporte técnico
Edge Function: create-verifactu-authorization

Trigger: Usuario clic en “Crear Autorización”.

Validaciones:

  1. Usuario autenticado
  2. Usuario es owner del negocio (user_businesses.role = 'owner')
  3. No existe autorización activa (status IN ('pending', 'signed'))

Flujo:

  1. Carga datos del negocio: name, legal_name, tax_id, email
  2. Genera texto legal reemplazando placeholders:
    {{BUSINESS_NAME}} → businesses.legal_name || businesses.name
    {{BUSINESS_TAX_ID}} → businesses.tax_id
    {{CURRENT_DATE}} → new Date().toLocaleDateString('es-ES')
  3. Genera HTML del documento con estilos
  4. Crea submission en DocuSeal API:
    POST https://api.docuseal.co/api/submissions
    Body: {
    template_id: DOCUSEAL_TEMPLATE_ID,
    send_email: false,
    submitters: [{
    role: "Primera Parte",
    email: business.email || user.email,
    name: businessName,
    fields: [...]
    }]
    }
  5. Extrae embed_src de respuesta DocuSeal
  6. INSERT en verifactu_authorizations:
    INSERT INTO verifactu_authorizations (
    business_id,
    docuseal_submission_id,
    status,
    business_name,
    business_tax_id,
    signer_email,
    legal_text,
    created_by,
    embed_url,
    docuseal_document_url
    ) VALUES (...)
  7. Retorna authorization con embed_url

Variables de entorno:

  • DOCUSEAL_API_KEY: API key
  • DOCUSEAL_TEMPLATE_ID: ID de plantilla
  • DOCUSEAL_API_URL: URL base (default: https://api.docuseal.co)

Output:

{
"success": true,
"authorization": {
"id": "uuid",
"status": "pending",
"embed_url": "https://docuseal.co/s/..."
}
}
Webhook: docuseal-webhook

Trigger: DocuSeal envía POST cuando cambia estado del documento.

Eventos:

  • form.completed: Usuario completó firma
  • form.declined: Usuario rechazó firma

Flujo para form.completed:

  1. Valida signature del webhook
  2. Extrae submission.id del payload
  3. Busca en DB:
    SELECT * FROM verifactu_authorizations
    WHERE docuseal_submission_id = '<submission_id>'
  4. Actualiza registro:
    UPDATE verifactu_authorizations
    SET status = 'signed',
    signed_at = NOW(),
    signed_document_url = '<documents[0].url>'
    WHERE id = '<authorization_id>'

Payload ejemplo:

{
"event_type": "form.completed",
"timestamp": "2026-02-16T10:30:00Z",
"data": {
"submission": {
"id": "12345",
"status": "completed",
"email": "empresa@ejemplo.com"
},
"documents": [{
"url": "https://docuseal.co/d/signed.pdf"
}]
}
}
Componente React: VeriFactuAuthorizationForm

Ubicación: src/features/invoices/sub-modules/verifactu/components/VeriFactuAuthorizationForm.tsx

Estados:

  1. Sin autorización: Muestra botón “Crear Autorización”
  2. Pendiente: Muestra iframe con DocuSeal embed + polling cada 3s
  3. Firmada: Muestra badge verde + botón descarga + botón revocar
  4. Rechazada/Revocada: Muestra alerta + botón “Crear Nueva Autorización”

Polling:

useEffect(() => {
if (authorization?.status === 'pending' && showEmbeddedForm) {
pollingRef.current = setInterval(() => {
refetch(); // Query a BD cada 3s
}, 3000);
}
return () => clearInterval(pollingRef.current);
}, [authorization?.status, showEmbeddedForm]);

Auto-cierre al firmar:

useEffect(() => {
if (authorization?.status === 'signed') {
clearInterval(pollingRef.current);
setShowEmbeddedForm(false);
toast({ title: '¡Autorización completada!' });
}
}, [authorization?.status]);
Query de diagnóstico
-- Ver estado completo de autorización
SELECT
id,
business_id,
status,
signed_at,
declined_at,
revoked_at,
docuseal_submission_id,
docuseal_document_url,
signer_email,
created_at
FROM verifactu_authorizations
WHERE business_id = '<business_id>'
ORDER BY created_at DESC
LIMIT 1;

Estados posibles:

  • pending: Esperando firma
  • signed: Firmada y activa
  • declined: Usuario rechazó
  • revoked: Owner revocó
  • expired: Expirada (uso futuro)