INFRAESTRUCTURA DE COTIZACIÓN
Conexión segura.
Cotización en tiempo real.
Consola para validar la identidad de integración, las sesiones Firebase y Worker, y el flujo privado de resultados por aseguradora.
SESIÓN DE PRUEBA
Validar conexión M2M
Mostrar depuración Sesiones, validaciones y vigencias
Configuración de demostración lista
- Vigencia Firebase
- Vigencia API
- Token opaco
- Validación Worker
COTIZACIÓN EN VIVO
Encuentra opciones para tu auto
Selecciona un vehículo y sigue cada aseguradora en tiempo real.
Vehículo seleccionado
Estado general
Respuesta JSON
GUÍA DE INTEGRACIÓN
Firebase + Cloudflare en cada plataforma
El backend autenticado del banco entrega un token personalizado de Firebase y un token opaco para el Worker. La credencial M2M nunca se comparte con el cliente.
1. Firebase Auth
2. Bearer Worker
3. Resultado privado
1M2M · Crear sesionesRecibir las credenciales separadas e iniciar Firebase Auth.Ver código
Web JS puroSDK web de Firebase
const response = await fetch(`${bankApiUrl}/insurance/session`, {
method: "POST",
credentials: "include",
});
const session = await response.json();
await signInWithCustomToken(auth, session.firebaseCustomToken);
let apiSessionToken = session.apiSessionToken;iOSFirebaseAuth
let session: BridgeSession = try await bankAPI.createInsuranceSession()
try await Auth.auth().signIn(withCustomToken: session.firebaseCustomToken)
var apiSessionToken = session.apiSessionTokenAndroidFirebase Auth KTX
val session = bankApi.createInsuranceSession()
Firebase.auth.signInWithCustomToken(session.firebaseCustomToken).await()
var apiSessionToken = session.apiSessionTokenFlutterfirebase_auth
final session = await bankApi.createInsuranceSession();
await FirebaseAuth.instance.signInWithCustomToken(session.firebaseCustomToken);
var apiSessionToken = session.apiSessionToken;- Clave de API web de Firebase
- Identificador público del proyecto Firebase. Selecciona el proyecto, pero no autoriza al usuario de integración.
- Correo y contraseña de integración
- Credenciales exclusivas del servidor para el único usuario de integración de Firebase. Nunca deben incluirse en aplicaciones web o móviles.
- Token de ID de integración
- Token de Firebase de corta duración devuelto por el inicio de sesión. La Function verifica que su UID coincida con el UID de integración configurado.
- endUserId
- Identificador estable del usuario de Banco Plata seleccionado por el backend bancario confiable. Se convierte en el UID de Firebase del usuario final.
- firebaseCustomToken
- Token de un solo uso que el cliente intercambia con Firebase Auth para obtener su sesión de usuario final.
- apiSessionToken
- Token bearer opaco e independiente usado solo con las API del Worker. El Worker almacena únicamente su hash SHA-256 en KV.
2Validar WorkerComprobar que el token opaco resuelve una sesión activa.Ver código
Web JS puroAPI Fetch
const response = await fetch(`${workerUrl}/session/probe`, {
headers: { Authorization: `Bearer ${apiSessionToken}` },
});
if (response.status !== 200) throw new Error("Sesión del Worker rechazada");iOSURLSession
var request = URLRequest(url: workerURL.appendingPathComponent("session/probe"))
request.setValue("Bearer \(apiSessionToken)", forHTTPHeaderField: "Authorization")
let (_, response) = try await URLSession.shared.data(for: request)
guard (response as? HTTPURLResponse)?.statusCode == 200 else { throw BridgeError.unauthorized }AndroidHttpURLConnection
val connection = URL("$workerUrl/session/probe").openConnection() as HttpURLConnection
connection.setRequestProperty("Authorization", "Bearer $apiSessionToken")
check(connection.responseCode == 200) { "Sesión del Worker rechazada" }Flutterhttp
final response = await http.get(
Uri.parse('$workerUrl/session/probe'),
headers: {'Authorization': 'Bearer $apiSessionToken'},
);
if (response.statusCode != 200) throw Exception('Sesión del Worker rechazada');- WORKER_URL
- Nombre de host público del Worker desplegado en Cloudflare. No existe hasta que el Worker se despliega y recibe una ruta.
- API_SESSION_TOKEN
- Token opaco sin procesar devuelto por el inicio de sesión. Debe conservarse en memoria y enviarse solo como credencial bearer al Worker.
- /session/probe
- Validación autenticada. Una respuesta 200 demuestra que el Worker encontró y validó la sesión de KV sin exponer la identidad del usuario.
3Reparar sesiónUsar la sesión Firebase vigente para reemplazar un token Worker vencido.Ver código
Web JS puroToken de ID de Firebase
const firebaseIdToken = await auth.currentUser.getIdToken();
// El backend bancario reenvía este token a refreshApiSession.
const response = await fetch(`${bankApiUrl}/insurance/session/refresh`, {
method: "POST",
headers: { Authorization: `Bearer ${firebaseIdToken}` },
});
apiSessionToken = (await response.json()).apiSessionToken;iOSFirebaseAuth + API bancaria
let firebaseIDToken = try await Auth.auth().currentUser!.getIDToken()
let refreshed = try await bankAPI.refreshWorkerSession(firebaseIDToken: firebaseIDToken)
apiSessionToken = refreshed.apiSessionTokenAndroidToken de ID de Firebase + API bancaria
val firebaseIdToken = Firebase.auth.currentUser!!.getIdToken(false).await().token!!
val refreshed = bankApi.refreshWorkerSession(firebaseIdToken)
apiSessionToken = refreshed.apiSessionTokenFlutterToken de ID de Firebase + API bancaria
final firebaseIdToken = await FirebaseAuth.instance.currentUser!.getIdToken();
final refreshed = await bankApi.refreshWorkerSession(firebaseIdToken!);
apiSessionToken = refreshed.apiSessionToken;- END_USER_FIREBASE_ID_TOKEN
- Token de ID actual de Firebase obtenido después de intercambiar firebaseCustomToken. No es el token del usuario de integración.
- /insurance/session/refresh
- Endpoint del backend de Banco Plata que reenvía el token del usuario final a la Function refreshApiSession. El cliente nunca recibe el secreto interno del Worker.
- refreshApiSession
- Function de Firebase que valida la sesión del usuario final y solicita un token opaco de reemplazo para el Worker. Una desconexión temporal no requiere llamarla: Firebase SDK reconecta automáticamente. Después de reiniciar la aplicación, si Firebase restauró su sesión pero el token Worker en memoria se perdió, se usa esta Function. Si no existe auth.currentUser o responde m2m_required, debe repetirse el bootstrap M2M completo.
- m2m_required
- Indica que la identidad de Firebase ya no puede restaurar la sesión del Worker. Banco Plata debe repetir el inicio M2M confiable.
4CotizarEnviar los datos mínimos del vehículo al Worker.Ver código
Web JS puroPOST /quote
const response = await fetch(`${workerUrl}/quote`, {
method: "POST",
headers: {
Authorization: `Bearer ${apiSessionToken}`,
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify(quote),
});
const { globalId } = await response.json();iOSPOST /quote
var request = URLRequest(url: workerURL.appendingPathComponent("quote"))
request.httpMethod = "POST"
request.httpBody = try JSONEncoder().encode(quote)
request.setValue("Bearer \(apiSessionToken)", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue(UUID().uuidString, forHTTPHeaderField: "Idempotency-Key")
let (data, _) = try await URLSession.shared.data(for: request)AndroidPOST /quote
val connection = URL("$workerUrl/quote").openConnection() as HttpURLConnection
connection.requestMethod = "POST"
connection.doOutput = true
connection.setRequestProperty("Authorization", "Bearer $apiSessionToken")
connection.setRequestProperty("Content-Type", "application/json")
connection.setRequestProperty("Idempotency-Key", UUID.randomUUID().toString())
connection.outputStream.use { it.write(quoteJson.toByteArray()) }FlutterPOST /quote
final response = await http.post(
Uri.parse('$workerUrl/quote'),
headers: {
'Authorization': 'Bearer $apiSessionToken',
'Content-Type': 'application/json',
'Idempotency-Key': const Uuid().v4(),
},
body: jsonEncode(quote),
);- Idempotency-Key
- Identificador único de la solicitud. Reutiliza el mismo valor únicamente al reintentar la misma cotización.
- Cuerpo de la cotización
- Datos mínimos del vehículo y conductor aceptados desde el cliente. El Worker agrega los campos controlados por el backend.
- globalId
- Identificador de la operación completa de cotización. Se usa para observar el estado global en RTDB y sus aseguradoras relacionadas.
5Ver detallesRecuperar el JSON privado de una aseguradora usando su resultId.Ver código
Web JS puroGET /quote/{resultId}
const response = await fetch(`${workerUrl}/quote/${encodeURIComponent(resultId)}`, {
headers: { Authorization: `Bearer ${apiSessionToken}` },
});
const insurerDetail = await response.json();iOSGET /quote/{resultId}
let url = workerURL.appendingPathComponent("quote/\(resultId)")
var request = URLRequest(url: url)
request.setValue("Bearer \(apiSessionToken)", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
let detail = try JSONDecoder().decode(InsurerDetail.self, from: data)AndroidGET /quote/{resultId}
val url = "$workerUrl/quote/${URLEncoder.encode(resultId, Charsets.UTF_8)}"
val connection = URL(url).openConnection() as HttpURLConnection
connection.setRequestProperty("Authorization", "Bearer $apiSessionToken")
val insurerDetailJson = connection.inputStream.bufferedReader().readText()FlutterGET /quote/{resultId}
final response = await http.get(
Uri.parse('$workerUrl/quote/${Uri.encodeComponent(resultId)}'),
headers: {'Authorization': 'Bearer $apiSessionToken'},
);
final insurerDetail = jsonDecode(response.body);- RESULT_ID
- ID del registro de aseguradora referenciado por el registro global de RTDB, por ejemplo {globalId}-axa.
- Resultado privado
- JSON completo de la aseguradora almacenado en results/{uid}/{resultId}.json en R2. RTDB contiene únicamente el estado y resultId.
- Propiedad
- El Worker obtiene el UID de la sesión de API autenticada. Los clientes nunca envían el UID ni reciben una URL directa de R2.