Ir al contenido

SDK para Android

El SDK de Android recoge las señales del dispositivo y de su entorno en cada operación sensible y las envía al motor antifraude de Ironchip. Úsalo si tu aplicación móvil es nativa de Android.

Plataforma Versiones soportadas
Android 5.0.0+

Primero, en el fichero settings.gradle, referencia el repositorio remoto donde está la biblioteca:

settings.gradle
dependencyResolutionManagement {
...
repositories {
maven { url 'https://jitpack.io' }
...
}
}

A continuación, en el fichero build.gradle, añade la dependencia del SDK:

build.gradle
dependencies {
...
implementation "com.github.Ironchip-Security:LBFraud-SDK-Android:1.2.26"
...
}

Añade los siguientes permisos al manifest:

AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" tools:ignore="QueryAllPackagesPermission" />

tools:ignore requiere declarar el espacio de nombres xmlns:tools="http://schemas.android.com/tools" en la etiqueta <manifest>.

Para aprovechar todo el potencial del SDK, concede el permiso ACCESS_FINE_LOCATION. Consulta cómo solicitar permisos en Android.

import com.ironchip.ironchiplbfraudandroidsdk.LBFraudSDK
// Sustituye APIKEY por la API key generada en la consola.
val fraud = LBFraudSDK(this, "APIKEY")
// Por defecto el SDK apunta al entorno de producción. Para apuntar a otro:
// val fraud = LBFraudSDK(this, "APIKEY", LBFraudSDK.Environment.TESTING)
val extraData = hashMapOf<String, Any>(
"concept" to "Book august",
"amount" to 30,
"operation" to "booking",
)
// transactionId (obligatorio, único): identificador con el que después pedirás el informe
// userId (obligatorio): identificador del usuario
// extraData (opcional): información adicional para el análisis
fraud.sendTransaction("random_identifier_generated", "john.doe@gmail.com", extraData, {
// Código a ejecutar cuando la transacción ha terminado.
}, { exception ->
// Código a ejecutar si se produce un error durante la transacción.
})

Además de una Activity, el constructor también acepta un Context (desde la versión 1.2.23), por lo que puedes usar el SDK desde un servicio. El constructor lanza LBFraudInitializationException (comprobada) si el contexto es nulo: en Java envuélvelo en try/catch; en Kotlin no es obligatorio.

sendTransaction envía la transacción en segundo plano y recibe dos funciones de retorno: la primera (un Runnable) se ejecuta si el motor acepta la transacción y la segunda (un ExceptionCallback, con el método onExceptionOccurred(Exception e)) si se produce un error. Solo se ejecuta una de las dos, y en un hilo secundario: si desde ellas actualizas la interfaz, hazlo con runOnUiThread.

Si el error es de red o lo devuelve el servidor, la excepción es una TransactionException. Su método getCode() devuelve el código de error de la respuesta del servidor (error_code) o una de estas constantes:

Código Constante Significado
"0" RESPONSE_PARSING_ERROR El servidor devolvió un error que no se pudo interpretar
"1" NO_CONNECTION_ERROR No se puede conectar con el servidor
"2" TIMEOUT_ERROR Se agotó el tiempo de espera
"3" NETWORK_ERROR Otro error de red

getHttpCode() devuelve el código de estado HTTP de la respuesta (0 en los errores de red) y getTraceabilityId(), su identificador de trazabilidad (null si la respuesta no lo trae). Inclúyelo si abres un ticket con soporte. El formato de las respuestas de error está en Respuestas de error.

Si tu app sale a Internet a través de un proxy, configúralo con setProxy antes de enviar transacciones. Recibe un java.net.Proxy y puede lanzar IllegalArgumentException.

import java.net.InetSocketAddress
import java.net.Proxy
fraud.setProxy(Proxy(Proxy.Type.HTTP, InetSocketAddress("proxy.example.com", 8080)))

Ejemplo completo: tras un inicio de sesión correcto, se anonimiza el identificador del usuario con SHA-256 y se envía la transacción.

import com.ironchip.ironchiplbfraudandroidsdk.LBFraudSDK;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
...
// Sustituye APIKEY por la API key generada en la consola.
// El constructor lanza LBFraudInitializationException: gestiónala con try/catch.
LBFraudSDK fraud = new LBFraudSDK(this, "APIKEY");
// Método asíncrono para realizar el inicio de sesión del usuario
private void login(String username, String password) {
performLogin(username, password).thenAccept(loginSuccessful -> {
if (loginSuccessful) {
// Si el inicio de sesión es correcto, llama a sendTransaction con los parámetros necesarios
String transactionID = generateRandomTransactionID(10); // Genera u obtén tu ID de transacción
String userID = "john.doe@gmail.com"; // Identificador de usuario
String anonymizedUserID = anonymizeUserID(userID); // ID de usuario anonimizado
Map<String, Object> extraData = new HashMap<>(); // Información adicional para análisis
extraData.put("amount", 30); // Usa Integer.valueOf(30) si es necesario
extraData.put("operation", "login");
sendTransactionAfterLogin(transactionID, anonymizedUserID, extraData);
} else {
// Gestiona el fallo del inicio de sesión
}
});
}
// Inicio de sesión asíncrono que devuelve un CompletableFuture<Boolean>
private CompletableFuture<Boolean> performLogin(String username, String password) {
return CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
// Sustituye por tu lógica de inicio de sesión real:
// autentica al usuario y devuelve true si es correcto
return true;
} catch (InterruptedException e) {
return false; // En caso de un error, devuelve false
}
});
}
// Envía la transacción tras un inicio de sesión correcto
private void sendTransactionAfterLogin(String transactionID, String anonymizedUserID, Map<String, Object> extraData) {
fraud.sendTransaction(transactionID, anonymizedUserID, extraData, () -> {
// Código a ejecutar cuando la transacción ha terminado.
}, exception -> {
// Código a ejecutar si se produce un error durante la transacción.
});
}
// Recorta, convierte a minúsculas y calcula el hash del userID
public static String anonymizeUserID(String userID) {
String trimmedLowercaseUserID = userID.trim().toLowerCase();
return hashString(trimmedLowercaseUserID);
}
// Calcula el hash con SHA-256
public static String hashString(String input) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hashBytes = digest.digest(input.getBytes(StandardCharsets.UTF_8));
StringBuilder hexString = new StringBuilder();
for (byte b : hashBytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Error while calculating hash", e);
}
}
private String generateRandomTransactionID(int length) {
// Implementa tu método para generar un ID de transacción único.
final String chars = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890";
Random rnd = new Random();
return IntStream.range(0, length)
.mapToObj(i -> String.valueOf(chars.charAt(rnd.nextInt(chars.length()))))
.collect(Collectors.joining());
}

Cambiado

  • Actualizada una biblioteca interna del SDK.

Cambiado

  • Actualizada una biblioteca interna del SDK.

Añadido

  • LBFraudSDK acepta también un Context además de una Activity, para poder usarlo desde componentes que no son una actividad, como los servicios.

Cambiado

  • Actualizada una biblioteca interna del SDK.

Corregido

  • sendTransaction devuelve una TransactionException en los errores de red, en lugar de una IOException. Códigos nuevos: NO_CONNECTION_ERROR, TIMEOUT_ERROR y NETWORK_ERROR.

Cambiado

  • Actualizada una biblioteca interna del SDK.

Cambiado

  • La generación del JSON de la transacción pasa a un hilo secundario.

Cambiado

  • Actualizada una biblioteca interna del SDK.

Cambiado

  • Actualizados los identificadores del modelo de dispositivo.

Añadido

  • Nuevos identificadores en el modelo de dispositivo.

Cambiado

  • Actualizada una biblioteca interna del SDK.

Cambiado

  • Actualizada una biblioteca interna del SDK.

Añadido

  • Detección de comunicación.
  • Tipo de red de la SIM (2G, 3G, 4G, 5G).

Añadido

  • Método de configuración del proxy.

Cambiado

  • Ahora se utilizan conjuntos de cifrado (cipher suites).

Cambiado

  • Corregido el envío de los datos adicionales, que no se enviaban.
  • Esta versión es una actualización sin cambios funcionales. El número de versión se actualiza a 1.2.10 para mantener la secuencia de versiones.

Cambiado

  • Biblioteca Commons actualizada con correcciones adicionales.

Cambiado

  • Biblioteca Commons actualizada para aplicar algunas correcciones de errores.

Añadido

  • Se añade la versión del SDK al modelo de transacción.

Cambiado

  • Gestión previa de errores para permitir crear el servicio de fraude aunque el proveedor de GPS no esté disponible.

Añadido

  • Gestión de errores adicional para evitar que la transacción falle cuando falla alguno de los pasos de construcción de la transacción.

Cambiado

  • Se modifica el modelo de transacción para incluir información sobre la tarjeta SIM.

Cambiado

  • Se modifica el modelo de transacción para incluir el estado de los permisos solicitados.
  • Se modifica el modelo de transacción para incluir si los proveedores de GPS y Wi-Fi están habilitados.

Cambiado

  • Corregida la configuración de ProGuard que hacía que la aplicación del cliente se volviera a empaquetar en la carpeta interna de la biblioteca.

Cambiado

  • Los errores durante el callback de sendTransaction ahora se registran en el log en lugar de redirigirse al callback de excepción.

Cambiado

  • Corregido un problema con la identificación de la huella digital (fingerprint).

Cambiado

  • Corregido un error cuando el dispositivo no está conectado a una red Wi-Fi.
  • Corregidos los saltos de línea en los identificadores cifrados.
  • Mejora en la detección de emulación.

Cambiado

  • Refactorización de nombres de clase.
  • Las etiquetas de los logs se cambian para que coincidan con la refactorización.
  • El constructor de Fraud ya no admite un host de URL, solo permite seleccionar el entorno deseado.

Añadido

  • Versión del kernel en las propiedades del dispositivo.
  • Registros de depuración.

Cambiado

  • Corregido un error por el que el JSON enviaba cadenas en lugar de arrays.
  • Mejora en la identificación del dispositivo, de la instalación y de la huella digital.
  • El GPS y la señal ya no pueden bloquear el proceso.

Cambiado

  • La biblioteca pasa a publicarse en GitHub.

Añadido

  • Compatibilidad con Android 5 y posteriores.

Añadido

  • Fichero de licencia (LICENSE) en el proyecto.

Cambiado

  • Refactorización del nombre del módulo.

Añadido

  • Excepciones personalizadas.

Cambiado

  • Callbacks y excepciones excluidos de la ofuscación para facilitar el uso del cliente.
  • Cambian los nombres y la estructura de los parámetros del modelo.

Cambiado

  • Callbacks y excepciones excluidos de la ofuscación para facilitar el uso del cliente.
  • Cambian los nombres y la estructura de los parámetros del modelo.

Añadido

  • Ofuscación del código.

Cambiado

  • Secciones de código migradas a una biblioteca común.
  • Cambia el comportamiento del servicio de GPS.