Node.js

バックエンドとの接続

UIとバックエンド・エンドポイントの統合

前のモジュールでは、UIと小さなUIステートマシン(VerifyUiState).では、そのUIをバックエンドに接続しよう。

主なアイデアは、AndroidアプリがVonageを直接呼び出すことはないということです。あなたのバックエンドを呼び出すだけです:

  • POST /verification 検証フローを開始する

  • POST /check-code コードを検証する(今のところSMSコード)

  • POST /next フォールバック・チャンネル(SMS)を即座に強制する(20秒待たないため)

まずは実装から始めよう!

検証開始POST /verification)

ユーザーが 検証開始:

  1. アプリは電話番号を /verification

  2. バックエンドが返す:

    • request_id (いつも)
    • check_url (オプション。後でサイレント認証に使用する)
  3. このセクションでは、Silent Authをスキップして、すぐにSMSへのフォールバックを要求する。 /next

  4. UIは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)
}

SMSコードを送信するPOST /check-code)

ユーザーが 投稿コード:

  1. アプリが送信する { request_id, code } への /check-code
  2. バックエンドは次のように応答します。 { verified: true/false }
  3. UIは成功または "無効なコード "を表示する
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
    )
}

フォールバックを素早く強制するPOST /next)

呼び出し /next は "正しさ "の観点からはオプションだが(Vonageは自動的にフォールバックする)、UXの観点からは非常に有用だ:

サイレント認証が完了しない(あるいはまだ実装していない)ことがすでに分かっている場合、次のように呼び出す。 /next Silent Authのタイムアウトを待たずに済む。

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")
    }
}