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) oFactura 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
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"
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
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
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"
}
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
Lista de comprobación para la migración (ecosistema español)
Antes de migrar
- [ ] Inventariar todos los usos de
Spire.PDFyFreeSpire.PDFen 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.PDFde NuGet, instalarIronPdf - [ ] Actualizar imports:
using Spire.Pdf;→using IronPdf; - [ ] Reemplazar
LoadFromHTML()conChromePdfRenderer.RenderHtmlAsPdf()(corrección crítica) - [ ] Reemplazar
new PdfDocument()+LoadFromFile()conPdfDocument.FromFile() - [ ] Reemplazar
InsertPageRange()conPdfDocument.Merge() - [ ] Reemplazar
Canvas.DrawString()conTextStamper+ApplyStamp() - [ ] Reemplazar
SaveToFile()conSaveAs() - [ ] Eliminar todas las llamadas
Close()(IronPDF gestiona el ciclo de vida automáticamente) - [ ] Integrar leyenda
VERI*FACTUen plantillas HTML de facturas - [ ] Integrar código QR AEAT (generado con IronQR o biblioteca equivalente)
- [ ] Configurar firma PAdES con
PdfSignaturey 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*FACTUaparece 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:
- 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
- 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
- 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.

