Las aplicaciones de escritorio antiguas no desaparecen de la noche a la mañana. Muchas empresas siguen operando con software desarrollado hace décadas en Visual Basic 6, Delphi, FoxPro o incluso aplicaciones DOS adaptadas a Windows. Estos sistemas no están diseñados para consumir APIs REST modernas, pero necesitan cumplir con VeriFactu igual que cualquier otra solución de facturación.
La cuestión es cómo adaptarse sin reescribir decenas de miles de líneas de código que llevan años funcionando.
En este artículo
El problema técnico real
Las aplicaciones legacy tienen limitaciones arquitectónicas concretas:
- Sin librerías HTTP modernas: Muchas no pueden hacer llamadas HTTPS con TLS 1.2+
- Sin parseo JSON nativo: Trabajaban con formatos planos, DBF o XML básico.
- Sin gestión de certificados digitales: No están preparadas para manejar autenticación por certificado.
- Entornos de ejecución obsoletos: Runtimes que no reciben actualizaciones desde hace años.
Reescribir estas aplicaciones para integrar una API REST no es solo costoso, en la mayoría de casos el código fuente original ya no está disponible, el desarrollador original ya no trabaja en la empresa, o la aplicación está tan entrelazada con lógica de negocio crítica que modificarla es demasiado arriesgado.
La solución: ejecutables como puente de integración
La forma más práctica de conectar este tipo de aplicaciones con servicios modernos es usar un ejecutable intermedio que actúe como traductor. La aplicación antigua escribe datos en un formato que conoce (archivos de texto, XML, línea de comandos), llama al ejecutable, y este se encarga de la comunicación con la API.
Este patrón no es nuevo. Se usa en integraciones bancarias, EDI, y cualquier escenario donde los sistemas antiguos necesitan hablar con protocolos modernos.
Ejemplo de flujo de integración
[Aplicación legacy]
↓ (escribe archivo XML o JSON con datos de factura)
[Archivo temporal: factura.json]
↓ (la app ejecuta el .exe con parámetros)
[Ejecutable VeriFactu]
↓ (lee el archivo, firma, envía a AEAT)
[API VeriFactu] → [AEAT]
↓ (respuesta)
[Archivo de respuesta: resultado.json]
↓ (la app legacy lee el resultado)
[Aplicación legacy procesa el resultado]
Implementación práctica
Paso 1: Preparar los datos desde la aplicación antigua
La aplicación legacy debe generar un archivo con los datos de la factura. El formato más sencillo es JSON, pero si la aplicación no puede generarlo, un archivo de texto estructurado o XML también funciona.
Ejemplo de archivo factura.json:
{
"numero_factura": "2025/0042",
"fecha": "2025-01-15",
"cliente_nif": "B12345678",
"base_imponible": 1000.00,
"iva": 210.00,
"total": 1210.00,
"conceptos": [
{
"descripcion": "Servicios consultoría",
"cantidad": 1,
"precio_unitario": 1000.00
}
]
}
Si la aplicación legacy está escrita en Visual Basic 6, el código para generar este archivo sería:
Private Sub GenerarArchivoFactura()
Dim rutaArchivo As String
Dim contenido As String
rutaArchivo = App.Path & "\factura.json"
contenido = "{" & vbCrLf
contenido = contenido & " ""numero_factura"": """ & txtNumFactura.Text & """," & vbCrLf
contenido = contenido & " ""fecha"": """ & Format(dtpFecha.Value, "yyyy-mm-dd") & """," & vbCrLf
contenido = contenido & " ""cliente_nif"": """ & txtNIF.Text & """," & vbCrLf
contenido = contenido & " ""base_imponible"": " & txtBase.Text & "," & vbCrLf
contenido = contenido & " ""iva"": " & txtIVA.Text & "," & vbCrLf
contenido = contenido & " ""total"": " & txtTotal.Text & vbCrLf
contenido = contenido & "}"
Open rutaArchivo For Output As #1
Print #1, contenido
Close #1
End Sub
Paso 2: Llamar al ejecutable
Una vez generado el archivo, la aplicación legacy ejecuta el .exe pasándole la ruta del archivo como parámetro:
Private Sub EnviarFacturaVeriFactu()
Dim rutaExe As String
Dim rutaFactura As String
Dim comando As String
rutaExe = App.Path & "\verifactu.exe"
rutaFactura = App.Path & "\factura.json"
comando = rutaExe & " enviar --archivo """ & rutaFactura & """ --output resultado.json"
Shell comando, vbNormalFocus
End Sub
En aplicaciones Delphi, el equivalente sería:
procedure TFormFactura.EnviarFactura;
var
comando: string;
resultado: Cardinal;
begin
comando := ExtractFilePath(Application.ExeName) +
'verifactu.exe enviar --archivo factura.json --output resultado.json';
resultado := ShellExecute(Handle, 'open', PChar(comando), nil, nil, SW_SHOWNORMAL);
if resultado <= 32 then
ShowMessage('Error al ejecutar VeriFactu');
end;
Paso 3: Procesar la respuesta
El ejecutable escribe el resultado en un archivo (por ejemplo, resultado.json). La aplicación legacy lee este archivo para saber si el envío fue exitoso:
{
"estado": "aceptada",
"csv": "ABC123XYZ789",
"fecha_envio": "2025-01-15T10:30:45Z",
"codigo_aeat": "ACEPTADO"
}
Código VB6 para procesar la respuesta:
Private Function LeerRespuesta() As Boolean
Dim rutaRespuesta As String
Dim contenido As String
Dim estadoInicio As Long
Dim estadoFin As Long
Dim estado As String
rutaRespuesta = App.Path & "\resultado.json"
Open rutaRespuesta For Input As #1
contenido = Input$(LOF(1), 1)
Close #1
' Parsing básico de JSON (en VB6)
estadoInicio = InStr(contenido, """estado"": """) + 12
estadoFin = InStr(estadoInicio, contenido, """")
estado = Mid(contenido, estadoInicio, estadoFin - estadoInicio)
If estado = "aceptada" Then
LeerRespuesta = True
MsgBox "Factura enviada correctamente a VeriFactu"
Else
LeerRespuesta = False
MsgBox "Error al enviar factura"
End If
End Function
Consideraciones técnicas
Si la aplicación legacy necesita esperar la respuesta antes de continuar, usa Shell con espera bloqueante o escribe un bucle que verifique la existencia del archivo de respuesta.
En VB6, puedes usar la API de Windows:
Private Declare Function WaitForSingleObject Lib "kernel32" _
(ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" _
(ByVal hObject As Long) As Long
Private Sub EjecutarYEsperar(comando As String)
Dim taskID As Long
Dim hProcess As Long
Const SYNCHRONIZE = &H100000
taskID = Shell(comando, vbNormalFocus)
hProcess = OpenProcess(SYNCHRONIZE, False, taskID)
WaitForSingleObject hProcess, -1 ' Esperar indefinidamente
CloseHandle hProcess
End Sub
Gestión de errores
El ejecutable debe devolver códigos de error claros. Y por su parte, la aplicación legacy debe verificar:
- Que el archivo de respuesta se haya generado
- Que el contenido sea válido
- Que el estado indique éxito o error específico
Seguridad
Los archivos temporales con datos fiscales no deben quedar expuestos. Opciones para lograrlo:
- Escribir en carpetas con permisos restringidos
- Borrar archivos inmediatamente después de procesarlos
- Usar nombres de archivo únicos (timestamp, GUID) para evitar colisiones
Logs y trazabilidad
El ejecutable debe generar logs de todas las operaciones. La aplicación legacy puede leer estos logs para realizar una depuración o auditoría posterior.
Alternativa: stdin/stdout
Si tu aplicación legacy puede capturar la salida estándar de procesos, puedes pasar los datos directamente sin archivos intermedios:
echo '{"numero_factura":"2025/0042",...}' | verifactu.exe enviar --stdin
Esto elimina archivos temporales y simplifica el flujo.
Mantenimiento a largo plazo
Este enfoque tiene ventajas de mantenimiento:
- La aplicación legacy no cambia su lógica de negocio.
- Las actualizaciones de VeriFactu solo afectan al ejecutable.
- Si la normativa cambia, solo se actualiza el .exe, no la aplicación antigua.
- Puedes utilizar el mismo patrón para otras integraciones futuras.
Si trabajas con aplicaciones de escritorio antiguas y necesitas integrar VeriFactu, puedes probar nuestra librería ejecutable de VerifactuAPI en el sandbox sin certificado digital y totalmente gratis.


