Przesyłanie prośby o weryfikację SMS-a w aplikacji na Androida

Aby weryfikacja automatyczna odbywała się automatycznie, musisz wdrożyć część procesu weryfikacji zarówno po stronie klienta, jak i po stronie serwera. W tym dokumencie opisujemy, jak wdrożyć część klienta w aplikacji na Androida.

Aby rozpocząć procedurę weryfikacji numeru telefonu w aplikacji na Androida, wyślij numer telefonu na serwer weryfikacji i zadzwoń do interfejsu SMS Fetcher API, aby rozpocząć odbieranie wiadomości SMS zawierającej jednorazowy kod dla aplikacji. Gdy otrzymasz wiadomość, wyślesz jednorazowy kod na swój serwer, aby dokończyć proces weryfikacji.

Zanim zaczniesz

Aby przygotować aplikację, wykonaj czynności opisane w poniższych sekcjach.

Wymagania wstępne aplikacji

Upewnij się, że w kompilacji pliku aplikacji są używane te wartości:

  • minSdkVersion w wersji 19 lub nowszej
  • Metoda compileSdkVersion w wersji 28 lub nowszej

Konfigurowanie aplikacji

W pliku build.gradle na poziomie projektu umieść repozytorium Maven i repozytorium centralne Maven w sekcjach buildscript i allprojects:

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

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

Dodaj zależność Usług Google Play od interfejsu SMS Fetchr API do pliku kompilacji Gradle modułu, który zazwyczaj ma wartość app/build.gradle:

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

1. Uzyskiwanie numeru telefonu użytkownika

Możesz uzyskać numer telefonu użytkownika w sposób odpowiedni dla swojej aplikacji. Często najlepiej jest wybierać go spośród numerów zapisanych na urządzeniu i uniknąć ręcznego wpisywania numeru. Aby użyć selektora podpowiedzi:

// 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. Uruchom moduł pobierania SMS-ów

Gdy przygotujesz się do weryfikacji numeru telefonu użytkownika, pobierz wystąpienie obiektu SmsRetrieverClient, wywołaj metodę startSmsRetriever i dołącz informację o udanym i nieudanym odsłuchaniu do zadania pobierania SMS-ów:

// 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
    // ...
  }
});

Zadanie pobierania SMS-a będzie nasłuchiwać przez maksymalnie 5 minut w przypadku wiadomości zawierającej unikalny ciąg identyfikujący Twoją aplikację.

3. Wyślij numer telefonu na swój serwer

Gdy otrzymasz numer telefonu użytkownika i zaczniesz nasłuchiwać SMS-ów, wyślij numer telefonu tego użytkownika na serwer weryfikacji za pomocą dowolnej metody (zwykle z żądaniem HTTPS POST).

Serwer generuje wiadomość weryfikacyjną i wysyła ją SMS-em na podany numer. Zobacz Przeprowadź weryfikację SMS-em na serwerze.

4. Otrzymuj wiadomości weryfikacyjne

Gdy otrzymasz wiadomość weryfikacyjną na urządzenie użytkownika, Usługi Play jednoznacznie przekażą Twojej aplikacji intencję SmsRetriever.SMS_RETRIEVED_ACTION zawierającą treść wiadomości. Użyj BroadcastReceiver, by odebrać wiadomość.

W module obsługi BroadcastReceiveronReceive pobierz tekst wiadomości weryfikacyjnej z elementów intencji:

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

Zarejestruj BroadcastReceiver za pomocą filtra intencji com.google.android.gms.auth.api.phone.SMS_RETRIEVED (wartości stałej SmsRetriever.SMS_RETRIEVED_ACTION) i uprawnienia com.google.android.gms.auth.api.phone.permission.SEND (wartości stałej SmsRetriever.SEND_PERMISSION) w pliku AndroidManifest.xml aplikacji, jak w poniższym przykładzie, lub dynamicznie za pomocą 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. Wyślij jednorazowy kod z wiadomości weryfikacyjnej na swój serwer

Skoro masz już tekst wiadomości weryfikacyjnej, użyj wyrażenia regularnego lub innej metody, aby pobrać jednorazowy kod z wiadomości. Format kodu jednorazowego zależy od sposobu zaimplementowania go na serwerze.

Na koniec wyślij jednorazowy kod na swój serwer, używając bezpiecznego połączenia. Gdy serwer odbiera kod jednorazowy, rejestruje, że numer telefonu został zweryfikowany.

Opcjonalnie: zapisywanie numeru telefonu za pomocą funkcji Smart Lock na hasła

Opcjonalnie, gdy użytkownik potwierdzi swój numer telefonu, możesz poprosić go o zapisanie konta numeru telefonu przy użyciu funkcji Smart Lock na hasła. Będzie ona automatycznie dostępna w innych aplikacjach i na innych urządzeniach bez potrzeby wpisywania ani wybierania numeru.

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

Gdy użytkownik ponownie zainstaluje aplikację lub zainstaluje ją na nowym urządzeniu, będzie można pobrać zapisany numer telefonu bez konieczności ponownego pytania użytkownika o numer telefonu.

// 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)