Guía por stack Java 17+ · Spring Boot 3 HttpClient del JDK

Cómo integrar facturación electrónica en Java con Spring Boot

Integra la facturación electrónica del SRI en una aplicación Spring Boot con el cliente HTTP que trae el JDK. Sin dependencias extra: un servicio y un controlador.

LO QUE VAS A HACER5 pasos

  1. Configura la aplicación
  2. Crea el cliente
  3. Expón un endpoint
  4. Pruébalo
  5. Pasa a producción con buenas prácticas

Antes de empezar

Java 17 o superior

Y Spring Boot 3.

Una API key de pruebas de Flashpi

Guárdala en una variable de entorno, nunca en el código ni en el repositorio.

Solicítala aquí

Tu certificado de firma .p12

Cargado en la cuenta de pruebas.

Cargar el certificado

Tus datos de emisor

RUC, establecimiento y punto de emisión configurados en tu cuenta.

Paso 1 · Configura la aplicación

propertiessrc/main/resources/application.properties
# src/main/resources/application.properties
flashpi.url=https://api.flashpi.ec/v1
flashpi.key=${FLASHPI_API_KEY}

Y exporta la variable antes de arrancar: export FLASHPI_API_KEY="tu_api_key_de_pruebas".

Paso 2 · Crea el cliente

javaFlashpiClient.java
package ec.flashpi.demo;

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class FlashpiClient {

    private final HttpClient http = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(10))
            .build();
    private final String baseUrl;
    private final String apiKey;

    public FlashpiClient(@Value("${flashpi.url}") String baseUrl,
                         @Value("${flashpi.key}") String apiKey) {
        this.baseUrl = baseUrl;
        this.apiKey = apiKey;
    }

    public String emitirFactura(String facturaJson) throws IOException, InterruptedException {
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(baseUrl + "/facturas"))
                .timeout(Duration.ofSeconds(30))
                .header("Authorization", "Bearer " + apiKey)
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(facturaJson))
                .build();

        HttpResponse<String> response = http.send(request, HttpResponse.BodyHandlers.ofString());

        if (response.statusCode() >= 400) {
            throw new IllegalStateException("Flashpi " + response.statusCode() + ": " + response.body());
        }
        return response.body();
    }
}

Paso 3 · Expón un endpoint

javaFacturaController.java
package ec.flashpi.demo;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class FacturaController {

    private final FlashpiClient flashpi;

    public FacturaController(FlashpiClient flashpi) {
        this.flashpi = flashpi;
    }

    @PostMapping(value = "/facturar", consumes = "application/json", produces = "application/json")
    public String facturar(@RequestBody String facturaJson) throws Exception {
        return flashpi.emitirFactura(facturaJson);
    }
}

Paso 4 · Pruébalo

bashterminal
./mvnw spring-boot:run

curl -X POST http://localhost:8080/facturar \
  -H "Content-Type: application/json" \
  -d '{
  "comprador": {
    "tipo_identificacion": "cedula",
    "identificacion": "0102030405",
    "razon_social": "Cliente de ejemplo",
    "email": "[email protected]"
  },
  "detalles": [
    { "descripcion": "Servicio de ejemplo", "cantidad": 1, "precio_unitario": 25.00 }
  ]
}'

Paso 5 · Pasa a producción con buenas prácticas

Maneja IllegalStateException con un @ControllerAdvice, usa @Async o una cola para no bloquear al usuario y registra la clave_acceso de cada comprobante. Si ya usas RestClient o WebClient, la lógica es la misma.

Errores frecuentes

SíntomaCausa probableQué hacerReferencia
401 UnauthorizedAPI key ausente, inválida o de otro ambiente.Revisa el header Authorization y que uses la key del ambiente correcto.Ver detalle
422 Esquema XMLAlgún campo no cumple la estructura esperada.Lee el detalle del error y corrige el campo indicado.Ver detalle
SRI 43Clave de acceso ya registrada.No reenvíes: consulta el estado del comprobante por su clave de acceso.Ver detalle
SRI 70Clave de acceso en procesamiento.Espera unos segundos y consulta el estado. No reenvíes el comprobante.Ver detalle

Siguientes pasos

Empieza hoy

Obtén tu API key y prueba el ejemplo

Prueba la API en el ambiente de pruebas del SRI y pasa a producción cuando estés listo.