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

Zadbaj o dobrą organizację dzięki kolekcji Zapisuj i kategoryzuj treści zgodnie ze swoimi preferencjami.

Aby automatyczna weryfikacja numerów telefonów odbywała się automatycznie, musisz wdrożyć część procesu weryfikacji po stronie klienta oraz serwera. Ten dokument opisuje, jak wdrożyć część klienta w aplikacji na Androida.

Aby rozpocząć procedurę weryfikacji numeru telefonu w aplikacji na Androida, wyślij numer telefonu na swój serwer weryfikacji i wywołaj interfejs SMS Fetcher API, aby zacząć nasłuchiwać wiadomości SMS zawierającej jednorazowy kod dla aplikacji. Po jej otrzymaniu odbierzesz jednorazowy kod na swój serwer w celu ukończenia procesu weryfikacji.

Zanim zaczniesz

Aby przygotować aplikację, wykonaj czynności opisane w kolejnych sekcjach.

Wymagania wstępne aplikacji

Upewnij się, że plik kompilacji aplikacji zawiera następujące wartości:

  • Wartość minSdkVersion w wersji 19 lub nowszej
  • Metoda compileSdkWersja 28 lub nowsza

Skonfiguruj aplikację

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

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

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

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

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

1. Uzyskiwanie numeru telefonu użytkownika

Numer telefonu użytkownika możesz pobrać w sposób odpowiedni dla danej aplikacji. Często najlepszym rozwiązaniem jest użycie selektora podpowiedzi, który pozwala użytkownikowi wybrać spośród dostępnych na urządzeniu numerów telefonów, dzięki czemu nie trzeba ręcznie wpisywać numeru telefonu. 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ł do pobierania SMS-ów

Gdy wszystko będzie gotowe do weryfikacji numeru telefonu użytkownika, uzyskaj wystąpienie obiektu SmsRetrieverClient, wywołaj metodę startSmsRetriever i dołącz detektory powodzenia i niepowodzenia 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-ów będzie nasłuchiwać przez pięć minut w przypadku SMS-a zawierającego unikalny ciąg identyfikujący Twoją aplikację.

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

Po uzyskaniu numeru telefonu użytkownika i rozpoczęciu nasłuchiwania SMS-ów wyślij ten numer na swój serwer weryfikacyjny za pomocą dowolnej metody (zwykle za pomocą żądania HTTPS POST).

Serwer generuje wiadomość weryfikacyjną i wysyła ją SMS-em na podany numer telefonu. Zobacz Weryfikowanie SMS-ów na serwerze.

4. Otrzymuj wiadomości weryfikacyjne

Gdy na urządzeniu użytkownika pojawi się wiadomość weryfikacyjna, Usługi Play jednoznacznie przesyłają do aplikacji intencję SmsRetriever.SMS_RETRIEVED_ACTION zawierającą tekst wiadomości. Użyj BroadcastReceiver, aby odebrać tę wiadomość weryfikacyjną.

W module obsługi onReceive elementu BroadcastReceiver pobierz tekst wiadomości weryfikacyjnej z intencji 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 uprawnień (com.google.android.gms.auth.api.phone.permission.SEND) 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

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

Na koniec wyślij jednorazowy kod na swój serwer przez bezpieczne połączenie. Gdy serwer odbiera kod jednorazowy, rejestruje, że numer telefonu został zweryfikowany.

Opcjonalnie: zapisz numer telefonu w funkcji Smart Lock na hasła

Opcjonalnie, gdy użytkownik potwierdzi numer telefonu, możesz poprosić go o zapisanie konta numeru w funkcji Smart Lock na hasła. Dzięki temu będzie ono automatycznie dostępne w innych aplikacjach i na innych urządzeniach bez potrzeby ponownego wpisywania lub 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, możesz pobrać zapisany numer telefonu bez pytania użytkownika o jej numer:

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