Ejemplo en JAVA

Ejemplo de uso del API SAT en java.

Archivo fuente: java.java

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * Ejemplo Java — POST /api/v1/usuario/datos-fiscales
 *
 * Dependencias Maven:
 *   <dependency>
 *     <groupId>com.fasterxml.jackson.core</groupId>
 *     <artifactId>jackson-databind</artifactId>
 *     <version>2.16.0</version>
 *   </dependency>
 *
 * Uso:
 *   export SAT_API_KEY="sat_xxxxxxxxxxxx"
 *   java -cp target/classes:target/dependency/* SatApiExample [RFC]
 */
public class SatApiExample {

    private static final String BASE_URL = "https://api.cfdi4.com";

    private static final String USER_AGENT = "java-sat-api/1.0";
    private final String apiKey;
    private final HttpClient http;
    private final ObjectMapper mapper;

    public SatApiExample(String apiKey) {
        this.apiKey = apiKey;
        this.http = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(10))
            .build();
        this.mapper = new ObjectMapper();
    }

    public Map<String, Object> datosFiscales(String rfc) throws Exception {
        return post("/api/v1/usuario/datos-fiscales",
            Map.of("rfc", rfc.toUpperCase().trim()));
    }

    @SuppressWarnings("unchecked")
    private Map<String, Object> post(String endpoint, Map<String, String> body) throws Exception {
        String url = BASE_URL + endpoint;
        String jsonBody = mapper.writeValueAsString(body);

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(url))
            .timeout(Duration.ofSeconds(30))
            .header("Authorization", "Bearer " + apiKey)
            .header("User-Agent", USER_AGENT)
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
            .build();

        HttpResponse<String> response = http.send(request, HttpResponse.BodyHandlers.ofString());
        Map<String, Object> parsed = mapper.readValue(response.body(), Map.class);
        return (Map<String, Object>) parsed.getOrDefault("body", Map.of());
    }

    public static void main(String[] args) {
        String apiKey = System.getenv("SAT_API_KEY");
        if (apiKey == null || apiKey.isEmpty()) {
            System.err.println("ERROR: configura la variable de entorno SAT_API_KEY");
            System.err.println("  export SAT_API_KEY=\"sat_xxxxxxxxxxxx\"");
            System.exit(1);
        }

        String rfc = args.length > 0 ? args[0] : "XAXX010101000";
        System.out.println("Consultando datos fiscales de RFC: " + rfc + "\n");

        try {
            SatApiExample client = new SatApiExample(apiKey);
            Map<String, Object> result = client.datosFiscales(rfc);

            int codigo = ((Number) result.getOrDefault("cfdi_codigo", 0)).intValue();
            String texto = (String) result.getOrDefault("cfdi_texto", "");
            String desc = (String) result.getOrDefault("cfdi_descripcion", "");
            int saldo = ((Number) result.getOrDefault("saldo", 0)).intValue();

            System.out.printf("  Código:    %d%n", codigo);
            System.out.printf("  Texto:     %s%n", texto);
            System.out.printf("  Detalle:   %s%n", desc);
            System.out.printf("  Saldo:     %d créditos%n", saldo);

            if (codigo == 1) {
                Object data = result.get("data");
                System.out.println("\n  Datos fiscales:");
                System.out.println("  " + new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(data));
                System.exit(0);
            } else if (codigo == 1004) {
                System.out.println("\n  ⚠️  Saldo insuficiente. Recarga en https://panel.cfdi4.com/saldos");

            } else if (codigo == 1001) {
                System.out.println("\n  ⚠️  API key inválida");
            }
        } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
        }
        System.exit(1);
    }
}