Android 앱에서 SMS 확인 요청

전화번호를 자동으로 확인하려면 확인 흐름의 클라이언트 부분과 서버 부분을 모두 구현해야 합니다. 이 문서는 Android 앱에서 클라이언트 부분을 구현하는 방법을 설명합니다.

Android 앱에서 전화번호 확인 흐름을 시작하려면 전화번호를 확인 서버로 보내고 SMS Retriever API를 호출하여 앱의 일회성 코드가 포함된 SMS 메시지 수신을 시작합니다. 메시지를 받은 후 확인 프로세스를 완료하기 위해 일회성 코드를 서버로 다시 보냅니다.

시작하기 전에

앱을 준비하려면 다음 섹션의 단계를 완료하세요.

앱 전제 조건

앱의 빌드 파일이 다음 값을 사용하는지 확인하십시오.

  • minSdkVersion 19 이상
  • 28 이상의 compileSdkVersion

앱 구성

프로젝트 수준의 build.gradle 파일에 포함 구글의 메이븐 저장소메이븐 중앙 저장소 당신의 모두 buildscriptallprojects 섹션 :

buildscript {
    repositories {
        google()
        mavenCentral()
    }
}

allprojects {
    repositories {
        google()
        mavenCentral()
    }
}

추가 구글 플레이 서비스 사용자에 대한 SMS 리트리버 API에 대한 의존성을 모듈의 Gradle을 빌드 파일 일반적이며, app/build.gradle :

dependencies {
  implementation 'com.google.android.gms:play-services-auth:19.2.0'
  implementation 'com.google.android.gms:play-services-auth-api-phone:17.5.1'
}

1. 사용자의 전화번호 획득

앱에 적합한 방법으로 사용자의 전화번호를 얻을 수 있습니다. 종종 힌트 선택기를 사용하여 사용자에게 장치에 저장된 전화 번호를 선택하라는 메시지를 표시함으로써 전화 번호를 수동으로 입력할 필요가 없도록 하는 것이 최상의 사용자 경험입니다. 힌트 선택기를 사용하려면:

// Construct a request for phone numbers and show the picker
private void requestHint() {
    HintRequest hintRequest = new HintRequest.Builder()
           .setPhoneNumberIdentifierSupported(true)
           .build();

    PendingIntent intent = Auth.CredentialsApi.getHintPickerIntent(
            apiClient, hintRequest);
    startIntentSenderForResult(intent.getIntentSender(),
            RESOLVE_HINT, null, 0, 0, 0);
}

// Obtain the phone number from the result
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  if (requestCode == RESOLVE_HINT) {
      if (resultCode == RESULT_OK) {
          Credential credential = data.getParcelableExtra(Credential.EXTRA_KEY);
          // credential.getId();  <-- will need to process phone number string
      }
  }
}

2. SMS 리트리버 시작

당신이 사용자의 전화 번호를 확인 할 준비가되면, 인스턴스 수 SmsRetrieverClient , 개체를 호출 startSmsRetriever 하고 SMS 검색 작업에 성공과 실패 청취자를 첨부 :

// Get an instance of SmsRetrieverClient, used to start listening for a matching
// SMS message.
SmsRetrieverClient client = SmsRetriever.getClient(this /* context */);

// Starts SmsRetriever, which waits for ONE matching SMS message until timeout
// (5 minutes). The matching SMS message will be sent via a Broadcast Intent with
// action SmsRetriever#SMS_RETRIEVED_ACTION.
Task<Void> task = client.startSmsRetriever();

// Listen for success/failure of the start Task. If in a background thread, this
// can be made blocking using Tasks.await(task, [timeout]);
task.addOnSuccessListener(new OnSuccessListener<Void>() {
  @Override
  public void onSuccess(Void aVoid) {
    // Successfully started retriever, expect broadcast intent
    // ...
  }
});

task.addOnFailureListener(new OnFailureListener() {
  @Override
  public void onFailure(@NonNull Exception e) {
    // Failed to start retriever, inspect Exception for more details
    // ...
  }
});

SMS 검색 작업은 앱을 식별하는 고유한 문자열이 포함된 SMS 메시지를 최대 5분 동안 수신 대기합니다.

3. 전화번호를 서버로 전송

사용자의 전화번호를 획득하고 SMS 메시지 수신을 시작한 후에는 모든 방법(일반적으로 HTTPS POST 요청 사용)을 사용하여 사용자의 전화번호를 확인 서버로 보냅니다.

서버에서 확인 메시지를 생성하고 SMS로 지정한 전화번호로 보냅니다. 참조 서버에서 SMS 인증을 수행합니다 .

4. 인증 메시지 수신

확인 메시지가 사용자의 기기에 수신되면, 재생 서비스는 명시 적으로 인앱에 방송 SmsRetriever.SMS_RETRIEVED_ACTION 메시지의 텍스트를 포함 의도. 용도 BroadcastReceiver 이 확인 메시지가 나타날 수 있습니다.

에서 BroadcastReceiveronReceive 핸들러, 텐트의 엑스트라에서 확인 메시지의 텍스트를 얻을 :

/**
 * BroadcastReceiver to wait for SMS messages. This can be registered either
 * in the AndroidManifest or at runtime.  Should filter Intents on
 * SmsRetriever.SMS_RETRIEVED_ACTION.
 */
public class MySMSBroadcastReceiver extends BroadcastReceiver {

  @Override
  public void onReceive(Context context, Intent intent) {
    if (SmsRetriever.SMS_RETRIEVED_ACTION.equals(intent.getAction())) {
      Bundle extras = intent.getExtras();
      Status status = (Status) extras.get(SmsRetriever.EXTRA_STATUS);

      switch(status.getStatusCode()) {
        case CommonStatusCodes.SUCCESS:
          // Get SMS message contents
          String message = (String) extras.get(SmsRetriever.EXTRA_SMS_MESSAGE);
          // Extract one-time code from the message and complete verification
          // by sending the code back to your server.
          break;
        case CommonStatusCodes.TIMEOUT:
          // Waiting for SMS timed out (5 minutes)
          // Handle the error ...
          break;
      }
    }
  }
}

이 레지스터 BroadcastReceiver 의도 필터 com.google.android.gms.auth.api.phone.SMS_RETRIEVED (의 값 SmsRetriever.SMS_RETRIEVED_ACTION 정수) 및 권한 com.google.android.gms.auth.api.phone.permission.SEND (의 값 SmsRetriever.SEND_PERMISSION 앱의 상수) AndroidManifest.xml 다음 예제와 같이 파일, 또는 동적으로 사용하여 Context.registerReceiver .

<receiver android:name=".MySMSBroadcastReceiver" android:exported="true"
          android:permission="com.google.android.gms.auth.api.phone.permission.SEND">
    <intent-filter>
        <action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED"/>
    </intent-filter>
</receiver>

5. 인증 메시지의 일회용 코드를 서버로 보냅니다.

이제 확인 메시지의 텍스트가 있으므로 정규식이나 다른 논리를 사용하여 메시지에서 일회성 코드를 가져옵니다. 일회성 코드의 형식은 서버에서 코드를 구현한 방법에 따라 다릅니다.

마지막으로 보안 연결을 통해 서버에 일회용 코드를 보냅니다. 서버가 일회용 코드를 수신하면 전화번호가 확인되었음을 기록합니다.

선택 사항: Smart Lock for Passwords로 전화번호 저장

선택적으로 사용자가 전화번호를 확인한 후 이 전화번호 계정을 비밀번호용 Smart Lock으로 저장하도록 요청할 수 있습니다. 그러면 전화번호를 다시 입력하거나 선택하지 않고도 다른 앱과 다른 장치에서 자동으로 사용할 수 있습니다. :

Credential credential = new Credential.Builder(phoneNumberString)
        .setAccountType("https://signin.example.com")  // a URL specific to the app
        .setName(displayName)  // optional: a display name if available
        .build();
Auth.CredentialsApi.save(apiClient, credential).setResultCallback(
            new ResultCallback() {
                public void onResult(Result result) {
                    Status status = result.getStatus();
                    if (status.isSuccess()) {
                        Log.d(TAG, "SAVE: OK");  // already saved
                    } else if (status.hasResolution()) {
                        // Prompt the user to save
                        status.startResolutionForResult(this, RC_SAVE);
                    }
                }
            });

그런 다음 사용자가 앱을 다시 설치하거나 새 기기에 앱을 설치한 후 사용자에게 전화번호를 다시 묻지 않고도 저장된 전화번호를 검색할 수 있습니다.

// On the next install, retrieve the phone number
mCredentialRequest = new CredentialRequest.Builder()
    .setAccountTypes("https://signin.example.com")  // the URL specific to the developer
    .build();
Auth.CredentialsApi.request(apiClient, mCredentialRequest).setResultCallback(
    new ResultCallback<CredentialRequestResult>() {
        public void onResult(CredentialRequestResult credentialRequestResult) {
            if (credentialRequestResult.getStatus().isSuccess()) {
                credentialRequestResult.getCredential().getId();  // this is the phone number
            }
        }
    });

// Then, initiate verification and sign the user in (same as original verification logic)