Connexion avec le backend
Intégration de l'interface utilisateur avec les points de terminaison du backend
Dans le module précédent, nous avons construit l'interface utilisateur et une petite machine à états (VerifyUiState). Nous allons maintenant connecter cette interface utilisateur à notre backend.
L'idée principale est que l'application Android n'appellera jamais Vonage directement. Elle n'appellera que votre backend :
-
POST /verificationpour lancer le processus de vérification -
POST /check-codepour valider un code (code SMS pour l'instant) -
POST /nextpour forcer le canal de repli (SMS) immédiatement (afin de ne pas attendre ~20 secondes)
Commençons par la mise en œuvre !
Démarrer la vérification (POST /verification)
Lorsque l'utilisateur tape sur Début de la vérification:
-
L'application envoie le numéro de téléphone à
/verification -
Le backend renvoie :
request_id(toujours)check_url(facultatif, utilisé ultérieurement pour l'authentification silencieuse)
-
Dans cette section, nous allons ignorer l'authentification silencieuse et demander immédiatement le retour aux SMS en appelant
/next -
L'interface utilisateur passe à l'écran SMS (
EnterSms(requestId))
private suspend fun startVerification(phone: String): Pair<String, String?> = withContext(Dispatchers.IO) {
val client = OkHttpClient()
val json = Gson().toJson(mapOf("phone" to phone))
val requestBody = json.toRequestBody("application/json".toMediaType())
val request = Request.Builder()
.url("$BACKEND_URL/verification")
.post(requestBody)
.build()
val response = client.newCall(request).execute()
if (!response.isSuccessful) {
val errorBody = response.body?.string() ?: "Unknown error"
throw IOException("Start verification failed: HTTP ${response.code} - $errorBody")
}
val body = response.body?.string() ?: throw IOException("Empty response body")
val jsonBody = Gson().fromJson(body, JsonObject::class.java)
val requestId = jsonBody.get("request_id")?.asString ?: throw IOException("Missing request_id")
val checkUrl = jsonBody.get("check_url")?.asString // may be null
Pair(requestId, checkUrl)
}
Soumettre le code SMS (POST /check-code)
Lorsque l'utilisateur tape sur Soumettre le code:
- L'application envoie
{ request_id, code }à/check-code - Le backend répond par
{ verified: true/false } - L'interface utilisateur indique un succès ou un "code invalide".
private suspend fun submitCode(requestId: String, code: String): CheckCodeResponse = withContext(Dispatchers.IO) {
val client = OkHttpClient()
val json = Gson().toJson(mapOf("request_id" to requestId, "code" to code))
val requestBody = json.toRequestBody("application/json".toMediaType())
val request = Request.Builder()
.url("$BACKEND_URL/check-code")
.post(requestBody)
.build()
val response = client.newCall(request).execute()
if (!response.isSuccessful) {
val errorBody = response.body?.string() ?: "Unknown error"
throw IOException("Check code failed: HTTP ${response.code} - $errorBody")
}
val body = response.body?.string() ?: throw IOException("Empty response body")
val jsonBody = Gson().fromJson(body, JsonObject::class.java)
CheckCodeResponse(
verified = jsonBody.get("verified")?.asBoolean ?: false,
status = jsonBody.get("status")?.asString
)
}
Forcer le repli rapidement (POST /next)
Appel /next est facultatif du point de vue de la "correction" (Vonage peut se rabattre automatiquement), mais il est très utile pour l'interface utilisateur :
Si nous savons déjà que nous ne compléterons pas l'authentification silencieuse (ou que nous ne l'avons pas encore mise en œuvre), l'appel de l'option /next évite d'attendre le délai d'expiration de l'authentification silencieuse.
private suspend fun requestNextWorkflow(requestId: String): Unit = withContext(Dispatchers.IO) {
val client = OkHttpClient()
val json = Gson().toJson(mapOf("requestId" to requestId))
val requestBody = json.toRequestBody("application/json".toMediaType())
val request = Request.Builder()
.url("$BACKEND_URL/next")
.post(requestBody)
.build()
val response = client.newCall(request).execute()
if (!response.isSuccessful) {
val errorBody = response.body?.string() ?: "Unknown error"
throw IOException("Next workflow failed: HTTP ${response.code} - $errorBody")
}
}
Premiers pas avec l'authentification silencieuse
L'authentification silencieuse est assez difficile à comprendre. Ce tutoriel vous montre comment construire une intégration à partir de zéro avec Nodejs et Kotlin.