Skip to content

📚 Documentación del Módulo Verifactu ​

Versión en Castellano ​


📋 Índice ​

  1. Introducción
  2. Requisitos del Sistema
  3. Instalación
  4. Configuración Inicial
  5. Gestión de Certificados
  6. Creación de Facturas
  7. Gestión de Líneas de Factura
  8. Confirmación de Facturas
  9. Registro en AEAT
  10. Encadenamiento de Facturas
  11. Cancelación de Facturas
  12. Consultas a AEAT
  13. Generación de Documentos
  14. Códigos QR de Verificación
  15. Manejo de Errores
  16. API y Servicios
  17. Troubleshooting

1. Introducción ​

¿Qué es Verifactu? ​

Verifactu es el sistema de la Agencia Tributaria Española (AEAT) para la verificación y trazabilidad de facturas electrónicas. Este módulo implementa la integración completa con Verifactu según la normativa vigente.

Características Principales ​

  • ✅ Gestión completa de facturas conformes a normativa Verifactu
  • ✅ Encadenamiento criptográfico mediante hashes SHA-256
  • ✅ Integración directa con AEAT mediante SOAP
  • ✅ Certificados digitales para firma electrónica
  • ✅ Códigos QR de verificación
  • ✅ Multi-tenant con soporte para múltiples empresas
  • ✅ Auditoría completa de todas las operaciones
  • ✅ Gestión de errores y reintentos automáticos

Normativa Aplicable ​

  • Reglamento que regula las obligaciones de facturación
  • Orden HAC/1177/2024 de Verifactu
  • Especificaciones técnicas de la AEAT

2. Requisitos del Sistema ​

Requisitos Técnicos ​

PHP >= 8.4
Laravel >= 12.x
Filament >= 4.x
OpenSSL Extension
SOAP Extension
GD/Imagick Extension (para QR)

Requisitos Legales ​

  • Certificado digital válido emitido por autoridad certificadora reconocida
  • NIF de empresa española
  • Alta en el sistema Verifactu de AEAT

Base de Datos ​

  • SQLite, MySQL, PostgreSQL o SQL Server
  • Soporte para transacciones
  • Charset UTF-8

3. Instalación ​

Paso 1: Instalación del Módulo ​

bash
# Clonar o copiar el módulo en /Modules
cd Modules
git clone [repositorio] Verifactu

Paso 2: Instalar Dependencias ​

bash
composer require bacon/bacon-qr-code
composer require chillerlan/php-qrcode

Paso 3: Ejecutar Migraciones ​

bash
php artisan migrate

Paso 4: Publicar Configuración (Opcional) ​

bash
php artisan vendor:publish --tag=verifactu-config

4. Configuración Inicial ​

Variables de Entorno ​

Añade al .env:

env
VERIFACTU_ENVIRONMENT=sandbox  # sandbox | production
VERIFACTU_SOAP_ENDPOINT=https://prewww2.aeat.es/wlpl/TIKE-CONT/ws/SuministroInformacion
VERIFACTU_QR_URL=https://prewww2.aeat.es/wlpl/TIKE-CONT/ValidarQR

Entornos Disponibles ​

Sandbox (Pruebas) ​

SOAP: https://prewww2.aeat.es/wlpl/TIKE-CONT/ws/SuministroInformacion
QR: https://prewww2.aeat.es/wlpl/TIKE-CONT/ValidarQR

Producción ​

SOAP: https://www2.agenciatributaria.gob.es/wlpl/TIKE-CONT/ws/SuministroInformacion
QR: https://www2.agenciatributaria.gob.es/wlpl/TIKE-CONT/ValidarQR

5. Gestión de Certificados ​

5.1 Formatos Soportados ​

  • P12/PFX: Formato estándar (recomendado)
  • PEM: Conversión automática interna

5.2 Crear un Certificado ​

  1. Acceder a Verifactu → Certificados
  2. Clic en Crear Certificado
  3. Completar datos:
    • Nombre: Identificador interno
    • Descripción: Opcional
    • Archivo P12: Subir certificado
    • Contraseña: Contraseña del certificado
    • Entorno: Sandbox o Producción

5.3 Datos del Sistema ​

Configurar información del software:

Nombre del Sistema: ERP Building MM
Versión: 1.0
ID del Sistema: 01
Número de Instalación: 1
Proveedor NIF: [NIF de tu empresa]
Solo Verifactu: Sí
Múltiples Obligaciones: No

5.4 Validación del Certificado ​

El sistema valida automáticamente:

  • ✅ Formato del certificado
  • ✅ Validez temporal
  • ✅ NIF del emisor
  • ✅ Contraseña correcta

6. Creación de Facturas ​

6.1 Estados de una Factura ​

DRAFT → CONFIRMED → REGISTERED → [CANCELLED]
  • Draft: Borrador editable
  • Confirmed: Confirmada con hash generado
  • Registered: Registrada en AEAT
  • Cancelled: Anulada

6.2 Crear Borrador de Factura ​

  1. Acceder a Verifactu → Facturas
  2. Clic en Crear Factura
  3. Completar datos básicos:

Datos Obligatorios ​

✓ Certificado Verifactu
✓ Número de serie (ej: FA2025/001)
✓ Fecha de emisión
✓ NIF del emisor
✓ Nombre del emisor
✓ Tipo de factura
✓ Descripción de la operación

Tipos de Factura ​

CódigoDescripción
F1Factura completa (con destinatario)
F2Factura simplificada
F3Factura sin destinatario identificado
R1Rectificativa (error fundado en derecho)
R2Rectificativa (Art. 80.1, 80.2, 80.6 LIVA)
R3Rectificativa (Art. 80.3 LIVA)
R4Rectificativa (resto)
R5Rectificativa en facturas simplificadas

6.3 Encadenamiento Automático ​

El sistema automáticamente:

  • ✅ Detecta si es la primera factura
  • ✅ Obtiene datos de la factura anterior
  • ✅ Asigna el hash de encadenamiento

7. Gestión de Líneas de Factura ​

7.1 Añadir Líneas ​

Desde el borrador de factura:

  1. Ir a pestaña Líneas de factura
  2. Clic en Añadir línea
  3. Completar datos:
✓ Descripción
✓ Cantidad
✓ Unidad (ud, h, kg, etc)
✓ Precio unitario
✓ Descuento % (opcional)
✓ Tipo de impuesto (IVA, IGIC, IPSI)
✓ Porcentaje de IVA (21%, 10%, 4%)
✓ Calificación de operación

7.2 Calificaciones de Operación ​

CódigoDescripciónCuándo usar
S1Sujeta y NO exenta sin inversiónOperaciones normales (95% casos)
S2Sujeta y NO exenta con inversiónOro, chatarra, construcción
S3Sujeta y exentaSanidad, educación, seguros
N1NO sujeta (Art. 7, 14)Exportaciones fuera UE
N2NO sujeta (Art. 20-24)Entregas intracomunitarias

7.3 Cálculos Automáticos ​

El sistema calcula automáticamente:

  • ✅ Subtotal = (Precio × Cantidad) - Descuento
  • ✅ IVA = Subtotal × (Tipo IVA / 100)
  • ✅ Total línea = Subtotal + IVA
  • ✅ Totales de factura (se actualizan en tiempo real)

7.4 Desglose de Impuestos ​

Generado automáticamente agrupando líneas por:

  • Tipo de impuesto (IVA, IGIC, IPSI)
  • Porcentaje aplicado
  • Calificación de operación

8. Confirmación de Facturas ​

8.1 Requisitos para Confirmar ​

Antes de confirmar, verificar:

  • ✅ Al menos 1 línea de factura
  • ✅ Totales calculados correctamente
  • ✅ Destinatario (si es factura F1)
  • ✅ Desglose de impuestos generado

8.2 Proceso de Confirmación ​

  1. Desde la factura en borrador
  2. Clic en Confirmar factura
  3. Revisar datos
  4. Confirmar acción

8.3 Acciones Automáticas al Confirmar ​

El sistema realiza:

1. Validación de datos obligatorios
2. Detección de encadenamiento:
   - Si es primera factura → first_record = true
   - Si no → Obtiene hash de factura anterior
3. Generación del hash SHA-256
4. Cambio de estado a CONFIRMED
5. Creación del registro de cadena
6. Log de auditoría

8.4 Hash de Encadenamiento ​

El hash se genera con:

  • NIF del emisor
  • Número de serie
  • Fecha y hora de emisión
  • Importes
  • Hash de la factura anterior (si no es la primera)

⚠️ Importante: Una vez confirmada, la factura NO puede editarse.


9. Registro en AEAT ​

9.1 Envío a AEAT ​

Desde una factura confirmada:

  1. Clic en Registrar en AEAT
  2. El sistema envía automáticamente vía SOAP
  3. Esperar respuesta

9.2 Respuestas Posibles ​

✅ Registro Exitoso ​

json
{
  "status": "ok",
  "csv": "ABC123XYZ789",
  "timestamp": "2025-11-03T10:30:00"
}

Se genera:

  • CSV (Código Seguro de Verificación)
  • Código QR
  • Estado cambia a REGISTERED

❌ Error en Registro ​

json
{
  "status": "error",
  "errors": [
    {
      "code": "1207",
      "description": "Error interno en el servidor",
      "type": "soap_fault",
      "level": "fatal"
    }
  ]
}

9.3 Reintentos Automáticos ​

El sistema gestiona:

  • Contador de errores
  • Contador de reintentos
  • Último error registrado
  • Botón manual de reintento

9.4 Errores Comunes ​

CódigoDescripciónSolución
1207Error interno servidorReintentar más tarde
2001Certificado inválidoVerificar certificado
3001Datos incorrectosRevisar formato de datos
4001Hash inválidoVerificar encadenamiento

10. Encadenamiento de Facturas ​

10.1 Concepto ​

Cada factura contiene el hash de la anterior, creando una cadena inmutable:

FA2025/001 → Hash A
FA2025/002 → Hash B (incluye Hash A)
FA2025/003 → Hash C (incluye Hash B)

10.2 Primera Factura ​

La primera factura de un certificado:

first_record = true
previous_hash = null
previous_series_number = null

10.3 Facturas Subsiguientes ​

Las siguientes facturas automáticamente toman:

first_record = false
previous_hash = [hash de factura anterior]
previous_series_number = [serie de factura anterior]
previous_issuer_nif = [NIF de factura anterior]
previous_issue_date = [fecha de factura anterior]

10.4 Validación de Cadena ​

El sistema valida:

  • ✅ Existencia de factura anterior
  • ✅ Hash coincide con el registrado
  • ✅ Mismo certificado
  • ✅ Orden cronológico

10.5 Tabla de Cadenas ​

verifactu_invoice_chains registra:

  • ID de factura actual
  • ID de factura anterior
  • Posición en la cadena
  • Validación de integridad

11. Cancelación de Facturas ​

11.1 Requisitos para Cancelar ​

  • ✅ Factura registrada en AEAT (status = registered)
  • ✅ No tener cancelación pendiente
  • ✅ No estar ya cancelada

11.2 Proceso de Cancelación ​

  1. Desde factura registrada
  2. Clic en Cancelar Factura
  3. Completar formulario:
✓ Motivo de cancelación (texto libre)
✓ Tipo de cancelación:
  - Error en los datos
  - Factura duplicada
  - Solicitud del cliente
  - Otro motivo
  1. Confirmar cancelación

11.3 Registro de Cancelación ​

Se crea registro independiente con:

  • Referencia a factura original
  • Motivo y tipo de cancelación
  • Encadenamiento propio
  • Hash de cancelación
  • Envío a AEAT

11.4 Efectos de la Cancelación ​

  • Estado factura → CANCELLED
  • La factura permanece en la cadena
  • Se registra en AEAT
  • Se genera CSV de cancelación

12. Consultas a AEAT ​

12.1 Consultar Estado de Factura ​

Para facturas con CSV:

  1. Clic en Consultar Estado
  2. El sistema consulta AEAT en tiempo real
  3. Muestra resultado:
    • Estado actual
    • Fecha de registro
    • CSV

12.2 Consulta Detallada ​

Proporciona:

  • Estado completo del registro
  • Indicador de paginación
  • Registros encontrados
  • Errores si existen

12.3. Actualizar Estado ​

Refresca el estado desde AEAT:

  • Verifica si sigue registrada
  • Actualiza información local
  • Detecta cambios

12.4 Consulta Masiva ​

Para múltiples facturas:

  1. Seleccionar facturas
  2. Acción masiva → Actualizar todos los estados
  3. El sistema consulta cada una
  4. Muestra resumen:
    • Actualizadas
    • Errores

13. Generación de Documentos ​

13.1 Formatos Disponibles ​

  • XML Verifactu (sin firmar)
  • XML firmado (con certificado digital)
  • PDF (representación visual)
  • Ticket (formato 80mm para TPV)

13.2 Descargar XML ​

php
// Sin firma
$xml = $invoice->generateFacturaeXml();

// Con firma
$signedXml = $invoice->generateSignedFacturaeXml();

Acciones en UI:

  • Descargar Facturae XML
  • Descargar Facturae Firmado

13.3 Generar PDF ​

Representación visual profesional con:

  • Datos de emisor
  • Datos de receptor
  • Líneas de factura
  • Desglose de impuestos
  • Totales
  • Código QR (si está registrada)
  • CSV de verificación

13.4 Generar Ticket ​

Formato optimizado para impresoras térmicas 80mm:

  • Información simplificada
  • Líneas de productos
  • Totales
  • QR Code grande
  • Diseño monocromo

13.5 Descarga Masiva ​

Para múltiples facturas:

  1. Seleccionar facturas
  2. Descargar Facturas
  3. Elegir formato:
    • XML sin firmar
    • XML firmado
    • PDF
    • ZIP (todos los formatos)

Se genera archivo ZIP con estructura:

/xml/
  facturae_FA2025-001.xml
  facturae_FA2025-002.xml
/xml_signed/
  facturae_FA2025-001_signed.xml
/pdf/
  factura_FA2025-001.pdf

14. Códigos QR de Verificación ​

14.1 Generación de QR ​

Automática al registrar en AEAT:

  • Contiene URL de verificación AEAT
  • Incluye CSV
  • Formato PNG

14.2 Datos en el QR ​

https://www2.aeat.es/wlpl/TIKE-CONT/ValidarQR?CSV=ABC123XYZ789

14.3 Visualizar QR ​

Desde factura registrada:

  • Ver QR: Modal con código
  • Descargar QR: Archivo PNG

Opciones de descarga:

  • Formato: PNG o SVG
  • Tamaño: 200px, 300px, 400px, 500px

14.4 Verificación Pública ​

Cualquier persona puede:

  1. Escanear QR con móvil
  2. Accede a web AEAT
  3. Verifica autenticidad de factura

15. Manejo de Errores ​

15.1 Tipos de Errores ​

Errores de Cabecera ​

  • Datos del emisor incorrectos
  • Certificado inválido
  • Formato de fecha incorrecto

Errores de Registro ​

  • Datos de factura incorrectos
  • Hash inválido
  • Encadenamiento roto

Errores SOAP Fault ​

  • Error de servidor AEAT
  • Timeout de conexión
  • Certificado SSL inválido

15.2 Sistema de Reintentos ​

Configuración automática:

Max reintentos: 3
Intervalo: Exponencial (1min, 5min, 15min)
Después de 3 fallos: Reintento manual

15.3 Logs y Auditoría ​

Cada operación registra:

  • Timestamp
  • Usuario
  • Acción realizada
  • Datos modificados
  • Resultado (éxito/error)
  • Mensaje de error (si aplica)

Acceso a logs: Verifactu → Auditoría

15.4 Notificaciones ​

El sistema notifica:

  • ✅ Registro exitoso
  • ❌ Errores de envío
  • ⚠️ Advertencias
  • 🔄 Actualizaciones de estado

16. API y Servicios ​

16.1 Servicios Principales ​

VerifactuService ​

php
use Modules\Verifactu\Services\VerifactuService;

// Configurar
VerifactuService::config([
    'certPath' => '/path/to/cert.p12',
    'certPassword' => 'password',
    'soapEndpoint' => 'https://...',
]);

// Registrar factura
$response = VerifactuService::registerInvoice($invoiceSubmission);

// Consultar
$response = VerifactuService::queryInvoices($query);

// Cancelar
$response = VerifactuService::cancelInvoice($cancellation);

HashGeneratorService ​

php
use Modules\Verifactu\Services\HashGeneratorService;

$hash = HashGeneratorService::generate($invoiceSubmission);
// Retorna: SHA-256 hash en hexadecimal

QrGeneratorService ​

php
use Modules\Verifactu\Services\QrGeneratorService;

$qr = QrGeneratorService::generateQr(
    $invoiceRecord,
    $baseUrl,
    $destination, // STRING | FILE
    $size,        // 200-500px
    $renderer     // GD | SVG
);

XmlSignerService ​

php
use Modules\Verifactu\Services\XmlSignerService;

$signedXml = XmlSignerService::signXml(
    $xmlString,
    $certPath,
    $certPassword
);

16.2 Facades ​

php
use Modules\Verifactu\Facades\Verifactu;

// Configurar para empresa
Verifactu::forCompany($companyId);

// Registrar
$response = Verifactu::registerInvoice($submission);

// Generar QR
$qr = Verifactu::generateInvoiceQr($record);

16.3 Modelos Eloquent ​

VerifactuInvoice ​

php
$invoice = VerifactuInvoice::find($id);

// Estados
$invoice->isDraft();
$invoice->isConfirmed();
$invoice->isRegistered();
$invoice->isCancelled();

// Acciones
$invoice->confirm();
$invoice->recalculateTotals();
$invoice->updateBreakdownFromLines();

// Relaciones
$invoice->lines;
$invoice->breakdowns;
$invoice->recipients;
$invoice->certificate;
$invoice->cancellation;

VerifactuCertificate ​

php
$cert = VerifactuCertificate::find($id);

$cert->getCertificatePath();
$cert->getDecryptedPassword();
$cert->isValid();
$cert->expiresIn(); // días restantes

16.4 Eventos ​

php
// Evento cuando se actualizan totales
event(new InvoiceTotalsUpdated($invoice));

// Listener
public function handle(InvoiceTotalsUpdated $event)
{
    $invoice = $event->invoice;
    // ... lógica
}

17. Troubleshooting ​

17.1 Problemas Comunes ​

Los totales no se actualizan ​

Problema: Añado líneas pero los totales siguen en 0€

Solución:

php
// En Tinker
$invoice = VerifactuInvoice::find($id);
$invoice->recalculateTotals();

Verificar que VerifactuInvoiceLine tiene el evento saved:

php
static::saved(function ($line) {
    $line->invoice?->recalculateTotals();
});

El encadenamiento no funciona ​

Problema: La factura no toma el hash anterior

Solución:

  1. Verificar que la factura anterior está confirmada (tiene hash)
  2. Verificar que usan el mismo certificado
  3. Confirmar orden cronológico
php
// Verificar en Tinker
$prev = VerifactuInvoice::where('status', 'confirmed')
    ->where('verifactu_certificate_id', $certId)
    ->latest('issue_date')
    ->first();

$prev->hash; // Debe tener valor

Error 1207 de AEAT ​

Problema: "Error interno en el servidor"

Solución:

  • Es un error del servidor sandbox de AEAT
  • Reintentar más tarde
  • En producción es muy raro

Certificado no válido ​

Problema: "Certificate verification failed"

Solución:

  1. Verificar formato P12/PFX
  2. Verificar contraseña correcta
  3. Verificar que no ha expirado
  4. Verificar que es de representación AEAT

QR no se genera ​

Problema: El QR aparece vacío

Solución:

  1. Verificar que la factura está registrada
  2. Verificar que tiene CSV
  3. Verificar extensión GD instalada:
bash
php -m | grep gd

17.2 Comandos Útiles ​

bash
# Limpiar caché
php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear

# Regenerar autoload
composer dump-autoload -o

# Verificar migraciones
php artisan migrate:status

# Tinker para debug
php artisan tinker

17.3 Logs ​

Ubicación de logs:

storage/logs/laravel.log

Buscar errores de Verifactu:

bash
tail -f storage/logs/laravel.log | grep Verifactu

17.4 Debugging en Tinker ​

php
// Ver última factura
$invoice = VerifactuInvoice::latest()->first();

// Ver estructura completa
$invoice->load(['lines', 'breakdowns', 'recipients', 'certificate']);
dd($invoice);

// Recalcular totales
$invoice->recalculateTotals();

// Ver errores
$invoice->aeat_errors;

// Confirmar manualmente
$invoice->confirm();

// Ver cadena
$invoice->chainRecord;

📞 Soporte ​

Para soporte técnico:




📚 Verifactu Module Documentation ​

English Version ​


📋 Table of Contents ​

  1. Introduction
  2. System Requirements
  3. Installation
  4. Initial Configuration
  5. Certificate Management
  6. Invoice Creation
  7. Invoice Lines Management
  8. Invoice Confirmation
  9. AEAT Registration
  10. Invoice Chaining
  11. Invoice Cancellation
  12. AEAT Queries
  13. Document Generation
  14. Verification QR Codes
  15. Error Handling
  16. API and Services
  17. Troubleshooting

1. Introduction ​

What is Verifactu? ​

Verifactu is the Spanish Tax Agency (AEAT) system for electronic invoice verification and traceability. This module implements complete Verifactu integration according to current regulations.

Main Features ​

  • ✅ Complete invoice management compliant with Verifactu regulations
  • ✅ Cryptographic chaining using SHA-256 hashes
  • ✅ Direct AEAT integration via SOAP
  • ✅ Digital certificates for electronic signature
  • ✅ Verification QR codes
  • ✅ Multi-tenant with support for multiple companies
  • ✅ Complete audit trail of all operations
  • ✅ Error handling and automatic retries

Applicable Regulations ​

  • Invoicing obligations regulations
  • Order HAC/1177/2024 on Verifactu
  • AEAT technical specifications

2. System Requirements ​

Technical Requirements ​

PHP >= 8.4
Laravel >= 12.x
Filament >= 4.x
OpenSSL Extension
SOAP Extension
GD/Imagick Extension (for QR)
  • Valid digital certificate issued by recognized certification authority
  • Spanish company Tax ID (NIF)
  • Registration in AEAT Verifactu system

Database ​

  • SQLite, MySQL, PostgreSQL or SQL Server
  • Transaction support
  • UTF-8 charset

3. Installation ​

Step 1: Module Installation ​

bash
# Clone or copy module to /Modules
cd Modules
git clone [repository] Verifactu

Step 2: Install Dependencies ​

bash
composer require bacon/bacon-qr-code
composer require chillerlan/php-qrcode

Step 3: Run Migrations ​

bash
php artisan migrate

Step 4: Publish Configuration (Optional) ​

bash
php artisan vendor:publish --tag=verifactu-config

4. Initial Configuration ​

Environment Variables ​

Add to .env:

env
VERIFACTU_ENVIRONMENT=sandbox  # sandbox | production
VERIFACTU_SOAP_ENDPOINT=https://prewww2.aeat.es/wlpl/TIKE-CONT/ws/SuministroInformacion
VERIFACTU_QR_URL=https://prewww2.aeat.es/wlpl/TIKE-CONT/ValidarQR

Available Environments ​

Sandbox (Testing) ​

SOAP: https://prewww2.aeat.es/wlpl/TIKE-CONT/ws/SuministroInformacion
QR: https://preww2.aeat.es/wlpl/TIKE-CONT/ValidarQR

Production ​

SOAP: https://www2.agenciatributaria.gob.es/wlpl/TIKE-CONT/ws/SuministroInformacion
QR: https://www2.agenciatributaria.gob.es/wlpl/TIKE-CONT/ValidarQR

5. Certificate Management ​

5.1 Supported Formats ​

  • P12/PFX: Standard format (recommended)
  • PEM: Automatic internal conversion

5.2 Create a Certificate ​

  1. Access Verifactu → Certificates
  2. Click Create Certificate
  3. Complete data:
    • Name: Internal identifier
    • Description: Optional
    • P12 File: Upload certificate
    • Password: Certificate password
    • Environment: Sandbox or Production

5.3 System Data ​

Configure software information:

System Name: ERP Building MM
Version: 1.0
System ID: 01
Installation Number: 1
Provider NIF: [Your company NIF]
Only Verifactu: Yes
Multiple Obligations: No

5.4 Certificate Validation ​

System automatically validates:

  • ✅ Certificate format
  • ✅ Temporal validity
  • ✅ Issuer NIF
  • ✅ Correct password

6. Invoice Creation ​

6.1 Invoice States ​

DRAFT → CONFIRMED → REGISTERED → [CANCELLED]
  • Draft: Editable draft
  • Confirmed: Confirmed with generated hash
  • Registered: Registered in AEAT
  • Cancelled: Cancelled

6.2 Create Invoice Draft ​

  1. Access Verifactu → Invoices
  2. Click Create Invoice
  3. Complete basic data:

Required Fields ​

✓ Verifactu Certificate
✓ Series number (e.g.: FA2025/001)
✓ Issue date
✓ Issuer NIF
✓ Issuer name
✓ Invoice type
✓ Operation description

Invoice Types ​

CodeDescription
F1Complete invoice (with recipient)
F2Simplified invoice
F3Invoice without identified recipient
R1Rectifying (legally founded error)
R2Rectifying (Art. 80.1, 80.2, 80.6 LIVA)
R3Rectifying (Art. 80.3 LIVA)
R4Rectifying (other)
R5Rectifying simplified invoices

6.3 Automatic Chaining ​

The system automatically:

  • ✅ Detects if it's the first invoice
  • ✅ Gets previous invoice data
  • ✅ Assigns chaining hash

7. Invoice Lines Management ​

7.1 Add Lines ​

From invoice draft:

  1. Go to Invoice lines tab
  2. Click Add line
  3. Complete data:
✓ Description
✓ Quantity
✓ Unit (ud, h, kg, etc)
✓ Unit price
✓ Discount % (optional)
✓ Tax type (VAT, IGIC, IPSI)
✓ VAT percentage (21%, 10%, 4%)
✓ Operation qualification

7.2 Operation Qualifications ​

CodeDescriptionWhen to use
S1Subject and NOT exempt without inversionNormal operations (95% cases)
S2Subject and NOT exempt with inversionGold, scrap, construction
S3Subject and exemptHealth, education, insurance
N1NOT subject (Art. 7, 14)Exports outside EU
N2NOT subject (Art. 20-24)Intra-community deliveries

7.3 Automatic Calculations ​

System automatically calculates:

  • ✅ Subtotal = (Price × Quantity) - Discount
  • ✅ VAT = Subtotal × (VAT Rate / 100)
  • ✅ Line total = Subtotal + VAT
  • ✅ Invoice totals (update in real-time)

7.4 Tax Breakdown ​

Automatically generated by grouping lines by:

  • Tax type (VAT, IGIC, IPSI)
  • Applied percentage
  • Operation qualification

8. Invoice Confirmation ​

8.1 Requirements to Confirm ​

Before confirming, verify:

  • ✅ At least 1 invoice line
  • ✅ Totals calculated correctly
  • ✅ Recipient (if F1 invoice)
  • ✅ Tax breakdown generated

8.2 Confirmation Process ​

  1. From invoice in draft
  2. Click Confirm invoice
  3. Review data
  4. Confirm action

8.3 Automatic Actions on Confirm ​

The system performs:

1. Validation of required data
2. Chaining detection:
   - If first invoice → first_record = true
   - If not → Gets previous invoice hash
3. SHA-256 hash generation
4. Status change to CONFIRMED
5. Chain record creation
6. Audit log

8.4 Chaining Hash ​

Hash is generated with:

  • Issuer NIF
  • Series number
  • Issue date and time
  • Amounts
  • Previous invoice hash (if not first)

⚠️ Important: Once confirmed, invoice CANNOT be edited.


9. AEAT Registration ​

9.1 Send to AEAT ​

From confirmed invoice:

  1. Click Register in AEAT
  2. System automatically sends via SOAP
  3. Wait for response

9.2 Possible Responses ​

✅ Successful Registration ​

json
{
  "status": "ok",
  "csv": "ABC123XYZ789",
  "timestamp": "2025-11-03T10:30:00"
}

Generated:

  • CSV (Secure Verification Code)
  • QR Code
  • Status changes to REGISTERED

❌ Registration Error ​

json
{
  "status": "error",
  "errors": [
    {
      "code": "1207",
      "description": "Internal server error",
      "type": "soap_fault",
      "level": "fatal"
    }
  ]
}

9.3 Automatic Retries ​

System manages:

  • Error counter
  • Retry counter
  • Last recorded error
  • Manual retry button

9.4 Common Errors ​

CodeDescriptionSolution
1207Internal server errorRetry later
2001Invalid certificateVerify certificate
3001Incorrect dataCheck data format
4001Invalid hashVerify chaining

10. Invoice Chaining ​

10.1 Concept ​

Each invoice contains the hash of the previous one, creating an immutable chain:

FA2025/001 → Hash A
FA2025/002 → Hash B (includes Hash A)
FA2025/003 → Hash C (includes Hash B)

10.2 First Invoice ​

First invoice of a certificate:

first_record = true
previous_hash = null
previous_series_number = null

10.3 Subsequent Invoices ​

Following invoices automatically take:

first_record = false
previous_hash = [previous invoice hash]
previous_series_number = [previous invoice series]
previous_issuer_nif = [previous invoice NIF]
previous_issue_date = [previous invoice date]

10.4 Chain Validation ​

System validates:

  • ✅ Previous invoice existence
  • ✅ Hash matches recorded
  • ✅ Same certificate
  • ✅ Chronological order

10.5 Chains Table ​

verifactu_invoice_chains records:

  • Current invoice ID
  • Previous invoice ID
  • Position in chain
  • Integrity validation

11. Invoice Cancellation ​

11.1 Requirements to Cancel ​

  • ✅ Invoice registered in AEAT (status = registered)
  • ✅ No pending cancellation
  • ✅ Not already cancelled

11.2 Cancellation Process ​

  1. From registered invoice
  2. Click Cancel Invoice
  3. Complete form:
✓ Cancellation reason (free text)
✓ Cancellation type:
  - Data error
  - Duplicate invoice
  - Customer request
  - Other reason
  1. Confirm cancellation

11.3 Cancellation Record ​

Independent record created with:

  • Original invoice reference
  • Reason and cancellation type
  • Own chaining
  • Cancellation hash
  • AEAT submission

11.4 Cancellation Effects ​

  • Invoice status → CANCELLED
  • Invoice remains in chain
  • Registered in AEAT
  • Cancellation CSV generated

12. AEAT Queries ​

12.1 Query Invoice Status ​

For invoices with CSV:

  1. Click Query Status
  2. System queries AEAT in real-time
  3. Shows result:
    • Current status
    • Registration date
    • CSV

12.2 Detailed Query ​

Provides:

  • Complete registration status
  • Pagination indicator
  • Found records
  • Errors if any

12.3 Update Status ​

Refreshes status from AEAT:

  • Verifies if still registered
  • Updates local information
  • Detects changes

12.4 Bulk Query ​

For multiple invoices:

  1. Select invoices
  2. Bulk action → Update all statuses
  3. System queries each one
  4. Shows summary:
    • Updated
    • Errors

13. Document Generation ​

13.1 Available Formats ​

  • Verifactu XML (unsigned)
  • Signed XML (with digital certificate)
  • PDF (visual representation)
  • Ticket (80mm format for POS)

13.2 Download XML ​

php
// Unsigned
$xml = $invoice->generateFacturaeXml();

// Signed
$signedXml = $invoice->generateSignedFacturaeXml();

UI Actions:

  • Download Facturae XML
  • Download Signed Facturae

13.3 Generate PDF ​

Professional visual representation with:

  • Issuer data
  • Recipient data
  • Invoice lines
  • Tax breakdown
  • Totals
  • QR Code (if registered)
  • Verification CSV

13.4 Generate Ticket ​

Format optimized for 80mm thermal printers:

  • Simplified information
  • Product lines
  • Totals
  • Large QR Code
  • Monochrome design

13.5 Bulk Download ​

For multiple invoices:

  1. Select invoices
  2. Download Invoices
  3. Choose format:
    • Unsigned XML
    • Signed XML
    • PDF
    • ZIP (all formats)

ZIP file generated with structure:

/xml/
  facturae_FA2025-001.xml
  facturae_FA2025-002.xml
/xml_signed/
  facturae_FA2025-001_signed.xml
/pdf/
  factura_FA2025-001.pdf

14. Verification QR Codes ​

14.1 QR Generation ​

Automatic when registering in AEAT:

  • Contains AEAT verification URL
  • Includes CSV
  • PNG format

14.2 Data in QR ​

https://www2.aeat.es/wlpl/TIKE-CONT/ValidarQR?CSV=ABC123XYZ789

14.3 View QR ​

From registered invoice:

  • View QR: Modal with code
  • Download QR: PNG file

Download options:

  • Format: PNG or SVG
  • Size: 200px, 300px, 400px, 500px

14.4 Public Verification ​

Anyone can:

  1. Scan QR with mobile
  2. Access AEAT website
  3. Verify invoice authenticity

15. Error Handling ​

15.1 Error Types ​

Header Errors ​

  • Incorrect issuer data
  • Invalid certificate
  • Incorrect date format

Record Errors ​

  • Incorrect invoice data
  • Invalid hash
  • Broken chain

SOAP Fault Errors ​

  • AEAT server error
  • Connection timeout
  • Invalid SSL certificate

15.2 Retry System ​

Automatic configuration:

Max retries: 3
Interval: Exponential (1min, 5min, 15min)
After 3 failures: Manual retry

15.3 Logs and Audit ​

Each operation records:

  • Timestamp
  • User
  • Performed action
  • Modified data
  • Result (success/error)
  • Error message (if applicable)

Access logs: Verifactu → Audit

15.4 Notifications ​

System notifies:

  • ✅ Successful registration
  • ❌ Submission errors
  • ⚠️ Warnings
  • 🔄 Status updates

16. API and Services ​

16.1 Main Services ​

VerifactuService ​

php
use Modules\Verifactu\Services\VerifactuService;

// Configure
VerifactuService::config([
    'certPath' => '/path/to/cert.p12',
    'certPassword' => 'password',
    'soapEndpoint' => 'https://...',
]);

// Register invoice
$response = VerifactuService::registerInvoice($invoiceSubmission);

// Query
$response = VerifactuService::queryInvoices($query);

// Cancel
$response = VerifactuService::cancelInvoice($cancellation);

HashGeneratorService ​

php
use Modules\Verifactu\Services\HashGeneratorService;

$hash = HashGeneratorService::generate($invoiceSubmission);
// Returns: SHA-256 hash in hexadecimal

QrGeneratorService ​

php
use Modules\Verifactu\Services\QrGeneratorService;

$qr = QrGeneratorService::generateQr(
    $invoiceRecord,
    $baseUrl,
    $destination, // STRING | FILE
    $size,        // 200-500px
    $renderer     // GD | SVG
);

XmlSignerService ​

php
use Modules\Verifactu\Services\XmlSignerService;

$signedXml = XmlSignerService::signXml(
    $xmlString,
    $certPath,
    $certPassword
);

16.2 Facades ​

php
use Modules\Verifactu\Facades\Verifactu;

// Configure for company
Verifactu::forCompany($companyId);

// Register
$response = Verifactu::registerInvoice($submission);

// Generate QR
$qr = Verifactu::generateInvoiceQr($record);

16.3 Eloquent Models ​

VerifactuInvoice ​

php
$invoice = VerifactuInvoice::find($id);

// States
$invoice->isDraft();
$invoice->isConfirmed();
$invoice->isRegistered();
$invoice->isCancelled();

// Actions
$invoice->confirm();
$invoice->recalculateTotals();
$invoice->updateBreakdownFromLines();

// Relationships
$invoice->lines;
$invoice->breakdowns;
$invoice->recipients;
$invoice->certificate;
$invoice->cancellation;

VerifactuCertificate ​

php
$cert = VerifactuCertificate::find($id);

$cert->getCertificatePath();
$cert->getDecryptedPassword();
$cert->isValid();
$cert->expiresIn(); // remaining days

16.4 Events ​

php
// Event when totals are updated
event(new InvoiceTotalsUpdated($invoice));

// Listener
public function handle(InvoiceTotalsUpdated $event)
{
    $invoice = $event->invoice;
    // ... logic
}

17. Troubleshooting ​

17.1 Common Issues ​

Totals not updating ​

Problem: I add lines but totals remain at 0€

Solution:

php
// In Tinker
$invoice = VerifactuInvoice::find($id);
$invoice->recalculateTotals();

Verify VerifactuInvoiceLine has saved event:

php
static::saved(function ($line) {
    $line->invoice?->recalculateTotals();
});

Chaining not working ​

Problem: Invoice doesn't take previous hash

Solution:

  1. Verify previous invoice is confirmed (has hash)
  2. Verify they use the same certificate
  3. Confirm chronological order
php
// Verify in Tinker
$prev = VerifactuInvoice::where('status', 'confirmed')
    ->where('verifactu_certificate_id', $certId)
    ->latest('issue_date')
    ->first();

$prev->hash; // Must have value

AEAT Error 1207 ​

Problem: "Internal server error"

Solution:

  • It's a sandbox AEAT server error
  • Retry later
  • Very rare in production

Invalid certificate ​

Problem: "Certificate verification failed"

Solution:

  1. Verify P12/PFX format
  2. Verify correct password
  3. Verify not expired
  4. Verify it's AEAT representation

QR not generated ​

Problem: QR appears empty

Solution:

  1. Verify invoice is registered
  2. Verify it has CSV
  3. Verify GD extension installed:
bash
php -m | grep gd

17.2 Useful Commands ​

bash
# Clear cache
php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear

# Regenerate autoload
composer dump-autoload -o

# Check migrations
php artisan migrate:status

# Tinker for debug
php artisan tinker

17.3 Logs ​

Log location:

storage/logs/laravel.log

Search Verifactu errors:

bash
tail -f storage/logs/laravel.log | grep Verifactu

17.4 Debugging in Tinker ​

php
// View latest invoice
$invoice = VerifactuInvoice::latest()->first();

// View complete structure
$invoice->load(['lines', 'breakdowns', 'recipients', 'certificate']);
dd($invoice);

// Recalculate totals
$invoice->recalculateTotals();

// View errors
$invoice->aeat_errors;

// Confirm manually
$invoice->confirm();

// View chain
$invoice->chainRecord;

📞 Support ​

For technical support:


© 2025 Qbit Dynamics SL - All rights reserved