Android에서 Firebase 전화번호 인증 오류 처리

Firebase PNV 라이브러리 호출이 실패하면 라이브러리는 FirebasePhoneNumberVerificationException를 보고합니다. 이 페이지에는 예외가 전달할 수 있는 모든 오류 코드, 각 오류 코드가 발생하는 시점, 앱에서 취해야 하는 조치가 나열되어 있습니다.

이 페이지에서는 Android에서 Firebase Phone Number Verification 시작하기에 설명된 대로 Firebase PNV를 통합했다고 가정합니다.

오류 보고 방식

  • 비동기 메서드 (getVerificationSupportInfo(), getVerifiedPhoneNumber(), 커스텀 흐름 메서드)는 Task를 반환합니다. 실패하면 Task가 FirebasePhoneNumberVerificationException와 함께 실패하며, 이는 addOnFailureListener에서 수신됩니다.

  • enableTestSession()는 동기식입니다. FirebasePhoneNumberVerificationException를 직접 발생시킵니다.

예외의 errorCode를 읽고 무엇이 잘못되었는지 확인합니다. Firebase PNV 코드는 FirebasePnvStatusCodes 클래스의 상수입니다. Google Play 서비스에서 오류가 발생하면 errorCode는 NETWORK_ERROR와 같은 CommonStatusCodes 값이 될 수도 있습니다.

지원되지 않는 기기 또는 SIM은 오류가 아닙니다. getVerificationSupportInfo()가 성공하고 해당 SIM의 isSupported()를 false로 보고하며 getReason()가 이유를 알려줍니다. 지원되지 않는 기기 및 SIM을 참고하세요.

오류 코드

테스트 세션 설정

이러한 오류는 enableTestSession()에 의해 동기식으로 발생합니다.

오류 코드 원인 권장 조치
TEST_SESSION_ALREADY_ENABLED
(55508)
enableTestSession()가 동일한 앱 프로세스에서 두 번 이상 호출되었습니다. FirebasePhoneNumberVerification.getInstance()는 매번 동일한 인스턴스를 반환하므로 이를 호출하는 Activity가 다시 생성될 때도 이 작업이 실행됩니다. 프로세스당 한 번(예: Application.onCreate()에서) enableTestSession()를 호출합니다. 테스트 모드에서 라이브러리 초기화를 참고하세요.
INVALID_TEST_NUMBER_ID
(55507)
enableTestSession()에 전달된 테스트 토큰이 비어 있습니다. 빌드가 Firebase Console에서 생성한 토큰을 전달하는지 확인하고 토큰이 비어 있지 않은 경우에만 enableTestSession()를 호출합니다.

인증

이러한 오류는 getVerifiedPhoneNumber()에서 반환한 Task를 실패하게 합니다.

오류 코드 원인 권장 조치
CREDENTIAL_MANAGER_ERROR
(55506)
Android 인증 관리자가 전화번호를 반환하지 않았습니다. 예외의 cause가 GetCredentialCancellationException이면 사용자가 동의 화면을 닫았을 가능성이 높습니다. SMS와 같은 다른 전화번호 인증 방법을 제공합니다. 사용자에게 동의 화면이 다시 표시되므로 자동으로 다시 시도하지 마세요.
CARRIER_NOT_SUPPORTED
(55501)
선택한 SIM의 이동통신사가 지원되지 않거나 기기에 이를 확인하는 데 필요한 구독 정보가 없습니다. SMS와 같은 다른 확인 방법으로 대체합니다.
UNSUPPORTED_OPERATION
(55505)
기기에서 이 요청에 Firebase PNV을(를) 사용할 수 없습니다. SMS와 같은 다른 확인 방법으로 대체합니다.
PREFLIGHT_CHECK_FAILED
(55504)
동의 화면이 표시되기 전에 Firebase PNV 백엔드에서 인증 요청을 만들 수 없습니다. SMS와 같은 다른 확인 방법으로 대체합니다. 모든 요청에서 이 문제가 발생하면 앱이 올바르게 설정되었는지 확인하세요(프로덕션 모드로 업그레이드 참고).
INTEGRITY_CHECK_FAILED
(55503)
기기 또는 앱이 무결성 검사를 통과하지 못했습니다. SMS와 같은 다른 확인 방법으로 대체합니다.
INVALID_DIGITAL_CREDENTIAL_RESPONSE
(55502)
인증 관리자의 응답을 읽을 수 없거나 인증된 전화번호로 교환할 수 없습니다. SMS와 같은 다른 확인 방법으로 대체합니다.
INVALID_TEST_NUMBER_ID
(55507)
테스트 모드에서 Firebase PNV 백엔드가 테스트 토큰을 거부했습니다(예: 만료되었기 때문). 테스트 토큰의 TTL은 7일입니다. 거부된 테스트 토큰은 일반적으로 이 코드를 보고합니다. 테스트 모드에서 다른 오류가 표시되면 토큰이 최신 상태인지도 확인하세요. Firebase Console에서 새 테스트 토큰을 생성하고 앱을 다시 빌드합니다.
ACTIVITY_CONTEXT_REQUIRED
(55509)
getVerifiedPhoneNumber()에 전달된 Context가 Activity가 아닙니다. 이 메서드에는 동의 화면을 표시하기 위한 Activity가 필요합니다. 현재 Activity를 전달합니다. 이는 앱의 버그이며 런타임에 처리할 조건이 아닙니다.

지원 확인

getVerificationSupportInfo()에서 반환된 Task은 검사 자체를 실행할 수 없는 경우에만 실패합니다. 이 경우 errorCode는 Google Play 서비스 CommonStatusCodes 값 또는 CARRIER_NOT_SUPPORTED입니다. 기기를 지원되지 않는 것으로 처리하고 SMS와 같은 다른 확인 방법으로 대체합니다.

테스트 세션이 사용 설정되어 있는 동안에는 getVerificationSupportInfo()가 Firebase PNV 백엔드에 연결하지 않으며 테스트 토큰이 만료된 경우에도 항상 테스트 SIM을 지원되는 것으로 보고합니다.

커스텀 흐름

getVerifiedPhoneNumber() 대신 맞춤 흐름을 사용하는 경우:

  • getDigitalCredentialPayload()는 PREFLIGHT_CHECK_FAILED로 실패하거나 백엔드가 테스트 토큰을 거부하는 경우 INVALID_TEST_NUMBER_ID로 실패합니다.
  • exchangeCredentialResponseForPhoneNumber()는 INVALID_DIGITAL_CREDENTIAL_RESPONSE와 함께 실패하거나 백엔드가 테스트 토큰을 거부하는 경우 INVALID_TEST_NUMBER_ID와 함께 실패합니다.
  • 인증 관리자에 대한 자체 호출에서 GetCredentialException가 발생하며, 이를 직접 처리합니다.

지원되지 않는 기기 및 SIM

SIM의 isSupported()가 false인 경우 getReason()는 다음 VerificationSupportStatus 값 중 하나를 반환합니다.

값 의미
INCAPABLE_DUE_TO_CARRIER_UNSUPPORTED SIM의 이동통신사가 지원되지 않습니다. 지원되는 이동통신사를 참고하세요.
INCAPABLE_DUE_TO_ANDROID_VERSION 기기에서 Android 9 (API 수준 28) 이전 버전의 Android를 실행합니다.
INCAPABLE_DUE_TO_SIM_STATE SIM이 준비되지 않았습니다. 잠겨 있거나 아직 로드 중인 SIM도 이동통신사가 먼저 확인되므로 INCAPABLE_DUE_TO_CARRIER_UNSUPPORTED를 보고할 수 있습니다.

각 경우에 해당 SIM에 SMS와 같은 다른 확인 방법을 사용하세요.

예

다음 예에서는 일반적인 앱이 getVerifiedPhoneNumber()를 호출할 때 구분해야 하는 오류를 처리합니다.

Kotlin

import android.util.Log
// Credential Manager is included with the Firebase PNV library.
import androidx.credentials.exceptions.GetCredentialCancellationException
import com.google.firebase.pnv.FirebasePhoneNumberVerification
import com.google.firebase.pnv.FirebasePhoneNumberVerificationException
import com.google.firebase.pnv.FirebasePnvStatusCodes

private const val TAG = "PhoneVerification"

// In your Activity:
private fun verifyPhoneNumber() {
    FirebasePhoneNumberVerification.getInstance()
        .getVerifiedPhoneNumber(this)
        .addOnSuccessListener { result ->
            // Send result.getToken() to your backend.
        }
        .addOnFailureListener { e -> handleFpnvError(e) }
}

private fun handleFpnvError(e: Exception) {
    if (e !is FirebasePhoneNumberVerificationException) {
        Log.w(TAG, "Firebase PNV failed", e)
        showSmsVerification()
        return
    }
    when (e.errorCode) {
        FirebasePnvStatusCodes.CREDENTIAL_MANAGER_ERROR -> {
            if (e.cause is GetCredentialCancellationException) {
                // The user dismissed the consent screen.
            }
            showSmsVerification()
        }
        FirebasePnvStatusCodes.INVALID_TEST_NUMBER_ID -> {
            // Test mode only: generate a new test token.
            Log.e(TAG, "Firebase PNV test token rejected", e)
        }
        FirebasePnvStatusCodes.ACTIVITY_CONTEXT_REQUIRED -> {
            // App bug: pass an Activity to getVerifiedPhoneNumber().
            Log.e(TAG, "Firebase PNV needs an Activity context", e)
        }
        else -> {
            // Carrier not supported, network errors, and other failures.
            Log.w(TAG, "Firebase PNV failed with error code ${e.errorCode}", e)
            showSmsVerification()
        }
    }
}

이 예시에서 showSmsVerification()는 앱의 기존 전화번호 인증 흐름입니다.

다음 단계