Node.js

Networking to Backend

The following Kotlin functions define how the mobile client communicates with the backend server to perform a phone number verification using the Verify API. This process consists of three main steps:

  1. Starting the verification process by submitting the phone number.
  2. Checking for a silent authentication result, which happens automatically in the background.
  3. Submitting the verification code (received silently or via fallback, like SMS) to complete the verification.

Each function runs inside a coroutine and performs network operations on the IO dispatcher to avoid blocking the main thread.

Start Verification

This function initiates the verification process by sending the user's phone number to the backend. The backend then starts the verification via the Vonage Verify API and responds with two values:

  • request_id: A unique identifier for the verification request.
  • check_url: A URL that can be used to check the result of the silent authentication.
suspend fun startVerification(phoneNumber: String): Pair<String, String> = withContext(Dispatchers.IO) {
    val client = OkHttpClient()

    // Prepare request JSON body
    val requestJson = mapOf("phone" to phoneNumber)
    val requestBody = Gson()
        .toJson(requestJson)
        .toRequestBody("application/json".toMediaType())

    // Make POST request to /verification
    val request = Request.Builder()
        .url("$BACKEND_URL/verification")
        .post(requestBody)
        .build()

    val response = client.newCall(request).execute()

    // Ensure request succeeded
    if (!response.isSuccessful) {
        throw IOException("Verification failed with code ${response.code}")
    }

    // Parse response
    val responseBody = response.body?.string()
        ?: throw IOException("Empty response from server")
    val json = Gson().fromJson(responseBody, JsonObject::class.java)

    // Extract check URL and request ID
    val checkUrl = json.get("check_url")?.asString
        ?: throw IOException("Missing check_url in response")
    val requestId = json.get("request_id")?.asString
        ?: throw IOException("Missing request_id in response")

    return@withContext Pair(requestId, checkUrl)
}

Check Silent Authentication

After initiating the verification, this function initializes the silent authentication by sending a GET request to the check_url received earlier. If the silent authentication succeeds, the server responds with a verification code (after some redirects), which can be used to complete the verification process.

suspend fun checkSilentAuth(checkUrl: String): String = withContext(Dispatchers.IO) {
    val client = OkHttpClient()

    // Send GET request to check_url
    val request = Request.Builder()
        .url(checkUrl)
        .get()
        .build()

    val response = client.newCall(request).execute()

    if (!response.isSuccessful) {
        throw IOException("Silent Auth failed with code ${response.code}")
    }

    val responseBody = response.body?.string()
        ?: throw IOException("Empty response from Silent Auth")

    val json = Gson().fromJson(responseBody, JsonObject::class.java)

    return@withContext json.get("code")?.asString
        ?: throw IOException("Missing code in Silent Auth response")
}

Submit Code

This function submits the verification code to the backend to finalize the verification process. The backend verifies the code using the Verify API and responds with a boolean indicating whether the verification was successful.

suspend fun submitCode(requestId: String, code: String): Boolean = withContext(Dispatchers.IO) {
    val client = OkHttpClient()

    val requestJson = mapOf("request_id" to requestId, "code" to code)
    val requestBody = Gson()
        .toJson(requestJson)
        .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) {
        throw IOException("Code verification failed with code ${response.code}")
    }

    val responseBody = response.body?.string()
        ?: throw IOException("Empty response from server")

    val json = Gson().fromJson(responseBody, JsonObject::class.java)

    return@withContext json.get("verified")?.asBoolean ?: false
}

With these functions in place, your Android app can connect to your backend to complete the phone number verification process using Vonage Verify. The next step would typically involve handling success or failure in your UI, showing appropriate messages or redirecting the user accordingly.