@gatekeeperx/cordova-plugin-devicex 1.2.5 → 1.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +107 -428
- package/package.json +1 -1
- package/plugin.xml +4 -3
- package/src/android/com/gatekeeperx/cordova/DevicexPlugin.java +35 -0
- package/src/android/com/gatekeeperx/cordova/GatekeeperXClient.java +110 -0
- package/src/android/hooks/configure-gradle.js +1 -1
- package/src/android/libs/devicex-1.2.6.aar +0 -0
- package/www/devicex.js +8 -0
- package/src/android/libs/devicex-1.2.5.aar +0 -0
package/README.md
CHANGED
|
@@ -1,484 +1,163 @@
|
|
|
1
|
-
# cordova-plugin-devicex
|
|
1
|
+
# @gatekeeperx/cordova-plugin-devicex
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/@gatekeeperx/cordova-plugin-devicex)
|
|
4
4
|
[](https://opensource.org/licenses/Apache-2.0)
|
|
5
5
|
|
|
6
|
-
Plugin
|
|
7
|
-
|
|
8
|
-
## 🚀 Features
|
|
9
|
-
|
|
10
|
-
- ✅ **Detección de rooting/jailbreak** (Magisk, Frida, Xposed, Superuser)
|
|
11
|
-
- ✅ **Identificación de emuladores** (AVD, Genymotion, Bluestacks)
|
|
12
|
-
- ✅ **Risk scoring** basado en +50 señales del dispositivo
|
|
13
|
-
- ✅ **Deep Fingerprinting**:
|
|
14
|
-
- 🔋 Batería & Energía
|
|
15
|
-
- 📷 Cámaras & Codecs
|
|
16
|
-
- 💾 CPU, GPU & Memoria
|
|
17
|
-
- 📡 Sensores & Input Devices
|
|
18
|
-
- 📦 Package Manager & Settings
|
|
19
|
-
- ✅ **Event tracking** con telemetría de seguridad automática
|
|
20
|
-
- ✅ **Configuración manual** flexible desde el código
|
|
21
|
-
- ✅ **TypeScript definitions** incluidas
|
|
22
|
-
- ✅ **Integration Bridge**: Mapeo directo 1:1 con `device-intelligence-android`
|
|
23
|
-
- ✅ **Soporte cordova-android >= 11**
|
|
6
|
+
Plugin oficial de Cordova para la integración del SDK **GatekeeperX Device Intelligence** en aplicaciones Android. Proporciona capacidades avanzadas de fingerprinting, detección de fraude (root, emuladores, hooks) y telemetría de seguridad.
|
|
24
7
|
|
|
25
8
|
---
|
|
26
9
|
|
|
27
|
-
## 📋
|
|
10
|
+
## 📋 Requisitos
|
|
28
11
|
|
|
29
|
-
|
|
30
|
-
- [Instalación](#-instalación)
|
|
31
|
-
- [Uso](#-uso)
|
|
32
|
-
- [Ejemplos básicos](#ejemplos-básicos)
|
|
33
|
-
- [Casos de uso reales](#casos-de-uso-reales)
|
|
34
|
-
- [API Reference](#-api-reference)
|
|
35
|
-
- [Configuración avanzada](#-configuración-avanzada)
|
|
36
|
-
- [Seguridad y mejores prácticas](#-seguridad-y-mejores-prácticas)
|
|
37
|
-
- [Solución de problemas](#-solución-de-problemas)
|
|
38
|
-
- [Desarrollo y contribución](#-desarrollo-y-contribución)
|
|
39
|
-
- [Licencia](#licencia)
|
|
12
|
+
Para integrar este plugin, asegúrate de cumplir con los siguientes requisitos:
|
|
40
13
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
# 1. Instalar plugin desde npm
|
|
47
|
-
ionic cordova plugin add cordova-plugin-devicex
|
|
48
|
-
|
|
49
|
-
# 2. Agregar plataforma Android 11+
|
|
50
|
-
ionic cordova platform add android@11
|
|
51
|
-
|
|
52
|
-
# 3. Construir
|
|
53
|
-
ionic cordova build android
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
**Uso en tu app:**
|
|
57
|
-
|
|
58
|
-
```typescript
|
|
59
|
-
declare const Devicex: any;
|
|
60
|
-
|
|
61
|
-
// El SDK debe ser inicializado manualmente antes de su uso
|
|
62
|
-
await Devicex.configure({
|
|
63
|
-
tenant: 'gatekeeperx',
|
|
64
|
-
apiKey: 'tu-api-key',
|
|
65
|
-
environment: 'SANDBOX'
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
// Enviar eventos con telemetría de seguridad automática
|
|
69
|
-
const result = await Devicex.sendEvent('app_start');
|
|
70
|
-
console.log('Event sent:', result.ok, 'DeviceXId:', result.deviceXId);
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
---
|
|
74
|
-
|
|
75
|
-
## 📦 Requisitos
|
|
76
|
-
|
|
77
|
-
- **Node.js** y npm
|
|
78
|
-
- **Java JDK 11 o 17** (para cordova-android 11+)
|
|
79
|
-
- **Android SDK** instalado y configurado
|
|
80
|
-
- **Ionic CLI** (si usas Ionic)
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
# Configurar Java y Android SDK
|
|
84
|
-
export JAVA_HOME="$(/usr/libexec/java_home -v 17)"
|
|
85
|
-
export ANDROID_SDK_ROOT="$HOME/Library/Android/sdk"
|
|
86
|
-
```
|
|
14
|
+
- **Cordova Android**: Versión `11.0.0` o superior.
|
|
15
|
+
- **Java**: JDK 11 o 17.
|
|
16
|
+
- **Android SDK**: API Level 21+ soportado (API 31+ recomendado).
|
|
17
|
+
- **GatekeeperX Credentials**: Tenant ID y API Key válidos.
|
|
87
18
|
|
|
88
19
|
---
|
|
89
20
|
|
|
90
21
|
## 🔧 Instalación
|
|
91
22
|
|
|
92
|
-
|
|
23
|
+
Instala el plugin utilizando el CLI de Cordova o Ionic. Esto descargará el paquete de npm y configurará automáticamente las dependencias nativas en tu proyecto.
|
|
93
24
|
|
|
94
25
|
```bash
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
### Agregar plataforma Android
|
|
99
|
-
|
|
100
|
-
```bash
|
|
101
|
-
ionic cordova platform add android@11
|
|
102
|
-
# O versión superior (12, 13, etc.)
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
### Construir y ejecutar
|
|
106
|
-
|
|
107
|
-
```bash
|
|
108
|
-
# Build
|
|
109
|
-
ionic cordova build android
|
|
110
|
-
|
|
111
|
-
# Ejecutar en dispositivo
|
|
112
|
-
ionic cordova run android --device
|
|
113
|
-
|
|
114
|
-
# Ejecutar en emulador
|
|
115
|
-
ionic cordova run android --emulator
|
|
116
|
-
|
|
117
|
-
# Ver logs
|
|
118
|
-
adb logcat | grep -i -E "devicex|gatekeeperx"
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
---
|
|
122
|
-
|
|
123
|
-
## 💻 Uso
|
|
124
|
-
|
|
125
|
-
### Declaración TypeScript
|
|
126
|
-
|
|
127
|
-
```typescript
|
|
128
|
-
// Declarar el objeto global Devicex
|
|
129
|
-
declare const Devicex: any;
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
### Ejemplos básicos
|
|
133
|
-
|
|
134
|
-
#### 1. Verificar inicialización
|
|
135
|
-
|
|
136
|
-
```typescript
|
|
137
|
-
const initialized = await Devicex.isInitialized();
|
|
138
|
-
console.log('SDK initialized:', initialized);
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
#### 2. Obtener versión del SDK
|
|
142
|
-
|
|
143
|
-
```typescript
|
|
144
|
-
const version = await Devicex.getVersion();
|
|
145
|
-
console.log('SDK version:', version);
|
|
146
|
-
```
|
|
26
|
+
# Usando Ionic CLI (Recomendado)
|
|
27
|
+
ionic cordova plugin add @gatekeeperx/cordova-plugin-devicex
|
|
147
28
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
```typescript
|
|
151
|
-
const result = await Devicex.sendEvent(
|
|
152
|
-
'view_product',
|
|
153
|
-
{ productId: '12345', category: 'electronics' },
|
|
154
|
-
{ 'X-Trace-Id': 'abc-123' }
|
|
155
|
-
);
|
|
156
|
-
|
|
157
|
-
console.log('Event sent:', result.ok);
|
|
158
|
-
console.log('Device ID:', result.deviceXId);
|
|
29
|
+
# Usando Cordova CLI
|
|
30
|
+
cordova plugin add @gatekeeperx/cordova-plugin-devicex
|
|
159
31
|
```
|
|
160
32
|
|
|
161
|
-
###
|
|
162
|
-
|
|
163
|
-
### Casos de uso reales
|
|
33
|
+
### Configuración de Plataforma
|
|
164
34
|
|
|
165
|
-
|
|
35
|
+
Asegúrate de tener la plataforma Android configurada correctamente:
|
|
166
36
|
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
// Proceder con login
|
|
170
|
-
const loginResult = await authenticate(username, password);
|
|
171
|
-
|
|
172
|
-
// Enviar evento de login (el SDK adjunta fingerprint y risk signals internamente)
|
|
173
|
-
await Devicex.sendEvent('login', {
|
|
174
|
-
method: 'password',
|
|
175
|
-
success: loginResult.success
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
#### Monitoreo de pantallas
|
|
181
|
-
|
|
182
|
-
```typescript
|
|
183
|
-
// En tu componente/página (Ionic)
|
|
184
|
-
async ionViewDidEnter() {
|
|
185
|
-
await Devicex.sendEvent('view_screen', {
|
|
186
|
-
screen: 'home',
|
|
187
|
-
timestamp: Date.now()
|
|
188
|
-
});
|
|
189
|
-
}
|
|
37
|
+
```bash
|
|
38
|
+
cordova platform add android@11
|
|
190
39
|
```
|
|
191
40
|
|
|
192
41
|
---
|
|
193
42
|
|
|
194
43
|
## 📚 API Reference
|
|
195
44
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
| Método JS | Método Nativo (Kotlin) | Descripción |
|
|
199
|
-
|-----------|------------------------|-------------|
|
|
200
|
-
| `configure()` | `Devicex.configure()` | Inicializa el SDK con tu API Key y Tenant. |
|
|
201
|
-
| `sendEvent()` | `Devicex.sendEvent()` | Envía eventos de negocio asegurados con fingerprinting. |
|
|
202
|
-
| `getVersion()` | `Devicex.getVersion()` | Retorna la versión del SDK nativo subyacente. |
|
|
203
|
-
| `isInitialized()` | `Devicex.isInitialized()` | Verifica si la instancia `agent` está lista. |
|
|
45
|
+
El plugin expone el objeto global `Devicex` una vez que el evento `deviceready` se ha disparado.
|
|
204
46
|
|
|
205
|
-
### `Devicex.configure(
|
|
47
|
+
### 1. `Devicex.configure(options)`
|
|
48
|
+
Inicializa el SDK con las credenciales de tu proyecto. **Debe llamarse antes que cualquier otro método.**
|
|
206
49
|
|
|
50
|
+
**Parámetros:**
|
|
51
|
+
- `options` (`ConfigureOptions`):
|
|
52
|
+
- `tenant` (string, requerido): ID de tu tenant.
|
|
53
|
+
- `apiKey` (string, requerido): Tu clave de API.
|
|
54
|
+
- `environment` (string, opcional): `'SANDBOX'`, o `'PRODUCTION'`.
|
|
55
|
+
- `organizationId` (string, opcional): Identificador de organización.
|
|
207
56
|
|
|
208
|
-
|
|
209
|
-
Configura el SDK. Este paso es obligatorio antes de realizar cualquier otra llamada.
|
|
210
|
-
|
|
57
|
+
**Ejemplo:**
|
|
211
58
|
```typescript
|
|
212
59
|
await Devicex.configure({
|
|
213
|
-
tenant: '
|
|
214
|
-
apiKey: '
|
|
215
|
-
environment: 'PRODUCTION'
|
|
216
|
-
organizationId: 'your-org-id',
|
|
217
|
-
headers: { 'X-Custom-Header': 'value' } // opcional
|
|
60
|
+
tenant: 'mi-tenant',
|
|
61
|
+
apiKey: 'tu-api-key',
|
|
62
|
+
environment: 'PRODUCTION'
|
|
218
63
|
});
|
|
219
64
|
```
|
|
220
65
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
- `apiKey` (string, requerido): API Key de autenticación
|
|
224
|
-
- `environment` (string, opcional): Entorno del SDK
|
|
225
|
-
- `organizationId` (string, opcional): ID de organización
|
|
226
|
-
- `headers` (object, opcional): Headers HTTP personalizados
|
|
66
|
+
### 2. `Devicex.sendEvent(name, properties?, headers?)`
|
|
67
|
+
Envía un evento de telemetría con señales de seguridad adjuntas automáticamente.
|
|
227
68
|
|
|
228
|
-
**
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
### `Devicex.isInitialized()`
|
|
233
|
-
|
|
234
|
-
Verifica si el SDK está inicializado y listo para usarse.
|
|
69
|
+
**Parámetros:**
|
|
70
|
+
- `name` (string, requerido): Nombre del evento (ej: `'login'`, `'checkout'`).
|
|
71
|
+
- `properties` (object, opcional): Metadatos adicionales del evento.
|
|
72
|
+
- `headers` (object, opcional): Cabeceras HTTP personalizadas.
|
|
235
73
|
|
|
74
|
+
**Ejemplo:**
|
|
236
75
|
```typescript
|
|
237
|
-
const
|
|
76
|
+
const result = await Devicex.sendEvent('login', { user: 'id_123' });
|
|
77
|
+
if (result.ok) {
|
|
78
|
+
console.log('DeviceX ID:', result.deviceXId);
|
|
79
|
+
}
|
|
238
80
|
```
|
|
239
81
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
---
|
|
82
|
+
### 3. `Devicex.isInitialized()`
|
|
83
|
+
Verifica si el SDK ha sido configurado correctamente.
|
|
243
84
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
Obtiene la versión actual del SDK nativo.
|
|
85
|
+
**Retorna:** `Promise<boolean>`
|
|
247
86
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
// Ejemplo: "1.1.6"
|
|
251
|
-
```
|
|
87
|
+
### 4. `Devicex.getVersion()`
|
|
88
|
+
Obtiene la versión del SDK nativo subyacente.
|
|
252
89
|
|
|
253
90
|
**Retorna:** `Promise<string>`
|
|
254
91
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
### `Devicex.sendEvent(eventType, metadata?, headers?)`
|
|
260
|
-
|
|
261
|
-
Envía un evento personalizado al backend de GatekeeperX.
|
|
262
|
-
|
|
263
|
-
```typescript
|
|
264
|
-
const result = await Devicex.sendEvent(
|
|
265
|
-
'login',
|
|
266
|
-
{ method: 'oauth', provider: 'google' },
|
|
267
|
-
{ 'X-Request-ID': 'abc-123' }
|
|
268
|
-
);
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
**Parámetros:**
|
|
272
|
-
- `eventType` (string, requerido): Tipo de evento (ej: `'login'`, `'checkout'`, `'view_screen'`)
|
|
273
|
-
- `metadata` (object, opcional): Datos adicionales del evento
|
|
274
|
-
- `headers` (object, opcional): Headers HTTP personalizados para esta request
|
|
275
|
-
|
|
276
|
-
**Retorna:** `Promise<EventResult>`
|
|
277
|
-
|
|
278
|
-
```typescript
|
|
279
|
-
interface EventResult {
|
|
280
|
-
ok: boolean; // true si el evento se envió exitosamente
|
|
281
|
-
code?: string; // Código de respuesta del backend
|
|
282
|
-
deviceXId?: string; // ID del dispositivo
|
|
283
|
-
message?: string; // Mensaje de éxito
|
|
284
|
-
errorCode?: string; // Código de error (si ok=false)
|
|
285
|
-
errorMessage?: string; // Mensaje de error (si ok=false)
|
|
286
|
-
httpCode?: number; // Código HTTP de la respuesta
|
|
287
|
-
}
|
|
288
|
-
```
|
|
92
|
+
### 5. `Devicex.evaluateRisk(options)` (Beta)
|
|
93
|
+
Realiza una evaluación de riesgo específica enviando un payload al motor de decisión.
|
|
289
94
|
|
|
290
95
|
---
|
|
291
96
|
|
|
292
|
-
##
|
|
293
|
-
|
|
294
|
-
Es obligatorio configurar el SDK al inicio de la aplicación:
|
|
97
|
+
## 🚀 Uso Rápido (Ionic/Angular)
|
|
295
98
|
|
|
296
99
|
```typescript
|
|
297
|
-
// En
|
|
298
|
-
async
|
|
100
|
+
// En app.component.ts
|
|
101
|
+
async initializeApp() {
|
|
102
|
+
await this.platform.ready();
|
|
103
|
+
|
|
299
104
|
if (this.platform.is('cordova')) {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
105
|
+
declare const Devicex: any;
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
await Devicex.configure({
|
|
109
|
+
tenant: 'gatekeeperx', // tu tenant
|
|
110
|
+
apiKey: 'YOUR_API_KEY', // tu api key
|
|
111
|
+
environment: 'PRODUCTION' // PRODUCTION o SANDBOX
|
|
112
|
+
});
|
|
113
|
+
console.log('DeviceX Ready');
|
|
114
|
+
} catch (err) {
|
|
115
|
+
console.error('DeviceX Init Error', err);
|
|
116
|
+
}
|
|
306
117
|
}
|
|
307
118
|
}
|
|
308
|
-
```
|
|
309
119
|
|
|
310
|
-
### Guardias de plataforma
|
|
311
|
-
|
|
312
|
-
Siempre verifica que estás en Cordova antes de usar el plugin:
|
|
313
|
-
|
|
314
|
-
```typescript
|
|
315
|
-
import { Platform } from '@ionic/angular';
|
|
316
120
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
121
|
+
async login() {
|
|
122
|
+
//,,, logica previo a enviar el login
|
|
123
|
+
|
|
124
|
+
loading.present();
|
|
125
|
+
try {
|
|
126
|
+
// Enviar evento de login para obtener deviceXId
|
|
127
|
+
const result = await this.deviceX.sendEvent('login', {
|
|
128
|
+
username: this.username,
|
|
129
|
+
method: 'password',
|
|
130
|
+
timestamp: new Date().toISOString(),
|
|
131
|
+
screen: 'login'
|
|
132
|
+
});
|
|
133
|
+
console.log('Evento enviado, deviceXId:', result.deviceXId);
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
/** EVALUACION DE RIESGO
|
|
137
|
+
* Evaluar riesgo con GatekeeperX - debe hacerse back to back, no en el cliente.
|
|
138
|
+
* debe ser dentro del proceso del login en el backend
|
|
139
|
+
* si la decision es allow, se puede continuar con el login
|
|
140
|
+
* si la decision es deny, se debe denegar el acceso
|
|
141
|
+
* si la decision es unknown, se debe denegar el acceso
|
|
142
|
+
*/
|
|
143
|
+
|
|
144
|
+
//invocar proceso de login en el backend
|
|
145
|
+
const response = await this.http.post(BACKEND_URL, {
|
|
146
|
+
username: this.username,
|
|
147
|
+
password: this.password,
|
|
148
|
+
deviceXId: result.deviceXId
|
|
149
|
+
});
|
|
150
|
+
console.log('Login response:', JSON.stringify(response, null, 2));
|
|
151
|
+
|
|
152
|
+
loading.dismiss();
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
console.log('Login event result:', JSON.stringify(result, null, 2));
|
|
156
|
+
|
|
157
|
+
} catch (error) {
|
|
158
|
+
loading.dismiss();
|
|
159
|
+
console.error('Login event error:', error);
|
|
160
|
+
this.showAlert('Error', 'No se pudo enviar el evento de login', 'error');
|
|
161
|
+
}
|
|
323
162
|
}
|
|
324
163
|
```
|
|
325
|
-
|
|
326
|
-
---
|
|
327
|
-
|
|
328
|
-
## 🔒 Seguridad y mejores prácticas
|
|
329
|
-
|
|
330
|
-
### ✅ DO
|
|
331
|
-
|
|
332
|
-
- **Configura el SDK al inicio** mediante el método `configure`
|
|
333
|
-
- **Protege API keys** en CI/CD con secret managers
|
|
334
|
-
- **Usa `DEVELOPMENT`** para desarrollo/pruebas
|
|
335
|
-
- **Usa `PRODUCTION`** solo en builds release
|
|
336
|
-
- **Verifica `platform.is('cordova')`** antes de usar el plugin
|
|
337
|
-
- **Implementa rate limiting** en eventos personalizados
|
|
338
|
-
|
|
339
|
-
### ❌ DON'T
|
|
340
|
-
|
|
341
|
-
- ❌ **No hardcodees** API keys en código fuente
|
|
342
|
-
- ❌ **No commitees** credenciales en Git
|
|
343
|
-
- ❌ **No envíes** PII (datos personales) en metadata de eventos
|
|
344
|
-
- ❌ **No uses** el mismo API key para dev y prod
|
|
345
|
-
|
|
346
|
-
### Ejemplo de integración segura
|
|
347
|
-
|
|
348
|
-
### Ejemplo de integración segura
|
|
349
|
-
|
|
350
|
-
```typescript
|
|
351
|
-
async ionViewDidLoad() {
|
|
352
|
-
if (!this.platform.is('cordova')) return;
|
|
353
|
-
|
|
354
|
-
// El SDK adjuntará automáticamente las señales de seguridad
|
|
355
|
-
const result = await (window as any).Devicex.sendEvent('page_view', {
|
|
356
|
-
page: 'home'
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
console.log('Security telemetry sent:', result.ok);
|
|
360
|
-
}
|
|
361
|
-
```
|
|
362
|
-
|
|
363
|
-
---
|
|
364
|
-
|
|
365
|
-
## 🛠 Solución de problemas
|
|
366
|
-
|
|
367
|
-
### Error: "class not found" o referencias no resueltas
|
|
368
|
-
|
|
369
|
-
**Causa:** AAR no incluidos o Gradle no configurado correctamente.
|
|
370
|
-
|
|
371
|
-
**Solución:**
|
|
372
|
-
```bash
|
|
373
|
-
# Verifica que existan los AAR
|
|
374
|
-
ls -lh platforms/android/app/libs/devicex*.aar
|
|
375
|
-
|
|
376
|
-
# Re-agregar plugin
|
|
377
|
-
ionic cordova plugin rm cordova-plugin-devicex
|
|
378
|
-
ionic cordova plugin add cordova-plugin-devicex
|
|
379
|
-
|
|
380
|
-
# Limpiar y rebuild
|
|
381
|
-
ionic cordova platform rm android
|
|
382
|
-
ionic cordova platform add android@11
|
|
383
|
-
ionic cordova build android
|
|
384
|
-
```
|
|
385
|
-
|
|
386
|
-
---
|
|
387
|
-
|
|
388
|
-
### Error: Conflictos de dependencias Kotlin
|
|
389
|
-
|
|
390
|
-
**Causa:** Versiones incompatibles de Kotlin en tu proyecto.
|
|
391
|
-
|
|
392
|
-
**Solución:**
|
|
393
|
-
|
|
394
|
-
Este plugin usa:
|
|
395
|
-
- `kotlin-stdlib:1.9.25`
|
|
396
|
-
- `kotlinx-coroutines-android:1.7.3`
|
|
397
|
-
|
|
398
|
-
Asegúrate de no forzar versiones diferentes en tu `build.gradle`.
|
|
399
|
-
|
|
400
|
-
---
|
|
401
|
-
|
|
402
|
-
### Warning: "Mutating configuration after resolution"
|
|
403
|
-
|
|
404
|
-
**Causa:** Warning de Gradle 8.x relacionado con el hook de configuración.
|
|
405
|
-
|
|
406
|
-
**Solución:** Este es un aviso no bloqueante. La build funcionará correctamente. Se resolverá en futuras versiones del plugin.
|
|
407
|
-
|
|
408
|
-
---
|
|
409
|
-
|
|
410
|
-
### Plugin no disponible en runtime
|
|
411
|
-
|
|
412
|
-
**Causa:** No verificaste que Cordova esté cargado.
|
|
413
|
-
|
|
414
|
-
**Solución:**
|
|
415
|
-
```typescript
|
|
416
|
-
// Espera a que Cordova esté listo
|
|
417
|
-
this.platform.ready().then(() => {
|
|
418
|
-
if ((window as any).Devicex) {
|
|
419
|
-
// Usa el plugin aquí
|
|
420
|
-
}
|
|
421
|
-
});
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
---
|
|
425
|
-
|
|
426
|
-
## 🏗 Desarrollo y contribución
|
|
427
|
-
|
|
428
|
-
### Qué incluye este plugin
|
|
429
|
-
|
|
430
|
-
- `src/android/libs/devicex-bridge.aar`: Bridge Kotlin con API Cordova
|
|
431
|
-
- `src/android/libs/devicex-1.1.3.aar`: SDK Device Intelligence empaquetado
|
|
432
|
-
- `www/devicex.js`: Interfaz JavaScript
|
|
433
|
-
- `types/index.d.ts`: Definiciones TypeScript
|
|
434
|
-
- Dependencias: `kotlin-stdlib:1.9.25`, `kotlinx-coroutines-android:1.7.3`
|
|
435
|
-
|
|
436
|
-
### Reconstruir AARs (solo mantenedores)
|
|
437
|
-
|
|
438
|
-
**Compilar SDK:**
|
|
439
|
-
```bash
|
|
440
|
-
cd device-intelligence-android
|
|
441
|
-
export JAVA_HOME="$(/usr/libexec/java_home -v 11)"
|
|
442
|
-
./gradlew :devicex:clean :devicex:assembleProdEnvRelease
|
|
443
|
-
./gradlew :devicex:publishAgentProductionReleasePublicationToMavenLocal
|
|
444
|
-
```
|
|
445
|
-
|
|
446
|
-
**Compilar bridge:**
|
|
447
|
-
```bash
|
|
448
|
-
cd devicex-bridge-android
|
|
449
|
-
export JAVA_HOME="$(/usr/libexec/java_home -v 11)"
|
|
450
|
-
./gradlew :bridge:clean :bridge:assembleRelease
|
|
451
|
-
```
|
|
452
|
-
|
|
453
|
-
**Copiar AARs al plugin:**
|
|
454
|
-
```bash
|
|
455
|
-
cp devicex-bridge-android/bridge/build/outputs/aar/devicex-bridge.aar \
|
|
456
|
-
cordova-plugin-devicex/src/android/libs/
|
|
457
|
-
|
|
458
|
-
cp ~/.m2/repository/com/gatekeeperx/devicex/1.1.6/devicex-1.1.3.aar \
|
|
459
|
-
cordova-plugin-devicex/src/android/libs/
|
|
460
|
-
```
|
|
461
|
-
|
|
462
|
-
### Publicar a npm
|
|
463
|
-
|
|
464
|
-
```bash
|
|
465
|
-
# Actualizar versión
|
|
466
|
-
npm version patch # o minor/major
|
|
467
|
-
|
|
468
|
-
# Publicar
|
|
469
|
-
npm publish --access public
|
|
470
|
-
```
|
|
471
|
-
|
|
472
|
-
---
|
|
473
|
-
|
|
474
|
-
## Licencia
|
|
475
|
-
|
|
476
|
-
Apache-2.0
|
|
477
|
-
|
|
478
|
-
---
|
|
479
|
-
|
|
480
|
-
## Soporte
|
|
481
|
-
|
|
482
|
-
- **Documentación:** [https://docs.gatekeeperx.com](https://docs.gatekeeperx.com)
|
|
483
|
-
- **Issues:** [GitHub Issues](https://github.com/gatekeeperx/cordova-plugin-devicex/issues)
|
|
484
|
-
- **npm:** [cordova-plugin-devicex](https://www.npmjs.com/package/cordova-plugin-devicex)
|
package/package.json
CHANGED
package/plugin.xml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<plugin id="@gatekeeperx/cordova-plugin-devicex"
|
|
3
3
|
xmlns="http://apache.org/cordova/ns/plugins/1.0"
|
|
4
|
-
xmlns:android="http://schemas.android.com/apk/res/android" version="1.2.
|
|
4
|
+
xmlns:android="http://schemas.android.com/apk/res/android" version="1.2.7">
|
|
5
5
|
<name>Devicex</name>
|
|
6
6
|
<description>GatekeeperX Device Intelligence Cordova plugin (Android)</description>
|
|
7
7
|
<license>Apache-2.0</license>
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
<framework src="io.ktor:ktor-serialization-kotlinx-json:2.3.7" />
|
|
32
32
|
<!-- AARs locales -->
|
|
33
33
|
<lib-file src="src/android/libs/devicex-bridge.aar" arch="device" />
|
|
34
|
-
<lib-file src="src/android/libs/devicex-1.2.
|
|
34
|
+
<lib-file src="src/android/libs/devicex-1.2.6.aar" arch="device" />
|
|
35
35
|
|
|
36
36
|
<!-- Hook para configurar Gradle -->
|
|
37
37
|
<hook type="after_plugin_install" src="src/android/hooks/configure-gradle.js" />
|
|
@@ -44,7 +44,8 @@
|
|
|
44
44
|
</feature>
|
|
45
45
|
</config-file>
|
|
46
46
|
|
|
47
|
-
<!-- Incluir
|
|
47
|
+
<!-- Incluir las clases Java del plugin -->
|
|
48
48
|
<source-file src="src/android/com/gatekeeperx/cordova/DevicexPlugin.java" target-dir="src/com/gatekeeperx/cordova" />
|
|
49
|
+
<source-file src="src/android/com/gatekeeperx/cordova/GatekeeperXClient.java" target-dir="src/com/gatekeeperx/cordova" />
|
|
49
50
|
</platform>
|
|
50
51
|
</plugin>
|
|
@@ -85,6 +85,9 @@ public class DevicexPlugin extends CordovaPlugin {
|
|
|
85
85
|
callbackContext.error(e.getMessage());
|
|
86
86
|
}
|
|
87
87
|
return true;
|
|
88
|
+
// case "evaluateRisk":
|
|
89
|
+
// evaluateRisk(args, callbackContext);
|
|
90
|
+
// return true;
|
|
88
91
|
default:
|
|
89
92
|
return false;
|
|
90
93
|
}
|
|
@@ -201,4 +204,36 @@ public class DevicexPlugin extends CordovaPlugin {
|
|
|
201
204
|
}
|
|
202
205
|
return list;
|
|
203
206
|
}
|
|
207
|
+
|
|
208
|
+
private void evaluateRisk(JSONArray args, final CallbackContext cb) {
|
|
209
|
+
try {
|
|
210
|
+
JSONObject obj = args.optJSONObject(0);
|
|
211
|
+
if (obj == null)
|
|
212
|
+
obj = new JSONObject();
|
|
213
|
+
|
|
214
|
+
String apiUrl = obj.optString("apiUrl", "");
|
|
215
|
+
String orgId = obj.optString("organizationId", "");
|
|
216
|
+
String apiKey = obj.optString("apiKey", "");
|
|
217
|
+
JSONObject payload = obj.optJSONObject("payload");
|
|
218
|
+
|
|
219
|
+
if (apiUrl.isEmpty() || orgId.isEmpty() || payload == null) {
|
|
220
|
+
cb.error("apiUrl, organizationId and payload are required");
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
GatekeeperXClient.evaluateRisk(apiUrl, orgId, apiKey, payload, new GatekeeperXClient.Callback() {
|
|
225
|
+
@Override
|
|
226
|
+
public void onSuccess(JSONObject response) {
|
|
227
|
+
cb.success(response);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
@Override
|
|
231
|
+
public void onError(String error) {
|
|
232
|
+
cb.error(error);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
} catch (Exception e) {
|
|
236
|
+
cb.error(e.getMessage());
|
|
237
|
+
}
|
|
238
|
+
}
|
|
204
239
|
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
package com.gatekeeperx.cordova;
|
|
2
|
+
|
|
3
|
+
import android.os.AsyncTask;
|
|
4
|
+
import android.util.Log;
|
|
5
|
+
|
|
6
|
+
import org.json.JSONObject;
|
|
7
|
+
|
|
8
|
+
import java.io.BufferedReader;
|
|
9
|
+
import java.io.InputStreamReader;
|
|
10
|
+
import java.io.OutputStream;
|
|
11
|
+
import java.net.HttpURLConnection;
|
|
12
|
+
import java.net.URL;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Cliente HTTP para llamadas al API de GatekeeperX.
|
|
16
|
+
* Ejecuta requests en background para evitar bloquear el UI thread.
|
|
17
|
+
*/
|
|
18
|
+
public class GatekeeperXClient {
|
|
19
|
+
|
|
20
|
+
private static final String TAG = "GatekeeperXClient";
|
|
21
|
+
private static final int CONNECT_TIMEOUT = 30000;
|
|
22
|
+
private static final int READ_TIMEOUT = 30000;
|
|
23
|
+
|
|
24
|
+
public interface Callback {
|
|
25
|
+
void onSuccess(JSONObject response);
|
|
26
|
+
|
|
27
|
+
void onError(String error);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Evalúa el riesgo de un evento enviando datos al API de GatekeeperX.
|
|
32
|
+
*
|
|
33
|
+
* @param apiUrl URL del endpoint (ej:
|
|
34
|
+
* https://api.gatekeeperx.com/gatekeeperx/events/v1)
|
|
35
|
+
* @param organizationId ID de la organización
|
|
36
|
+
* @param apiKey API Key para autenticación (opcional)
|
|
37
|
+
* @param payload JSON con los datos del evento
|
|
38
|
+
* @param callback Callback para manejar respuesta/error
|
|
39
|
+
*/
|
|
40
|
+
private static void evaluateRisk(
|
|
41
|
+
final String apiUrl,
|
|
42
|
+
final String organizationId,
|
|
43
|
+
final String apiKey,
|
|
44
|
+
final JSONObject payload,
|
|
45
|
+
final Callback callback) {
|
|
46
|
+
|
|
47
|
+
new AsyncTask<Void, Void, Object>() {
|
|
48
|
+
@Override
|
|
49
|
+
protected Object doInBackground(Void... voids) {
|
|
50
|
+
HttpURLConnection conn = null;
|
|
51
|
+
try {
|
|
52
|
+
URL url = new URL(apiUrl);
|
|
53
|
+
conn = (HttpURLConnection) url.openConnection();
|
|
54
|
+
conn.setRequestMethod("POST");
|
|
55
|
+
conn.setRequestProperty("Content-Type", "application/json");
|
|
56
|
+
conn.setRequestProperty("X-Organization-Id", organizationId);
|
|
57
|
+
if (apiKey != null && !apiKey.isEmpty()) {
|
|
58
|
+
conn.setRequestProperty("X-Api-Key", apiKey);
|
|
59
|
+
}
|
|
60
|
+
conn.setDoOutput(true);
|
|
61
|
+
conn.setConnectTimeout(CONNECT_TIMEOUT);
|
|
62
|
+
conn.setReadTimeout(READ_TIMEOUT);
|
|
63
|
+
|
|
64
|
+
OutputStream os = conn.getOutputStream();
|
|
65
|
+
os.write(payload.toString().getBytes("UTF-8"));
|
|
66
|
+
os.close();
|
|
67
|
+
|
|
68
|
+
int responseCode = conn.getResponseCode();
|
|
69
|
+
BufferedReader br;
|
|
70
|
+
if (responseCode >= 200 && responseCode < 300) {
|
|
71
|
+
br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
|
|
72
|
+
} else {
|
|
73
|
+
br = new BufferedReader(new InputStreamReader(conn.getErrorStream(), "UTF-8"));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
StringBuilder response = new StringBuilder();
|
|
77
|
+
String line;
|
|
78
|
+
while ((line = br.readLine()) != null) {
|
|
79
|
+
response.append(line);
|
|
80
|
+
}
|
|
81
|
+
br.close();
|
|
82
|
+
|
|
83
|
+
Log.d(TAG, "Response code: " + responseCode);
|
|
84
|
+
Log.d(TAG, "Response body: " + response.toString());
|
|
85
|
+
|
|
86
|
+
if (responseCode >= 200 && responseCode < 300) {
|
|
87
|
+
return new JSONObject(response.toString());
|
|
88
|
+
} else {
|
|
89
|
+
return "HTTP " + responseCode + ": " + response.toString();
|
|
90
|
+
}
|
|
91
|
+
} catch (Exception e) {
|
|
92
|
+
Log.e(TAG, "evaluateRisk error: " + e.getMessage(), e);
|
|
93
|
+
return e.getMessage();
|
|
94
|
+
} finally {
|
|
95
|
+
if (conn != null)
|
|
96
|
+
conn.disconnect();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@Override
|
|
101
|
+
protected void onPostExecute(Object result) {
|
|
102
|
+
if (result instanceof JSONObject) {
|
|
103
|
+
callback.onSuccess((JSONObject) result);
|
|
104
|
+
} else {
|
|
105
|
+
callback.onError((String) result);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}.execute();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -43,7 +43,7 @@ repositories {
|
|
|
43
43
|
// Agregar dependencias de AARs después de fileTree si no existen
|
|
44
44
|
if (buildGradle.indexOf('devicex-bridge') === -1) {
|
|
45
45
|
const depsBlock = ` implementation files('libs/devicex-bridge.aar')
|
|
46
|
-
implementation files('libs/devicex-1.2.
|
|
46
|
+
implementation files('libs/devicex-1.2.6.aar')
|
|
47
47
|
|
|
48
48
|
// Dependencias del SDK Devicex
|
|
49
49
|
implementation 'io.ktor:ktor-client-core:2.3.7'
|
|
Binary file
|
package/www/devicex.js
CHANGED
|
@@ -26,3 +26,11 @@ exports.isInitialized = function () {
|
|
|
26
26
|
exports.getVersion = function () {
|
|
27
27
|
return call('getVersion', []).then(function (res) { return (res && res.value) || ''; });
|
|
28
28
|
};
|
|
29
|
+
|
|
30
|
+
// exports.evaluateRisk = function (options) {
|
|
31
|
+
// if (!options || !options.apiUrl || !options.organizationId || !options.payload) {
|
|
32
|
+
// return Promise.reject('apiUrl, organizationId and payload are required');
|
|
33
|
+
// }
|
|
34
|
+
// // apiKey es opcional
|
|
35
|
+
// return call('evaluateRisk', [options]);
|
|
36
|
+
// };
|
|
Binary file
|