Saltar al pie de página
GUíAS DE MIGRACIóN

Migrar de Spire.PDF a IronPDF: guía para ISVs españoles bajo VeriFactu y TicketBAI

IronPDF para software de facturación española: guía de evaluación frente a Spire.PDF bajo VeriFactu, TicketBAI y LOPDGDD

Los ISVs españoles que desarrollan software de facturación certificado se encuentran ante una decisión con consecuencias regulatorias directas: qué biblioteca PDF usar como componente dentro de ese software. El entorno regulatorio español — VeriFactu (AEAT), TicketBAI (Bizkaia, Gipuzkoa, Araba), Facturae/FACe, LOPDGDD y eIDAS — exige capacidades técnicas que no todas las bibliotecas PDF del mercado ofrecen con la misma solidez.

Esta guía analiza Spire.PDF e IronPDF desde la perspectiva específica de un ISV español sujeto a la penalización de software de facturación no conforme: hasta €150.000 anuales según la regulación VeriFactu vigente.


El marco regulatorio que cambia el análisis de la biblioteca PDF

VeriFactu: la penalización al proveedor de software

VeriFactu, el sistema de verificación de facturas de la AEAT (Agencia Estatal de Administración Tributaria), introduce un elemento único en el análisis de selección de biblioteca PDF para ISVs: la penalización por incumplimiento recae sobre el proveedor de software de facturación, no sobre el contribuyente final. Esto eleva el riesgo de selección de biblioteca a un nivel normativo.

Los plazos vigentes según el Real Decreto-ley 15/2025 son:

  • 1 de enero de 2027: obligación para contribuyentes del impuesto sobre sociedades
  • 1 de julio de 2027: obligación para el resto de contribuyentes

Los proveedores de software de facturación ya deben tener sus productos conformes. Las facturas VeriFactu requieren:

  • Código QR AEAT que enlace al endpoint de verificación de la sede electrónica
  • Leyenda VERI*FACTU (con asterisco, preservada exactamente) o Factura verificable en la sede electrónica de la AEAT
  • Huella encadenada (huella) para integridad de la cadena de registros de facturación
  • PDFs con texto real, no imágenes — los sistemas de la AEAT deben poder procesar el contenido

Posicionamiento importante: IronPDF es un componente para integrar DENTRO del software de facturación. No es un sistema de facturación certificado por la AEAT. Los ISVs que lo integran asumen la responsabilidad de la certificación completa del sistema.

TicketBAI: fragmentación foral con tres implementaciones distintas

TicketBAI está en vigor en el País Vasco y no es monolítico. Las tres diputaciones forales tienen autoridades tributarias independientes con especificaciones de implementación propias:

Territorio Autoridad Portal
Bizkaia Diputación Foral de Bizkaia (también BATUZ) bizkaia.eus
Gipuzkoa Diputación Foral de Gipuzkoa gipuzkoa.eus
Araba Diputación Foral de Araba araba.eus

TicketBAI exige que los XML de factura estén firmados con XAdES (XML Advanced Electronic Signatures). Los ISVs que atienden clientes del País Vasco deben gestionar las tres variantes forales. La firma del PDF de presentación se realiza posteriormente con PAdES.

LOPDGDD, eIDAS y el archivado de facturas electrónicas

La LOPDGDD (Ley Orgánica de Protección de Datos y Garantía de Derechos Digitales) establece los requisitos de integridad para el archivado de documentos electrónicos con datos personales. Para facturas electrónicas, esto se combina con el reglamento eIDAS para determinar el estándar de firma aplicable: PAdES-LTV (Long-Term Validation) para el archivado a largo plazo.

La FNMT (Fábrica Nacional de Moneda y Timbre) es la autoridad certificadora de referencia en el ecosistema empresarial español para certificados reconocidos por la AEAT y las haciendas forales.


Comparativa técnica: IronPDF vs Spire.PDF para el ecosistema español

Modelo de licencias y el riesgo VeriFactu × licencia

Spire.PDF opera bajo un modelo freemium: versión FreeSpire.PDF con límites de funcionalidad y versión comercial completa. Para un ISV que distribuye software de facturación certificado, esta estructura introduce ambigüedad:

  • ¿Qué funcionalidades están disponibles en cada nivel?
  • ¿Está cubierto el uso en producción para software de facturación distribuido?
  • ¿Cómo afecta esto a la certificación ante la AEAT?

IronPDF utiliza licencia comercial propietaria sin capas gratuitas con funcionalidad limitada. La licencia es clara para uso en software distribuido, sin claúsulas AGPL ni obligaciones de divulgación de código fuente que compliquen la certificación.

Nota sobre iText AGPL: iText7, otra alternativa popular, utiliza licencia AGPL que sí obliga a divulgar el código fuente si el software se distribuye. En el contexto de VeriFactu, donde la certificación del software es pública, esto añade complejidad legal. IronPDF ofrece licencia propietaria sin este riesgo.

Criterio FreeSpire.PDF Spire.PDF Comercial IronPDF
Modelo de licencia Freemium con límites Comercial Comercial propietario
AGPL / código abierto No No No
Ambigüedad para certificación VeriFactu Alta (restricciones freemium) Baja Muy baja
Precio Gratuito (funciones limitadas) Comercial Comercial

Capacidades técnicas relevantes para la facturación española

Capacidad Spire.PDF IronPDF
Motor HTML a PDF IE/Edge legacy (obsoleto 2022) Chromium moderno
Texto en PDF (no imagen) Frecuentemente imagen con LoadFromHTML() Texto real siempre
CSS3 Flexbox/Grid Parcial Completo
JavaScript ES6+ Limitado Completo
PAdES firma PDF Limitado Completo (IronPDF.Signing)
PDF/A para archivado Limitado PDF/A-1b, A-2, A-3
Compatibilidad .NET .NET Framework + Core .NET 4.6.2+ / .NET 8+
Accesibilidad WCAG Pobre (basado en imagen) Excelente

Instalación y configuración inicial

Cambio de paquete NuGet

# Eliminar Spire.PDF
dotnet remove package Spire.PDF
dotnet remove package FreeSpire.PDF

# Instalar IronPDF
dotnet add package IronPdf
# Eliminar Spire.PDF
dotnet remove package Spire.PDF
dotnet remove package FreeSpire.PDF

# Instalar IronPDF
dotnet add package IronPdf
SHELL

Inicialización de la licencia

// Añadir al inicio de la aplicación (Program.cs o Global.asax)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Añadir al inicio de la aplicación (Program.cs o Global.asax)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
' Añadir al inicio de la aplicación (Program.vb o Global.asax.vb)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

Generación de facturas VeriFactu con IronPDF: código QR AEAT y leyenda VERI*FACTU

El caso de uso central para ISVs bajo VeriFactu: generar un PDF de factura con texto real seleccionable, código QR AEAT verificable y la leyenda obligatoria. El motor Chromium de IronPDF garantiza que el texto sea siempre texto real — nunca imágenes de mapa de bits como ocurre con LoadFromHTML() de Spire.PDF.

// NuGet: Install-Package IronPdf
using IronPdf;

class GeneradorFacturasVeriFactu
{
    public static byte[] GenerarFactura(
        string nifEmisor,
        string numeroFactura,
        string qrAeatBase64,       // Código QR generado con IronQR
        string huellaEncadenada)   // Huella VeriFactu del registro anterior
    {
        IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";

        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;

        string html = $@"
        <html lang='es'>
        <head>
            <meta charset='UTF-8'>
            <style>
                body {{ font-family: Arial, sans-serif; font-size: 10pt; }}
                .cabecera {{ display: flex; justify-content: space-between; }}
                .bloque-verifactu {{ text-align: right; }}
                .leyenda-vf {{ font-weight: bold; font-size: 9pt; }}
                .qr-aeat {{ width: 80px; height: 80px; }}
                .tabla {{ width: 100%; border-collapse: collapse; margin-top: 15px; }}
                .tabla th, .tabla td {{ border: 1px solid #ccc; padding: 4px 8px; }}
                .pie {{ margin-top: 20px; font-size: 7pt; color: #555; }}
            </style>
        </head>
        <body>
            <div class='cabecera'>
                <div>
                    <h2>FACTURA ELECTRÓNICA</h2>
                    <p>Emisor NIF: {nifEmisor} | Nº: {numeroFactura}</p>
                </div>
                <div class='bloque-verifactu'>
                    <img class='qr-aeat' 
                         src='data:image/png;base64,{qrAeatBase64}' 
                         alt='Código QR AEAT' />
                    <p class='leyenda-vf'>VERI*FACTU</p>
                    <p style='font-size:7pt;'>Factura verificable en la sede electrónica de la AEAT</p>
                </div>
            </div>
            <div class='pie'>
                Huella: {huellaEncadenada}
            </div>
        </body>
        </html>";

        var pdf = renderer.RenderHtmlAsPdf(html);

        // El PDF resultante:
        // ✅ Texto real seleccionable — apto para indexación AEAT
        // ✅ Leyenda VERI*FACTU con asterisco preservada
        // ✅ QR AEAT embedido correctamente con motor Chromium
        // ✅ CSS Flexbox funciona — maquetación correcta de cabecera

        return pdf.BinaryData;
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;

class GeneradorFacturasVeriFactu
{
    public static byte[] GenerarFactura(
        string nifEmisor,
        string numeroFactura,
        string qrAeatBase64,       // Código QR generado con IronQR
        string huellaEncadenada)   // Huella VeriFactu del registro anterior
    {
        IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";

        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;

        string html = $@"
        <html lang='es'>
        <head>
            <meta charset='UTF-8'>
            <style>
                body {{ font-family: Arial, sans-serif; font-size: 10pt; }}
                .cabecera {{ display: flex; justify-content: space-between; }}
                .bloque-verifactu {{ text-align: right; }}
                .leyenda-vf {{ font-weight: bold; font-size: 9pt; }}
                .qr-aeat {{ width: 80px; height: 80px; }}
                .tabla {{ width: 100%; border-collapse: collapse; margin-top: 15px; }}
                .tabla th, .tabla td {{ border: 1px solid #ccc; padding: 4px 8px; }}
                .pie {{ margin-top: 20px; font-size: 7pt; color: #555; }}
            </style>
        </head>
        <body>
            <div class='cabecera'>
                <div>
                    <h2>FACTURA ELECTRÓNICA</h2>
                    <p>Emisor NIF: {nifEmisor} | Nº: {numeroFactura}</p>
                </div>
                <div class='bloque-verifactu'>
                    <img class='qr-aeat' 
                         src='data:image/png;base64,{qrAeatBase64}' 
                         alt='Código QR AEAT' />
                    <p class='leyenda-vf'>VERI*FACTU</p>
                    <p style='font-size:7pt;'>Factura verificable en la sede electrónica de la AEAT</p>
                </div>
            </div>
            <div class='pie'>
                Huella: {huellaEncadenada}
            </div>
        </body>
        </html>";

        var pdf = renderer.RenderHtmlAsPdf(html);

        // El PDF resultante:
        // ✅ Texto real seleccionable — apto para indexación AEAT
        // ✅ Leyenda VERI*FACTU con asterisco preservada
        // ✅ QR AEAT embedido correctamente con motor Chromium
        // ✅ CSS Flexbox funciona — maquetación correcta de cabecera

        return pdf.BinaryData;
    }
}
Imports IronPdf

Class GeneradorFacturasVeriFactu
    Public Shared Function GenerarFactura(
        nifEmisor As String,
        numeroFactura As String,
        qrAeatBase64 As String,       ' Código QR generado con IronQR
        huellaEncadenada As String) As Byte()   ' Huella VeriFactu del registro anterior

        IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"

        Dim renderer = New ChromePdfRenderer()
        renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4

        Dim html As String = $"
        <html lang='es'>
        <head>
            <meta charset='UTF-8'>
            <style>
                body {{ font-family: Arial, sans-serif; font-size: 10pt; }}
                .cabecera {{ display: flex; justify-content: space-between; }}
                .bloque-verifactu {{ text-align: right; }}
                .leyenda-vf {{ font-weight: bold; font-size: 9pt; }}
                .qr-aeat {{ width: 80px; height: 80px; }}
                .tabla {{ width: 100%; border-collapse: collapse; margin-top: 15px; }}
                .tabla th, .tabla td {{ border: 1px solid #ccc; padding: 4px 8px; }}
                .pie {{ margin-top: 20px; font-size: 7pt; color: #555; }}
            </style>
        </head>
        <body>
            <div class='cabecera'>
                <div>
                    <h2>FACTURA ELECTRÓNICA</h2>
                    <p>Emisor NIF: {nifEmisor} | Nº: {numeroFactura}</p>
                </div>
                <div class='bloque-verifactu'>
                    <img class='qr-aeat' 
                         src='data:image/png;base64,{qrAeatBase64}' 
                         alt='Código QR AEAT' />
                    <p class='leyenda-vf'>VERI*FACTU</p>
                    <p style='font-size:7pt;'>Factura verificable en la sede electrónica de la AEAT</p>
                </div>
            </div>
            <div class='pie'>
                Huella: {huellaEncadenada}
            </div>
        </body>
        </html>"

        Dim pdf = renderer.RenderHtmlAsPdf(html)

        ' El PDF resultante:
        ' ✅ Texto real seleccionable — apto para indexación AEAT
        ' ✅ Leyenda VERI*FACTU con asterisco preservada
        ' ✅ QR AEAT embedido correctamente con motor Chromium
        ' ✅ CSS Flexbox funciona — maquetación correcta de cabecera

        Return pdf.BinaryData
    End Function
End Class
$vbLabelText   $csharpLabel

Firma PAdES para TicketBAI y archivado LOPDGDD/eIDAS

Una vez generado el PDF de la factura, se aplica la firma PAdES conforme a eIDAS. Para TicketBAI, el flujo completo es: generar XML TicketBAI → firmar XML con XAdES → generar PDF con IronPDF → firmar PDF con PAdES.

using IronPdf;
using IronPdf.Signing;

class ServicioFirmaPades
{
    // Firma PAdES para archivado conforme LOPDGDD/eIDAS
    // Válido para: facturas VeriFactu, documentos TicketBAI, archivado Facturae
    public static void FirmarConPades(
        string rutaPdf,
        string rutaCertificadoPfx,    // Certificado FNMT o equivalente
        string passwordCert,
        string provinciaForal = null)  // "Bizkaia", "Gipuzkoa", "Araba" si aplica TicketBAI
    {
        IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";

        var documento = PdfDocument.FromFile(rutaPdf);

        string location = string.IsNullOrEmpty(provinciaForal) 
            ? "España" 
            : $"España - País Vasco ({provinciaForal})";

        var firma = new PdfSignature(rutaCertificadoPfx, passwordCert)
        {
            SigningContact = "facturacion@miempresa.com",
            SigningLocation = location,
            SigningReason = string.IsNullOrEmpty(provinciaForal)
                ? "Factura electrónica — archivado conforme LOPDGDD/eIDAS"
                : $"Factura TicketBAI {provinciaForal} — conforme eIDAS"
        };

        documento.Sign(firma);
        documento.SaveAs(rutaPdf.Replace(".pdf", "_firmado.pdf"));
    }

    // Firma en lote para cierres mensuales
    public static void FirmarLoteMensual(string directorio, string rutaCert, string password)
    {
        var firma = new PdfSignature(rutaCert, password)
        {
            SigningReason = "Lote facturas mensual — VeriFactu/SII"
        };

        foreach (string rutaFactura in System.IO.Directory.GetFiles(directorio, "*.pdf"))
        {
            var doc = PdfDocument.FromFile(rutaFactura);
            doc.Sign(firma);
            doc.SaveAs(rutaFactura.Replace(".pdf", "_firmado.pdf"));
        }
    }
}
using IronPdf;
using IronPdf.Signing;

class ServicioFirmaPades
{
    // Firma PAdES para archivado conforme LOPDGDD/eIDAS
    // Válido para: facturas VeriFactu, documentos TicketBAI, archivado Facturae
    public static void FirmarConPades(
        string rutaPdf,
        string rutaCertificadoPfx,    // Certificado FNMT o equivalente
        string passwordCert,
        string provinciaForal = null)  // "Bizkaia", "Gipuzkoa", "Araba" si aplica TicketBAI
    {
        IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";

        var documento = PdfDocument.FromFile(rutaPdf);

        string location = string.IsNullOrEmpty(provinciaForal) 
            ? "España" 
            : $"España - País Vasco ({provinciaForal})";

        var firma = new PdfSignature(rutaCertificadoPfx, passwordCert)
        {
            SigningContact = "facturacion@miempresa.com",
            SigningLocation = location,
            SigningReason = string.IsNullOrEmpty(provinciaForal)
                ? "Factura electrónica — archivado conforme LOPDGDD/eIDAS"
                : $"Factura TicketBAI {provinciaForal} — conforme eIDAS"
        };

        documento.Sign(firma);
        documento.SaveAs(rutaPdf.Replace(".pdf", "_firmado.pdf"));
    }

    // Firma en lote para cierres mensuales
    public static void FirmarLoteMensual(string directorio, string rutaCert, string password)
    {
        var firma = new PdfSignature(rutaCert, password)
        {
            SigningReason = "Lote facturas mensual — VeriFactu/SII"
        };

        foreach (string rutaFactura in System.IO.Directory.GetFiles(directorio, "*.pdf"))
        {
            var doc = PdfDocument.FromFile(rutaFactura);
            doc.Sign(firma);
            doc.SaveAs(rutaFactura.Replace(".pdf", "_firmado.pdf"));
        }
    }
}
Imports IronPdf
Imports IronPdf.Signing

Class ServicioFirmaPades
    ' Firma PAdES para archivado conforme LOPDGDD/eIDAS
    ' Válido para: facturas VeriFactu, documentos TicketBAI, archivado Facturae
    Public Shared Sub FirmarConPades(rutaPdf As String, rutaCertificadoPfx As String, passwordCert As String, Optional provinciaForal As String = Nothing) ' "Bizkaia", "Gipuzkoa", "Araba" si aplica TicketBAI
        IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"

        Dim documento = PdfDocument.FromFile(rutaPdf)

        Dim location As String = If(String.IsNullOrEmpty(provinciaForal), "España", $"España - País Vasco ({provinciaForal})")

        Dim firma As New PdfSignature(rutaCertificadoPfx, passwordCert) With {
            .SigningContact = "facturacion@miempresa.com",
            .SigningLocation = location,
            .SigningReason = If(String.IsNullOrEmpty(provinciaForal), "Factura electrónica — archivado conforme LOPDGDD/eIDAS", $"Factura TicketBAI {provinciaForal} — conforme eIDAS")
        }

        documento.Sign(firma)
        documento.SaveAs(rutaPdf.Replace(".pdf", "_firmado.pdf"))
    End Sub

    ' Firma en lote para cierres mensuales
    Public Shared Sub FirmarLoteMensual(directorio As String, rutaCert As String, password As String)
        Dim firma As New PdfSignature(rutaCert, password) With {
            .SigningReason = "Lote facturas mensual — VeriFactu/SII"
        }

        For Each rutaFactura As String In System.IO.Directory.GetFiles(directorio, "*.pdf")
            Dim doc = PdfDocument.FromFile(rutaFactura)
            doc.Sign(firma)
            doc.SaveAs(rutaFactura.Replace(".pdf", "_firmado.pdf"))
        Next
    End Sub
End Class
$vbLabelText   $csharpLabel

Gestión segura del certificado FNMT en producción

Los entornos de producción de software de facturación certificado no deben almacenar los ficheros .pfx en el sistema de ficheros del servidor. El certificado FNMT contiene claves privadas que, si se ven comprometidas, comprometen todos los documentos firmados con esa clave:

// Patrón recomendado: cargar certificado desde variable de entorno
string certBase64 = Environment.GetEnvironmentVariable("FACTURACION_CERT_PFX")
    ?? throw new InvalidOperationException("Certificado FNMT no configurado.");

byte[] certBytes = Convert.FromBase64String(certBase64);
string certPassword = Environment.GetEnvironmentVariable("FACTURACION_CERT_PASSWORD")
    ?? throw new InvalidOperationException("Contraseña del certificado no configurada.");

var firma = new IronPdf.Signing.PdfSignature(certBytes, certPassword)
{
    SigningReason = "Factura electrónica — certificado FNMT/AEAT"
};
// Patrón recomendado: cargar certificado desde variable de entorno
string certBase64 = Environment.GetEnvironmentVariable("FACTURACION_CERT_PFX")
    ?? throw new InvalidOperationException("Certificado FNMT no configurado.");

byte[] certBytes = Convert.FromBase64String(certBase64);
string certPassword = Environment.GetEnvironmentVariable("FACTURACION_CERT_PASSWORD")
    ?? throw new InvalidOperationException("Contraseña del certificado no configurada.");

var firma = new IronPdf.Signing.PdfSignature(certBytes, certPassword)
{
    SigningReason = "Factura electrónica — certificado FNMT/AEAT"
};
Imports System
Imports IronPdf.Signing

' Patrón recomendado: cargar certificado desde variable de entorno
Dim certBase64 As String = Environment.GetEnvironmentVariable("FACTURACION_CERT_PFX")
If certBase64 Is Nothing Then
    Throw New InvalidOperationException("Certificado FNMT no configurado.")
End If

Dim certBytes As Byte() = Convert.FromBase64String(certBase64)
Dim certPassword As String = Environment.GetEnvironmentVariable("FACTURACION_CERT_PASSWORD")
If certPassword Is Nothing Then
    Throw New InvalidOperationException("Contraseña del certificado no configurada.")
End If

Dim firma As New PdfSignature(certBytes, certPassword) With {
    .SigningReason = "Factura electrónica — certificado FNMT/AEAT"
}
$vbLabelText   $csharpLabel

Este patrón facilita la rotación del certificado cuando caduca: se actualiza la variable de entorno y se reinicia el servicio, sin modificar código.


PDF/A para Facturae y archivado según LOPDGDD

Las facturas enviadas a través de FACe (la plataforma B2G de la Administración) utilizan Facturae XML 3.2.2 normalmente embebido en PDF/A-3. El estándar PDF/A garantiza reproducibilidad a largo plazo, requisito del archivado conforme a LOPDGDD:

using IronPdf;

class GeneradorFace
{
    public static void GenerarContenedorPdfaFace(
        string htmlFactura,
        string rutaXmlFacturae,  // Fichero Facturae 3.2.2 XML
        string rutaSalida)
    {
        IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";

        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;

        var pdf = renderer.RenderHtmlAsPdf(htmlFactura);

        // PDF/A-3 permite adjuntar el XML Facturae como fichero embebido
        // Esto es el estándar para envíos B2G a FACe
        pdf.SaveAs(rutaSalida);

        // Nota: para el embed del XML Facturae como adjunto del PDF/A-3,
        // utilice la API de attachments de IronPDF
    }
}
using IronPdf;

class GeneradorFace
{
    public static void GenerarContenedorPdfaFace(
        string htmlFactura,
        string rutaXmlFacturae,  // Fichero Facturae 3.2.2 XML
        string rutaSalida)
    {
        IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";

        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;

        var pdf = renderer.RenderHtmlAsPdf(htmlFactura);

        // PDF/A-3 permite adjuntar el XML Facturae como fichero embebido
        // Esto es el estándar para envíos B2G a FACe
        pdf.SaveAs(rutaSalida);

        // Nota: para el embed del XML Facturae como adjunto del PDF/A-3,
        // utilice la API de attachments de IronPDF
    }
}
Imports IronPdf

Class GeneradorFace
    Public Shared Sub GenerarContenedorPdfaFace(
        htmlFactura As String,
        rutaXmlFacturae As String,  ' Fichero Facturae 3.2.2 XML
        rutaSalida As String)

        IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"

        Dim renderer = New ChromePdfRenderer()
        renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4

        Dim pdf = renderer.RenderHtmlAsPdf(htmlFactura)

        ' PDF/A-3 permite adjuntar el XML Facturae como fichero embebido
        ' Esto es el estándar para envíos B2G a FACe
        pdf.SaveAs(rutaSalida)

        ' Nota: para el embed del XML Facturae como adjunto del PDF/A-3,
        ' utilice la API de attachments de IronPDF
    End Sub
End Class
$vbLabelText   $csharpLabel

Lista de comprobación para la migración (ecosistema español)

Antes de migrar

  • [ ] Inventariar todos los usos de Spire.PDF y FreeSpire.PDF en el código base
  • [ ] Identificar llamadas LoadFromHTML() — estas producen texto como imagen (prioridad crítica)
  • [ ] Verificar si se usa la versión FreeSpire.PDF (restricciones de licencia que afectan a la certificación)
  • [ ] Obtener clave de licencia IronPDF en ironpdf.com
  • [ ] Revisar requisitos de firma foral para clientes TicketBAI (Bizkaia/Gipuzkoa/Araba)
  • [ ] Confirmar certificado FNMT disponible para entorno de pruebas y producción

Durante la migración

  • [ ] Eliminar Spire.PDF/FreeSpire.PDF de NuGet, instalar IronPdf
  • [ ] Actualizar imports: using Spire.Pdf;using IronPdf;
  • [ ] Reemplazar LoadFromHTML() con ChromePdfRenderer.RenderHtmlAsPdf() (corrección crítica)
  • [ ] Reemplazar new PdfDocument() + LoadFromFile() con PdfDocument.FromFile()
  • [ ] Reemplazar InsertPageRange() con PdfDocument.Merge()
  • [ ] Reemplazar Canvas.DrawString() con TextStamper + ApplyStamp()
  • [ ] Reemplazar SaveToFile() con SaveAs()
  • [ ] Eliminar todas las llamadas Close() (IronPDF gestiona el ciclo de vida automáticamente)
  • [ ] Integrar leyenda VERI*FACTU en plantillas HTML de facturas
  • [ ] Integrar código QR AEAT (generado con IronQR o biblioteca equivalente)
  • [ ] Configurar firma PAdES con PdfSignature y certificado FNMT

Pruebas específicas para el ecosistema español

  • [ ] Prueba crítica: verificar que el texto del PDF es seleccionable (no imagen)
  • [ ] Comprobar que la leyenda VERI*FACTU aparece con asterisco y sin alteraciones
  • [ ] Verificar que el QR AEAT enlaza correctamente a la sede electrónica de la AEAT
  • [ ] Validar maquetación de factura con CSS3 Flexbox/Grid
  • [ ] Probar firma PAdES con certificado de prueba FNMT
  • [ ] Si aplica TicketBAI: probar con los tres esquemas forales (Bizkaia, Gipuzkoa, Araba)
  • [ ] Comparar tamaños de fichero — deben ser significativamente menores que con Spire.PDF

Conclusión

Para los ISVs españoles, la selección de biblioteca PDF para software de facturación ya no es solo una decisión técnica: es una decisión con implicaciones normativas directas bajo VeriFactu (penalización hasta €150.000 anuales para proveedores de software no conformes). IronPDF resuelve los tres ejes que importan:

  1. Licencia clara y sin riesgo AGPL: licencia comercial propietaria, sin capas freemium ambiguas, sin obligaciones de divulgación de código fuente que compliquen la certificación ante la AEAT
  2. Motor Chromium con texto PDF real: elimina el problema de imagen vs. texto de Spire.PDF; los PDFs generados son indexables por los sistemas de la AEAT y verificables en FACe
  3. Firma PAdES integrada: API de firma completa para archivado conforme a LOPDGDD/eIDAS, compatible con flujos TicketBAI multi-foral (Bizkaia, Gipuzkoa, Araba) y con los certificados FNMT del ecosistema español

Comience la evaluación técnica con la prueba gratuita de IronPDF — sin tarjeta de crédito ni compromiso.

Preguntas Frecuentes

¿IronPDF es adecuado para software de facturación sujeto a VeriFactu?

IronPDF es un componente para usar DENTRO del software de facturación certificado, no un sistema de facturación certificado en sí. Proporciona las capacidades de generación PDF, firma PAdES y renderizado de plantillas con código QR AEAT y leyenda VERI*FACTU que necesita el ISV para desarrollar su solución certificada.

¿Cómo se gestiona la firma XAdES para TicketBAI con IronPDF?

El flujo es: generar XML TicketBAI → firmar con XAdES (biblioteca de firma XML) → generar el PDF de factura con IronPDF → opcionalmente firmar el PDF con PAdES usando IronPDF.Signing.PdfSignature. Las tres variantes forales (Bizkaia, Gipuzkoa, Araba) se gestionan configurando el SigningLocation adecuado.

¿Por qué el modelo de licencias de Spire.PDF es problemático para ISVs bajo VeriFactu?

El modelo freemium de Spire.PDF genera ambigüedad sobre qué funcionalidades están disponibles en cada nivel, lo que obliga a revisión legal y puede complicar la auditoría de certificación. Con penalización de hasta €150.000 anuales para proveedores de software de facturación no conformes, esa ambigüedad tiene coste directo. IronPDF ofrece licencia comercial propietaria transparente.

¿IronPDF soporta el archivado PDF/A requerido por LOPDGDD?

Sí. IronPDF soporta PDF/A-1b, A-2 y A-3. PDF/A-3 permite además embedir el XML Facturae dentro del documento PDF, que es el estándar para envíos B2G a través de FACe.

Curtis Chau
Escritor Técnico

Curtis Chau tiene una licenciatura en Ciencias de la Computación (Carleton University) y se especializa en el desarrollo front-end con experiencia en Node.js, TypeScript, JavaScript y React. Apasionado por crear interfaces de usuario intuitivas y estéticamente agradables, disfruta trabajando con frameworks modernos y creando manuales bien ...

Leer más

Equipo de soporte de Iron

Estamos disponibles online las 24 horas, 5 días a la semana.
Chat
Email
Llámame