Android 앱에서 SMS 확인 요청

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

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

전제 조건

SMS Retriever API는 Play 서비스 버전 10.2 이상이 설치된 Android 기기에서만 사용할 수 있습니다.

종속성 설치

앱의 build.gradle 파일에 Play 서비스 인증 구성 요소를 포함합니다.

implementation 'com.google.android.gms:play-services-auth:17.0.0'
implementation 'com.google.android.gms:play-services-auth-api-phone:17.4.0'

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. 확인 메시지 받기

사용자의 기기에서 확인 메시지가 수신되면 Play 서비스는 메시지 텍스트가 포함 된 SmsRetriever.SMS_RETRIEVED_ACTION Intent를 앱에 명시 적으로 브로드 캐스트합니다. 이 확인 메시지를 받으려면 BroadcastReceiver 를 사용하십시오.

BroadcastReceiveronReceive 핸들러에서 Intent의 추가 항목에서 확인 메시지 텍스트를 가져옵니다.

/**
 * 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;
      }
    }
  }
}

인 텐트 필터 com.google.android.gms.auth.api.phone.SMS_RETRIEVED ( SmsRetriever.SMS_RETRIEVED_ACTION 상수 값) 및 권한 com.google.android.gms.auth.api.phone.permission.SEND 사용하여이 BroadcastReceiver 를 등록 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으로 전화 번호 저장

선택적으로 사용자가 전화 번호를 확인한 후 사용자에게 비밀번호 대용 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)