Manejo de Errores
Esta guía te muestra cómo manejar errores correctamente cuando usas el SDK de Retorna.
Tipos de Errores
El SDK puede lanzar diferentes tipos de excepciones:
IllegalArgumentException
Lanzada cuando los parámetros proporcionados son inválidos:
try {
CreateOrderInput orderInput = new CreateOrderInput(
// ... parámetros inválidos
);
OrderResponse order = client.order.createPayoutOrder(orderInput);
} catch (IllegalArgumentException e) {
System.err.println("Error de validación: " + e.getMessage());
// Ejemplo: "clientId es requerido"
}
RuntimeException
Lanzada cuando hay errores de API (4xx, 5xx) o problemas de red:
try {
BalanceResponse balance = client.account.getBalance();
} catch (RuntimeException e) {
System.err.println("Error de API: " + e.getMessage());
// Ejemplo: "Error al obtener balance: 401 - Unauthorized"
}
Exception
Lanzada para otros errores generales (parsing, conexión, etc.):
try {
QuoteResponse quote = client.quotation.createQuote(quoteInput);
} catch (Exception e) {
System.err.println("Error general: " + e.getMessage());
e.printStackTrace();
}
Manejo de Errores Recomendado
Patrón Básico
try {
// Operación del SDK
BalanceResponse balance = client.account.getBalance();
System.out.println("Balance: " + balance.getTotalBalance());
} catch (IllegalArgumentException e) {
// Error de validación - datos inválidos
System.err.println("❌ Error de validación: " + e.getMessage());
// Tomar acción correctiva (mostrar mensaje al usuario, etc.)
} catch (RuntimeException e) {
// Error de API - problema con el servidor
System.err.println("❌ Error de API: " + e.getMessage());
// Reintentar, notificar, etc.
} catch (Exception e) {
// Error inesperado
System.err.println("❌ Error inesperado: " + e.getMessage());
e.printStackTrace();
// Logging, notificación, etc.
}
Manejo Específico por Operación
public class RetornaService {
public BalanceResponse getBalanceSafely(RetornaClient client) {
try {
return client.account.getBalance();
} catch (RuntimeException e) {
if (e.getMessage().contains("401") || e.getMessage().contains("403")) {
// Error de autenticación
throw new AuthenticationException("Credenciales inválidas", e);
} else if (e.getMessage().contains("500")) {
// Error del servidor
throw new ServerException("Error del servidor", e);
} else {
throw new RetornaException("Error desconocido", e);
}
}
}
public OrderResponse createOrderSafely(RetornaClient client, CreateOrderInput input) {
try {
return client.order.createPayoutOrder(input);
} catch (IllegalArgumentException e) {
// Error de validación
throw new ValidationException("Datos inválidos: " + e.getMessage(), e);
} catch (RuntimeException e) {
if (e.getMessage().contains("400")) {
// Bad Request
throw new BadRequestException("Solicitud inválida", e);
} else {
throw new RetornaException("Error al crear orden", e);
}
}
}
}
Códigos de Estado HTTP
El SDK puede recibir diferentes códigos de estado HTTP:
| Código | Significado | Acción Recomendada |
|---|---|---|
| 200, 201 | Éxito | Continuar normalmente |
| 400 | Bad Request | Verificar parámetros |
| 401 | Unauthorized | Verificar credenciales |
| 403 | Forbidden | Verificar permisos |
| 404 | Not Found | Recurso no existe |
| 500 | Internal Server Error | Reintentar más tarde |
| 503 | Service Unavailable | Servicio no disponible |
Ejemplo de Manejo por Código
public class ErrorHandler {
public static void handleApiError(RuntimeException e) {
String message = e.getMessage();
if (message.contains("401")) {
System.err.println("❌ Error de autenticación. Verifica tus credenciales.");
} else if (message.contains("403")) {
System.err.println("❌ Acceso denegado. Verifica tus permisos.");
} else if (message.contains("404")) {
System.err.println("❌ Recurso no encontrado.");
} else if (message.contains("400")) {
System.err.println("❌ Solicitud inválida. Verifica los parámetros.");
} else if (message.contains("500") || message.contains("503")) {
System.err.println("❌ Error del servidor. Intenta más tarde.");
} else {
System.err.println("❌ Error desconocido: " + message);
}
}
}
Reintentos Automáticos
El SDK maneja automáticamente algunos reintentos:
- 401/403: El SDK intenta renovar el token y reintentar la solicitud
- Errores de red: Puedes implementar tu propia lógica de reintentos
Implementar Reintentos Manuales
import java.util.concurrent.TimeUnit;
public class RetryExample {
public static BalanceResponse getBalanceWithRetry(
RetornaClient client, int maxRetries) {
int attempts = 0;
while (attempts < maxRetries) {
try {
return client.account.getBalance();
} catch (RuntimeException e) {
attempts++;
if (e.getMessage().contains("500") || e.getMessage().contains("503")) {
// Error del servidor - reintentar
if (attempts < maxRetries) {
System.out.println("Reintentando... (" + attempts + "/" + maxRetries + ")");
try {
TimeUnit.SECONDS.sleep(2 * attempts); // Backoff exponencial
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException("Interrumpido", ie);
}
continue;
}
}
// Otros errores o agotados los reintentos
throw e;
}
}
throw new RuntimeException("No se pudo obtener el balance después de " + maxRetries + " intentos");
}
}
Logging de Errores
Usa el sistema de logging del SDK para debuggear errores:
RetornaClient client = RetornaClient.create(
RetornaClientOptions.builder()
.environment(Environment.DEVELOP)
.loggingLevel(LoggingLevel.DEBUG) // Activar logging detallado
// ... otras configuraciones
.build()
);
Con LoggingLevel.DEBUG, verás:
- Intentos de autenticación
- Solicitudes HTTP
- Respuestas de la API
- Errores detallados
Errores Comunes y Soluciones
Error: "clientId es requerido"
Causa: No se proporcionó el clientId al crear el cliente.
Solución:
.clientId("tu-client-id") // Asegúrate de proporcionarlo
Error: "Error al obtener balance: 401"
Causa: Credenciales inválidas o token expirado.
Solución: Verifica tus credenciales. El SDK intentará renovar el token automáticamente.
Error: "Error de validación: ..."
Causa: Datos inválidos en la solicitud (ej: formato de documento incorrecto).
Solución: Verifica el formato de los datos según la plataforma de pago.
Error: "Formato de respuesta inesperado"
Causa: La API devolvió un formato inesperado.
Solución: Contacta al soporte o verifica la versión del SDK.
Mejores Prácticas
- Siempre maneja excepciones: No dejes que las excepciones se propaguen sin manejo
- Proporciona contexto: Incluye información útil en los mensajes de error
- Logging apropiado: Usa logging para debuggear, no para producción
- Reintentos inteligentes: Solo reintenta en errores recuperables (5xx)
- Validación temprana: Valida los datos antes de enviarlos al SDK
Ejemplo Completo
public class RobustErrorHandling {
public static void processPayment(RetornaClient client, CreateOrderInput input) {
try {
// Validar input antes de enviar
validateOrderInput(input);
// Crear orden
OrderResponse order = client.order.createPayoutOrder(input);
System.out.println("✅ Orden creada: " + order.getId());
} catch (IllegalArgumentException e) {
// Error de validación
System.err.println("❌ Error de validación: " + e.getMessage());
// Mostrar mensaje al usuario
showUserError("Por favor, verifica los datos ingresados.");
} catch (RuntimeException e) {
// Error de API
if (e.getMessage().contains("401") || e.getMessage().contains("403")) {
System.err.println("❌ Error de autenticación");
// Reautenticar o notificar
} else if (e.getMessage().contains("400")) {
System.err.println("❌ Solicitud inválida: " + e.getMessage());
// Mostrar error específico
} else {
System.err.println("❌ Error de API: " + e.getMessage());
// Reintentar o notificar
}
} catch (Exception e) {
// Error inesperado
System.err.println("❌ Error inesperado: " + e.getMessage());
e.printStackTrace();
// Logging y notificación
}
}
private static void validateOrderInput(CreateOrderInput input) {
if (input.getExternalId() == null || input.getExternalId().isEmpty()) {
throw new IllegalArgumentException("externalId es requerido");
}
// Más validaciones...
}
private static void showUserError(String message) {
// Implementar UI o logging
System.out.println("Error: " + message);
}
}
Siguiente Paso
- Temas Avanzados - Funcionalidades avanzadas del SDK
- Ejemplos - Más ejemplos de uso



