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