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

Migrar de DinkToPdf a IronPDF: cumplimiento VeriFactu, TicketBAI y LOPDGDD para ISVs españoles

Para los ISVs y desarrolladores de software de facturación en España, la elección del motor PDF no es únicamente una decisión técnica: es una decisión de cumplimiento regulatorio. DinkToPdf envuelve wkhtmltopdf, heredando sus vulnerabilidades de seguridad críticas y sus limitaciones técnicas. Bajo el Real Decreto-Ley 15/2025, los proveedores de software de facturación electrónica que no cumplan con VeriFactu se exponen a penalizaciones de hasta 150.000 €/año. Un motor PDF con CVE sin parchear en la cadena de generación de facturas no solo es un riesgo técnico, sino un riesgo regulatorio directo ante la AEAT.

Por qué DinkToPdf es incompatible con VeriFactu y TicketBAI

DinkToPdf hereda vulnerabilidades críticas sin parchear de wkhtmltopdf, cuyo repositorio fue archivado en julio de 2024. Para los sistemas de facturación electrónica que deben cumplir con VeriFactu (RDL 15/2025) o TicketBAI (Bizkaia, Gipuzkoa, Araba), estas vulnerabilidades tienen consecuencias directas.

Cuestiones críticas de seguridad

  1. CVE-2022-35583 (SSRF): Falsificación de solicitud del lado del servidor que permite a los atacantes acceder a recursos de red internos. En un sistema que genera facturas VeriFactu con acceso a la AEAT o a sistemas ERP internos (SAP, Dynamics 365), esta vulnerabilidad puede exponer datos sensibles de facturación y romper la cadena de auditoría íntegra exigida por el RDL 15/2025.
  2. Proyecto archivado: El repositorio wkhtmltopdf/wkhtmltopdf fue archivado el 2 de enero de 2023; toda la organización GitHub de wkhtmltopdf fue archivada el 10 de julio de 2024.
  3. Sin parches de seguridad futuros: Las vulnerabilidades conocidas y futuras no serán corregidas.

Problemas técnicos para la facturación electrónica española

Problema Impacto en cumplimiento
CVE-2022-35583 (SSRF) Riesgo regulatorio en flujos VeriFactu/TicketBAI con acceso a AEAT o ERP
Motor WebKit obsoleto (2015) Sin soporte Flexbox/Grid — dificulta la leyenda VERI*FACTU y QR AEAT
Sin firmas digitales TicketBAI exige firma XAdES; toda la firma debe implementarse fuera del motor
Seguridad de hilos SynchronizedConverter falla en producción bajo carga concurrente
Binarios nativos Despliegue complejo con libwkhtmltox específicos de plataforma
Sin mantenimiento DinkToPdf 1.0.8 (2017); wkhtmltopdf archivado (2024)

Comparación de arquitecturas

Aspecto DinkToPdf IronPDF
Seguridad CVE-2022-35583 (SSRF), sin parchear Sin CVEs críticos conocidos
Motor de renderizado WebKit obsoleto (2015) Chromium moderno
Seguridad de hilos Fallos en uso concurrente Thread-safe por diseño
Dependencias nativas Binarios específicos de plataforma Paquete NuGet gestionado
Soporte CSS Sin Flexbox/Grid CSS3 completo
Firmas digitales ❌ No disponible ✅ XAdES, PAdES, CAdES
JavaScript Limitada e incoherente Compatible
Mantenimiento Archivado (2024) Mantenimiento activo

Comparación de características

Característica DinkToPdf IronPDF
HTML a PDF ✅ (motor obsoleto) ✅ (Chromium)
URL a PDF
Márgenes personalizados
Encabezados/pies de página ✅ (limitado) ✅ (HTML completo)
CSS3 / Flexbox / Grid
JavaScript ⚠️ Limitada ✅ Completo
Manipulación de PDF
Relleno de formularios
Firmas digitales XAdES/PAdES
Cifrado y marcas de agua
Fusionar/Dividir

Contexto regulatorio: VeriFactu, TicketBAI y la penalización de 150.000 €/año

España opera dos marcos nacionales paralelos más fragmentación regional. Para los ISVs que desarrollan software de facturación electrónica, la elección del componente PDF es parte del perímetro de cumplimiento.

VeriFactu (RDL 15/2025) — plazo vigente: Las empresas con facturación sujeta al Impuesto sobre Sociedades debían contar con software conforme desde el 1 de enero de 2027; el resto desde el 1 de julio de 2027. Los proveedores de software de facturación estaban obligados a tener productos conformes desde el 29 de julio de 2025. La penalización por incumplimiento asciende a 150.000 €/año para proveedores — un régimen único globalmente donde la sanción recae sobre el proveedor de software, no solo sobre el contribuyente.

CVE-2022-35583 y la cadena de auditoría VeriFactu: El SSRF de wkhtmltopdf heredado por DinkToPdf permite acceder a recursos de red internos. En sistemas que generan facturas VeriFactu con acceso a la AEAT o ERP internos (SAP Business One, Microsoft Dynamics 365), esta vulnerabilidad puede comprometer la cadena de auditoría íntegra exigida por el RDL 15/2025. Un motor comprometido por SSRF invalida la integridad de los registros de facturación.

TicketBAI (Bizkaia, Gipuzkoa, Araba): Las Haciendas Forales del País Vasco exigen facturación electrónica con firma XAdES y QR territorial. DinkToPdf no soporta firmas digitales — toda la firma XAdES debe implementarse fuera del motor PDF, aumentando la complejidad y los puntos de fallo. IronPDF incluye soporte nativo de firma digital (XAdES, PAdES, CAdES) en el mismo paquete, simplificando la arquitectura de cumplimiento TicketBAI.

*Leyenda VERIFACTU y CSS moderno:* La representación gráfica de facturas conformes con VeriFactu exige composición precisa de la leyenda obligatoria `VERIFACTUoFactura verificable en la sede electrónica de la AEAT`, el código QR de la AEAT y los datos de la factura. DinkToPdf, con su motor WebKit de 2015 sin soporte Flexbox/Grid, dificulta severamente la maquetación de estos elementos según las especificaciones técnicas de la AEAT. IronPDF con Chromium moderno soporta toda la especificación CSS3.

iText AGPL y el contexto de facturación español: Muchos equipos que migran desde DinkToPdf evalúan iText/iText7 como alternativa. En el contexto VeriFactu, la licencia AGPL de iText plantea una complejidad adicional: los ISVs de software de facturación sujetos a la penalización de €150K/año que distribuyen soluciones propietarias con iText AGPL deben cumplir también con las obligaciones de copyleft del AGPL, lo que puede requerir la publicación del código fuente del sistema de facturación. IronPDF ofrece licenciamiento comercial predecible sin restricciones de distribución AGPL.

Generación de factura VeriFactu con IronPDF

El siguiente ejemplo genera una factura con la leyenda obligatoria VERI*FACTU, el QR de verificación de la AEAT y formato de divisa en notación española (EUR 1.234,56 €), utilizando Flexbox CSS que DinkToPdf no puede renderizar:

using IronPdf;

// Generar factura conforme con VeriFactu usando Chromium (sin SSRF, soporte CSS3 completo)
var renderer = new ChromePdfRenderer();
var html = @"
<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .factura-header { display: flex; justify-content: space-between; align-items: flex-start; }
        .verifactu-legend {
            border: 2px solid #003366;
            padding: 8px 12px;
            font-size: 10px;
            text-align: center;
            margin-top: 20px;
            width: fit-content;
        }
        table { width: 100%; border-collapse: collapse; margin-top: 20px; }
        th, td { border: 1px solid #ccc; padding: 8px; }
        th { background-color: #003366; color: white; }
    </style>
</head>
<body>
    <div class='factura-header'>
        <div>
            <strong>FACTURA</strong> Nº 2026-0088<br>
            Fecha: 20/05/2026<br>
            NIF Emisor: B-12345678
        </div>
        <div>

            CIF Receptor: A-87654321
        </div>
    </div>
    <table>
        <tr><th>Concepto</th><th>Cantidad</th><th>Precio unit.</th><th>Base imponible</th><th>IVA (21%)</th><th>Total</th></tr>
        <tr><td>Servicio de consultoría</td><td>8 h</td><td>95,00 €</td><td>760,00 €</td><td>159,60 €</td><td>919,60 €</td></tr>
    </table>

    <div class='verifactu-legend'>
        <strong>VERI*FACTU</strong><br>
        Factura verificable en la sede electrónica de la AEAT<br>
        [QR AEAT — sede.agenciatributaria.gob.es]
    </div>
</body>
</html>";

var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("factura-verifactu-2026-0088.pdf");
using IronPdf;

// Generar factura conforme con VeriFactu usando Chromium (sin SSRF, soporte CSS3 completo)
var renderer = new ChromePdfRenderer();
var html = @"
<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .factura-header { display: flex; justify-content: space-between; align-items: flex-start; }
        .verifactu-legend {
            border: 2px solid #003366;
            padding: 8px 12px;
            font-size: 10px;
            text-align: center;
            margin-top: 20px;
            width: fit-content;
        }
        table { width: 100%; border-collapse: collapse; margin-top: 20px; }
        th, td { border: 1px solid #ccc; padding: 8px; }
        th { background-color: #003366; color: white; }
    </style>
</head>
<body>
    <div class='factura-header'>
        <div>
            <strong>FACTURA</strong> Nº 2026-0088<br>
            Fecha: 20/05/2026<br>
            NIF Emisor: B-12345678
        </div>
        <div>

            CIF Receptor: A-87654321
        </div>
    </div>
    <table>
        <tr><th>Concepto</th><th>Cantidad</th><th>Precio unit.</th><th>Base imponible</th><th>IVA (21%)</th><th>Total</th></tr>
        <tr><td>Servicio de consultoría</td><td>8 h</td><td>95,00 €</td><td>760,00 €</td><td>159,60 €</td><td>919,60 €</td></tr>
    </table>

    <div class='verifactu-legend'>
        <strong>VERI*FACTU</strong><br>
        Factura verificable en la sede electrónica de la AEAT<br>
        [QR AEAT — sede.agenciatributaria.gob.es]
    </div>
</body>
</html>";

var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("factura-verifactu-2026-0088.pdf");
Imports IronPdf

' Generar factura conforme con VeriFactu usando Chromium (sin SSRF, soporte CSS3 completo)
Dim renderer As New ChromePdfRenderer()
Dim html As String = "
<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .factura-header { display: flex; justify-content: space-between; align-items: flex-start; }
        .verifactu-legend {
            border: 2px solid #003366;
            padding: 8px 12px;
            font-size: 10px;
            text-align: center;
            margin-top: 20px;
            width: fit-content;
        }
        table { width: 100%; border-collapse: collapse; margin-top: 20px; }
        th, td { border: 1px solid #ccc; padding: 8px; }
        th { background-color: #003366; color: white; }
    </style>
</head>
<body>
    <div class='factura-header'>
        <div>
            <strong>FACTURA</strong> Nº 2026-0088<br>
            Fecha: 20/05/2026<br>
            NIF Emisor: B-12345678
        </div>
        <div>

            CIF Receptor: A-87654321
        </div>
    </div>
    <table>
        <tr><th>Concepto</th><th>Cantidad</th><th>Precio unit.</th><th>Base imponible</th><th>IVA (21%)</th><th>Total</th></tr>
        <tr><td>Servicio de consultoría</td><td>8 h</td><td>95,00 €</td><td>760,00 €</td><td>159,60 €</td><td>919,60 €</td></tr>
    </table>

    <div class='verifactu-legend'>
        <strong>VERI*FACTU</strong><br>
        Factura verificable en la sede electrónica de la AEAT<br>
        [QR AEAT — sede.agenciatributaria.gob.es]
    </div>
</body>
</html>"

Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("factura-verifactu-2026-0088.pdf")
$vbLabelText   $csharpLabel

Este ejemplo utiliza Flexbox (display: flex) e incluye NIF/CIF del emisor y receptor, formato de divisa español (EUR con separador de miles . y decimal ,), e IVA español al 21%. DinkToPdf no puede renderizar el layout Flexbox de la cabecera ni formatear correctamente la leyenda VERI*FACTU.

Preparación de la migración

Prerrequisitos

Asegúrese de que su entorno cumple estos requisitos:

  • .NET Framework 4.6.2+ o .NET Core 3.1 / .NET 5-9
  • Visual Studio 2019+ o VS Code con extensión de C#
  • Acceso al gestor de paquetes NuGet
  • Clave de licencia de IronPDF (prueba gratuita disponible en ironpdf.com)

Auditoría del uso de DinkToPdf

Ejecute estos comandos en su directorio de soluciones para identificar todas las referencias a DinkToPdf:

# Find all DinkToPdf usages in your codebase
grep -r "using DinkToPdf" --include="*.cs" .
grep -r "SynchronizedConverter\|HtmlToPdfDocument\|ObjectSettings" --include="*.cs" .

# Find NuGet package references
grep -r "DinkToPdf" --include="*.csproj" .

# Find wkhtmltopdf binaries
find . -name "libwkhtmltox*"
# Find all DinkToPdf usages in your codebase
grep -r "using DinkToPdf" --include="*.cs" .
grep -r "SynchronizedConverter\|HtmlToPdfDocument\|ObjectSettings" --include="*.cs" .

# Find NuGet package references
grep -r "DinkToPdf" --include="*.csproj" .

# Find wkhtmltopdf binaries
find . -name "libwkhtmltox*"
SHELL

Cambios importantes que hay que anticipar

Cambio DinkToPdf IronPDF Impacto
Convertidor SynchronizedConverter(new PdfTools()) ChromePdfRenderer Instanciación más sencilla
Documento HtmlToPdfDocument Llamada directa a métodos Sin objeto documento
Configuración GlobalSettings + ObjectSettings RenderingOptions Objeto de opciones único
Tipo de retorno byte[] PdfDocument Objeto más potente
Binario nativo libwkhtmltox.dll/so Ninguno (gestionado) Eliminar archivos nativos
Seguridad de hilos SynchronizedConverter requerido Thread-safe por defecto Código más sencillo
Firmas digitales Requiere biblioteca externa Nativo (XAdES, PAdES) Cumplimiento TicketBAI simplificado

Proceso de migración paso a paso

Paso 1: Actualizar paquetes NuGet

Elimine DinkToPdf e instale IronPDF:

# Remove DinkToPdf
dotnet remove package DinkToPdf

# Install IronPDF
dotnet add package IronPdf
# Remove DinkToPdf
dotnet remove package DinkToPdf

# Install IronPDF
dotnet add package IronPdf
SHELL

Paso 2: Eliminar binarios nativos

Elimine estos archivos específicos de la plataforma de su proyecto:

  • libwkhtmltox.dll (Windows)
  • libwkhtmltox.so (Linux)
  • libwkhtmltox.dylib (macOS)

IronPDF no tiene dependencias nativas: todo es código gestionado.

Paso 3: Actualizar referencias de espacios de nombres

Sustituya los espacios de nombres de DinkToPdf por IronPDF:

// Remove these
using DinkToPdf;
using DinkToPdf.Contracts;

// Add this
using IronPdf;
// Remove these
using DinkToPdf;
using DinkToPdf.Contracts;

// Add this
using IronPdf;
Imports IronPdf
$vbLabelText   $csharpLabel

Paso 4: Configurar la licencia

// Add at application startup (Program.cs or Global.asax)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Add at application startup (Program.cs or Global.asax)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
' Add at application startup (Program.vb or Global.asax)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

Referencia completa de migración de API

Mapeo de clases principales

DinkToPdf IronPDF
SynchronizedConverter ChromePdfRenderer
BasicConverter ChromePdfRenderer
PdfTools No es necesario
HtmlToPdfDocument No es necesario
GlobalSettings RenderingOptions
ObjectSettings RenderingOptions
MarginSettings Propiedades de márgenes individuales

Mapeo de GlobalSettings

Configuración global de DinkToPdf Equivalente de IronPDF
ColorMode = ColorMode.Color Por defecto (siempre en color)
Orientation = Orientation.Portrait PaperOrientation = PdfPaperOrientation.Portrait
Orientation = Orientation.Landscape PaperOrientation = PdfPaperOrientation.Landscape
PaperSize = PaperKind.A4 PaperSize = PdfPaperSize.A4
Margins = new MarginSettings() Propiedades de márgenes individuales

Mapeo de MarginSettings

Márgenes de DinkToPdf Equivalente de IronPDF
Margins.Top = 10 MarginTop = 10
Margins.Bottom = 10 MarginBottom = 10
Margins.Left = 15 MarginLeft = 15
Margins.Right = 15 MarginRight = 15

Ejemplos de migración de código

HTML básico a PDF

La conversión fundamental demuestra la simplificación de la configuración verbosa de DinkToPdf a la API de IronPDF.

Implementación de DinkToPdf:

// NuGet: Install-Package DinkToPdf
using DinkToPdf;
using DinkToPdf.Contracts;
using System.IO;

class Program
{
    static void Main()
    {
        var converter = new SynchronizedConverter(new PdfTools());
        var doc = new HtmlToPdfDocument()
        {
            GlobalSettings = {
                ColorMode = ColorMode.Color,
                Orientation = Orientation.Portrait,
                PaperSize = PaperKind.A4,
            },
            Objects = {
                new ObjectSettings() {
                    HtmlContent = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>",
                    WebSettings = { DefaultEncoding = "utf-8" }
                }
            }
        };
        byte[] pdf = converter.Convert(doc);
        File.WriteAllBytes("output.pdf", pdf);
    }
}
// NuGet: Install-Package DinkToPdf
using DinkToPdf;
using DinkToPdf.Contracts;
using System.IO;

class Program
{
    static void Main()
    {
        var converter = new SynchronizedConverter(new PdfTools());
        var doc = new HtmlToPdfDocument()
        {
            GlobalSettings = {
                ColorMode = ColorMode.Color,
                Orientation = Orientation.Portrait,
                PaperSize = PaperKind.A4,
            },
            Objects = {
                new ObjectSettings() {
                    HtmlContent = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>",
                    WebSettings = { DefaultEncoding = "utf-8" }
                }
            }
        };
        byte[] pdf = converter.Convert(doc);
        File.WriteAllBytes("output.pdf", pdf);
    }
}
Imports DinkToPdf
Imports DinkToPdf.Contracts
Imports System.IO

Module Program
    Sub Main()
        Dim converter = New SynchronizedConverter(New PdfTools())
        Dim doc = New HtmlToPdfDocument() With {
            .GlobalSettings = New GlobalSettings() With {
                .ColorMode = ColorMode.Color,
                .Orientation = Orientation.Portrait,
                .PaperSize = PaperKind.A4
            },
            .Objects = {
                New ObjectSettings() With {
                    .HtmlContent = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>",
                    .WebSettings = New WebSettings() With {
                        .DefaultEncoding = "utf-8"
                    }
                }
            }
        }
        Dim pdf As Byte() = converter.Convert(doc)
        File.WriteAllBytes("output.pdf", pdf)
    End Sub
End Module
$vbLabelText   $csharpLabel

Implementación de IronPDF:

// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF from HTML.</p>");
        pdf.SaveAs("output.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF from HTML.</p>");
        pdf.SaveAs("output.pdf");
    }
}
Imports IronPdf
Imports System

Class Program
    Shared Sub Main()
        Dim renderer = New ChromePdfRenderer()
        Dim pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF from HTML.</p>")
        pdf.SaveAs("output.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

IronPDF reduce una configuración de DinkToPdf de 20 líneas a 4 líneas. No SynchronizedConverter, no PdfTools, no HtmlToPdfDocument, no ObjectSettings — solo renderiza y guarda. Para más opciones, consulte la documentación HTML a PDF.

Conversión de URL a PDF

Implementación de DinkToPdf:

// NuGet: Install-Package DinkToPdf
using DinkToPdf;
using DinkToPdf.Contracts;
using System.IO;

class Program
{
    static void Main()
    {
        var converter = new SynchronizedConverter(new PdfTools());
        var doc = new HtmlToPdfDocument()
        {
            GlobalSettings = {
                ColorMode = ColorMode.Color,
                Orientation = Orientation.Portrait,
                PaperSize = PaperKind.A4,
            },
            Objects = {
                new ObjectSettings() {
                    Page = "https://www.example.com",
                }
            }
        };
        byte[] pdf = converter.Convert(doc);
        File.WriteAllBytes("webpage.pdf", pdf);
    }
}
// NuGet: Install-Package DinkToPdf
using DinkToPdf;
using DinkToPdf.Contracts;
using System.IO;

class Program
{
    static void Main()
    {
        var converter = new SynchronizedConverter(new PdfTools());
        var doc = new HtmlToPdfDocument()
        {
            GlobalSettings = {
                ColorMode = ColorMode.Color,
                Orientation = Orientation.Portrait,
                PaperSize = PaperKind.A4,
            },
            Objects = {
                new ObjectSettings() {
                    Page = "https://www.example.com",
                }
            }
        };
        byte[] pdf = converter.Convert(doc);
        File.WriteAllBytes("webpage.pdf", pdf);
    }
}
Imports DinkToPdf
Imports DinkToPdf.Contracts
Imports System.IO

Module Program
    Sub Main()
        Dim converter = New SynchronizedConverter(New PdfTools())
        Dim doc = New HtmlToPdfDocument() With {
            .GlobalSettings = New GlobalSettings() With {
                .ColorMode = ColorMode.Color,
                .Orientation = Orientation.Portrait,
                .PaperSize = PaperKind.A4
            },
            .Objects = New List(Of ObjectSettings) From {
                New ObjectSettings() With {
                    .Page = "https://www.example.com"
                }
            }
        }
        Dim pdf As Byte() = converter.Convert(doc)
        File.WriteAllBytes("webpage.pdf", pdf)
    End Sub
End Module
$vbLabelText   $csharpLabel

Implementación de IronPDF:

// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
        pdf.SaveAs("webpage.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
        pdf.SaveAs("webpage.pdf");
    }
}
Imports IronPdf
Imports System

Class Program
    Shared Sub Main()
        Dim renderer = New ChromePdfRenderer()
        Dim pdf = renderer.RenderUrlAsPdf("https://www.example.com")
        pdf.SaveAs("webpage.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

RenderUrlAsPdf de IronPDF reemplaza la configuración anidada ObjectSettings.Page con una llamada de método directa. Para obtener más opciones, consulte URL a la documentación en PDF.

Configuración personalizada con apaisado y márgenes

Implementación de DinkToPdf:

// NuGet: Install-Package DinkToPdf
using DinkToPdf;
using DinkToPdf.Contracts;
using System.IO;

class Program
{
    static void Main()
    {
        var converter = new SynchronizedConverter(new PdfTools());
        var doc = new HtmlToPdfDocument()
        {
            GlobalSettings = {
                ColorMode = ColorMode.Color,
                Orientation = Orientation.Landscape,
                PaperSize = PaperKind.A4,
                Margins = new MarginSettings { Top = 10, Bottom = 10, Left = 15, Right = 15 }
            },
            Objects = {
                new ObjectSettings() {
                    HtmlContent = "<h1>Custom PDF</h1><p>Landscape orientation with custom margins.</p>",
                    WebSettings = { DefaultEncoding = "utf-8" }
                }
            }
        };
        byte[] pdf = converter.Convert(doc);
        File.WriteAllBytes("custom.pdf", pdf);
    }
}
// NuGet: Install-Package DinkToPdf
using DinkToPdf;
using DinkToPdf.Contracts;
using System.IO;

class Program
{
    static void Main()
    {
        var converter = new SynchronizedConverter(new PdfTools());
        var doc = new HtmlToPdfDocument()
        {
            GlobalSettings = {
                ColorMode = ColorMode.Color,
                Orientation = Orientation.Landscape,
                PaperSize = PaperKind.A4,
                Margins = new MarginSettings { Top = 10, Bottom = 10, Left = 15, Right = 15 }
            },
            Objects = {
                new ObjectSettings() {
                    HtmlContent = "<h1>Custom PDF</h1><p>Landscape orientation with custom margins.</p>",
                    WebSettings = { DefaultEncoding = "utf-8" }
                }
            }
        };
        byte[] pdf = converter.Convert(doc);
        File.WriteAllBytes("custom.pdf", pdf);
    }
}
Imports DinkToPdf
Imports DinkToPdf.Contracts
Imports System.IO

Module Program
    Sub Main()
        Dim converter = New SynchronizedConverter(New PdfTools())
        Dim doc = New HtmlToPdfDocument() With {
            .GlobalSettings = New GlobalSettings() With {
                .ColorMode = ColorMode.Color,
                .Orientation = Orientation.Landscape,
                .PaperSize = PaperKind.A4,
                .Margins = New MarginSettings() With {
                    .Top = 10,
                    .Bottom = 10,
                    .Left = 15,
                    .Right = 15
                }
            },
            .Objects = {
                New ObjectSettings() With {
                    .HtmlContent = "<h1>Custom PDF</h1><p>Landscape orientation with custom margins.</p>",
                    .WebSettings = New WebSettings() With {
                        .DefaultEncoding = "utf-8"
                    }
                }
            }
        }
        Dim pdf As Byte() = converter.Convert(doc)
        File.WriteAllBytes("custom.pdf", pdf)
    End Sub
End Module
$vbLabelText   $csharpLabel

Implementación de IronPDF:

// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
        renderer.RenderingOptions.MarginTop = 10;
        renderer.RenderingOptions.MarginBottom = 10;
        renderer.RenderingOptions.MarginLeft = 15;
        renderer.RenderingOptions.MarginRight = 15;

        var pdf = renderer.RenderHtmlAsPdf("<h1>Custom PDF</h1><p>Landscape orientation with custom margins.</p>");
        pdf.SaveAs("custom.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
        renderer.RenderingOptions.MarginTop = 10;
        renderer.RenderingOptions.MarginBottom = 10;
        renderer.RenderingOptions.MarginLeft = 15;
        renderer.RenderingOptions.MarginRight = 15;

        var pdf = renderer.RenderHtmlAsPdf("<h1>Custom PDF</h1><p>Landscape orientation with custom margins.</p>");
        pdf.SaveAs("custom.pdf");
    }
}
Imports IronPdf
Imports IronPdf.Rendering
Imports System

Module Program
    Sub Main()
        Dim renderer As New ChromePdfRenderer()
        renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape
        renderer.RenderingOptions.MarginTop = 10
        renderer.RenderingOptions.MarginBottom = 10
        renderer.RenderingOptions.MarginLeft = 15
        renderer.RenderingOptions.MarginRight = 15

        Dim pdf = renderer.RenderHtmlAsPdf("<h1>Custom PDF</h1><p>Landscape orientation with custom margins.</p>")
        pdf.SaveAs("custom.pdf")
    End Sub
End Module
$vbLabelText   $csharpLabel

RenderingOptions de IronPDF reemplaza tanto GlobalSettings como MarginSettings con una API unificada. Para más opciones de configuración, consulte la documentación sobre opciones de renderización.

Cumplimiento LOPDGDD, eIDAS y Crea y Crece: el entorno regulatorio completo

España opera un entorno de cumplimiento para la facturación electrónica que va más allá de VeriFactu y TicketBAI. Migrar a un componente PDF que soporte este entorno completo reduce el riesgo de tener que cambiar de motor de renderizado nuevamente cuando entren en vigor los siguientes plazos regulatorios.

LOPDGDD y protección de datos en la generación de PDF

Para los sistemas de facturación electrónica en España, la generación de PDFs que contienen datos personales (NIF/CIF, datos fiscales, información de clientes) está sujeta a la LOPDGDD (Ley Orgánica de Protección de Datos y Garantía de Derechos Digitales) y a la supervisión de la AEPD (Agencia Española de Protección de Datos).

El procesamiento de documentos que contienen datos fiscales identificativos (NIF, CIF, domicilio fiscal) en entornos cloud plantea consideraciones bajo el RGPD/LOPDGDD respecto a las transferencias internacionales de datos. IronPDF permite el procesamiento on-premise — el motor de renderizado opera localmente dentro del perímetro de la organización, sin enviar contenido de facturas a servicios externos. Esto simplifica el análisis de cumplimiento LOPDGDD para ISVs que gestionan datos fiscales de contribuyentes españoles.

eIDAS, FNMT-RCM y firma de facturas electrónicas

Para operaciones de firma digital de facturas conforme a eIDAS, IronPDF soporta certificados emitidos por la FNMT-RCM (Fábrica Nacional de Moneda y Timbre), la autoridad de certificación española reconocida por la AEAT para facturas electrónicas y comunicaciones con la administración pública (FACe, sede.agenciatributaria.gob.es).

Crea y Crece: el siguiente horizonte regulatorio

La Ley Crea y Crece establece la obligatoriedad de la facturación electrónica B2B en España: desde 2027 para empresas con facturación superior a 8M€, y desde 2028 para el resto de autónomos y pymes. Las facturas bajo Crea y Crece deben respetar el estándar europeo EN 16931 y su implementación española CIUS-ES, lo que implica formatos estructurados (Facturae XML) con posible adjunto en PDF/A para la representación visual.

Para los ISVs que están migrando su motor PDF ahora, elegir IronPDF — que soporta PDF/A, firmas PAdES y procesamiento de XML estructurado en el mismo paquete — evita un segundo cambio de motor cuando los plazos de Crea y Crece entren en vigor. El SII (Suministro Inmediato de Información) para grandes empresas ya opera en tiempo real con la AEAT, y los sistemas de generación de facturas integrados con SII se benefician de un motor PDF predecible y sin vulnerabilidades SSRF activas.

iText AGPL frente a IronPDF en el contexto VeriFactu

Muchos equipos que migran desde DinkToPdf evalúan iText/iText7 como alternativa por su popularidad en el ecosistema .NET europeo. En el contexto específico de VeriFactu, la licencia AGPL de iText plantea una complejidad adicional que merece análisis explícito:

  • Los ISVs de software de facturación propietario que distribuyen soluciones con iText AGPL están obligados a liberar el código fuente bajo AGPL, o adquirir una licencia comercial de iText.
  • Esta restricción se amplifica bajo el régimen VeriFactu, donde los proveedores de software de facturación ya enfrentan la penalización de 150.000 €/año por incumplimiento — y donde la incertidumbre sobre el licenciamiento AGPL puede complicar la certificación del software ante la AEAT.
  • IronPDF ofrece licenciamiento comercial predecible con una única tarifa sin restricciones de distribución AGPL, simplificando el análisis de cumplimiento para ISVs que distribuyen software de facturación certificado.

En España, el término "software libre" connota específicamente código abierto / FOSS (no "gratuito"). Usar "software libre" para referirse al coste cero crea confusión de licenciamiento precisamente donde IronPDF y iText compiten directamente en el segmento de ISVs de facturación electrónica.

Notas de migración críticas

Quitar binarios nativos

El paso de limpieza más importante es eliminar los binarios nativos de wkhtmltopdf. IronPDF no tiene dependencias nativas:

# Delete native binaries
rm libwkhtmltox.* 2>/dev/null
# Delete native binaries
rm libwkhtmltox.* 2>/dev/null
SHELL

No se requiere Singleton

El SynchronizedConverter de DinkToPdf tuvo que registrarse como singleton para evitar fallas. El ChromePdfRenderer de IronPDF es thread-safe con cualquier duración de DI:

// DinkToPdf - MUST be singleton
services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools()));

// IronPDF - any lifetime works
services.AddScoped<ChromePdfRenderer>();
// Or just create inline:
var renderer = new ChromePdfRenderer();
// DinkToPdf - MUST be singleton
services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools()));

// IronPDF - any lifetime works
services.AddScoped<ChromePdfRenderer>();
// Or just create inline:
var renderer = new ChromePdfRenderer();
$vbLabelText   $csharpLabel

Tipo de retorno más rico

DinkToPdf devuelve byte[]. IronPDF devuelve PdfDocument con capacidades de manipulación:

// DinkToPdf returns byte[]
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("output.pdf", pdf);
return File(pdf, "application/pdf");

// IronPDF returns PdfDocument
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
return File(pdf.BinaryData, "application/pdf");
// DinkToPdf returns byte[]
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("output.pdf", pdf);
return File(pdf, "application/pdf");

// IronPDF returns PdfDocument
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
return File(pdf.BinaryData, "application/pdf");
$vbLabelText   $csharpLabel

Compatibilidad total con CSS3

Los diseños modernos que fallan en DinkToPdf funcionan perfectamente en IronPDF:

// DinkToPdf - doesn't work (wkhtmltopdf uses 2015 WebKit)
var html = "<div style='display: flex;'>...</div>";  // Broken!

// IronPDF - full support (modern Chromium)
var html = @"
    <div style='display: flex; justify-content: space-between;'>
        <div>Left</div>
        <div>Right</div>
    </div>";
var pdf = renderer.RenderHtmlAsPdf(html);  // Works!
// DinkToPdf - doesn't work (wkhtmltopdf uses 2015 WebKit)
var html = "<div style='display: flex;'>...</div>";  // Broken!

// IronPDF - full support (modern Chromium)
var html = @"
    <div style='display: flex; justify-content: space-between;'>
        <div>Left</div>
        <div>Right</div>
    </div>";
var pdf = renderer.RenderHtmlAsPdf(html);  // Works!
$vbLabelText   $csharpLabel

Lista de comprobación posterior a la migración

Después de completar la migración del código, verifique lo siguiente:

  • Ejecute todas las pruebas unitarias para verificar que la generación de PDF funcione correctamente
  • Pruebe escenarios multiproceso (estos fallaron con DinkToPdf)
  • Comparar la calidad de salida del PDF (Chromium de IronPDF renderiza mejor)
  • Verificar la representación CSS (Flexbox/Grid ahora funciona)
  • Pruebe la ejecución de JavaScript (fiable con IronPDF)
  • Actualizar las canalizaciones CI/CD para eliminar la instalación de wkhtmltopdf
  • Verificar los pases de escaneo de seguridad (sin indicadores CVE-2022-35583)
  • Eliminar la implementación binaria nativa de los scripts de despliegue/Docker
  • Incorporar leyenda VERI*FACTU o Factura verificable en la sede electrónica de la AEAT si el software gestiona facturación española bajo RDL 15/2025
  • Validar QR de la AEAT y compatibilidad con TicketBAI (Bizkaia, Gipuzkoa, Araba)
  • Verificar soporte de certificados FNMT-RCM para firmas digitales eIDAS
  • Revisar el análisis de cumplimiento LOPDGDD/AEPD para el procesamiento on-premise

Proteja su software de facturación ante la AEAT

Con el plazo VeriFactu activo desde el 29 de julio de 2025 para proveedores de software, y las penalizaciones de hasta 150.000 €/año para ISVs no conformes, la elección del componente PDF es parte del perímetro de auditoría ante la AEAT. IronPDF, con motor Chromium moderno, elimina CVE-2022-35583 de la cadena de generación de facturas, soporta la leyenda VERI*FACTU con CSS3 completo, e incluye firmas digitales XAdES nativas para cumplimiento TicketBAI en Bizkaia, Gipuzkoa y Araba. Para los ISVs que evaluaban iText/iText7 como alternativa, IronPDF ofrece licenciamiento comercial predecible sin las restricciones de distribución AGPL que complican la situación de los proveedores de software de facturación bajo el régimen de penalizaciones VeriFactu.

Recursos adicionales


La migración de DinkToPdf a IronPDF elimina vulnerabilidades críticas de seguridad (CVE-2022-35583), fallos de seguridad de hilos, complejidad de despliegue de binarios nativos y renderizado CSS obsoleto. Para los ISVs españoles bajo VeriFactu (RDL 15/2025), TicketBAI (Bizkaia, Gipuzkoa, Araba) o Facturae/FACe, la transición elimina el riesgo SSRF de la cadena de facturación, habilita la leyenda VERI*FACTU con CSS3 completo y proporciona firmas digitales XAdES nativas — con licenciamiento comercial predecible frente al AGPL de iText, compatible con los requisitos de distribución del software de facturación certificado ante la AEAT.

Preguntas Frecuentes

¿Por qué DinkToPdf es un riesgo bajo VeriFactu (RDL 15/2025)?

DinkToPdf hereda CVE-2022-35583 (SSRF) de wkhtmltopdf, que permite acceder a recursos de red internos. En sistemas de facturación VeriFactu con acceso a la AEAT o ERP internos, esto compromete la cadena de auditoría íntegra exigida por el RDL 15/2025. Además, el motor WebKit de 2015 no soporta Flexbox/Grid, dificultando la maquetación de la leyenda obligatoria VERI*FACTU. Los proveedores de software no conformes se exponen a penalizaciones de hasta 150.000 €/año.

¿IronPDF soporta TicketBAI en Bizkaia, Gipuzkoa y Araba?

Sí. IronPDF incluye soporte nativo de firmas digitales XAdES, PAdES y CAdES, necesarias para la firma de facturas TicketBAI en las tres provincias del País Vasco (Bizkaia, Gipuzkoa, Araba). A diferencia de DinkToPdf, que no tiene capacidades de firma digital, IronPDF permite implementar la firma XAdES dentro del mismo paquete sin bibliotecas externas adicionales.

¿Por qué es relevante la LOPDGDD al elegir una biblioteca PDF para facturación en España?

Los PDFs de facturas contienen datos personales y fiscales (NIF, CIF, domicilio fiscal) sujetos a la LOPDGDD y supervisados por la AEPD. IronPDF permite el procesamiento on-premise, manteniendo el contenido de las facturas dentro del perímetro de la organización sin enviar datos a servicios externos. Esto simplifica el análisis de cumplimiento LOPDGDD para ISVs que gestionan datos fiscales de contribuyentes españoles.

¿Cuál es la diferencia entre usar iText AGPL e IronPDF para software de facturación VeriFactu?

iText/iText7 utiliza licencia AGPL. Los ISVs de software de facturación propietario que distribuyen soluciones con iText AGPL deben cumplir con las obligaciones de copyleft del AGPL, lo que puede requerir publicar el código fuente. Esta complejidad se amplifica bajo el régimen VeriFactu, donde los proveedores de software de facturación ya enfrentan la penalización de 150.000 €/año por incumplimiento. IronPDF ofrece licenciamiento comercial predecible sin restricciones de distribución AGPL.

¿IronPDF soporta certificados FNMT-RCM para firma digital en España?

Sí. IronPDF soporta certificados digitales emitidos por la FNMT-RCM (Fábrica Nacional de Moneda y Timbre), la autoridad de certificación española reconocida por la AEAT. Esto permite la firma de facturas electrónicas conforme a eIDAS para comunicaciones con la administración pública española (FACe, sede.agenciatributaria.gob.es).

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