Richiesta di verifica SMS in un'app Android

Per verificare automaticamente i numeri di telefono, devi implementare sia la parte client sia la parte server del flusso di verifica. Questo documento descrive come implementare la parte client in un'app per Android.

Per avviare il flusso di verifica del numero di telefono in un'app per Android, invia il numero di telefono al tuo server di verifica e chiama l'API SMS Retriever per iniziare a monitorare la ricezione di un messaggio SMS contenente un codice una tantum per la tua app. Dopo aver ricevuto il messaggio, invia il codice una tantum al tuo server per completare la procedura di verifica.

Prima di iniziare

Per preparare l'app, completa i passaggi descritti nelle sezioni seguenti.

Prerequisiti delle app

Assicurati che il file di compilazione dell'app utilizzi i seguenti valori:

  • Una versione minSdkVersion pari o superiore a 19
  • Un valore compileSdkVersion pari o superiore a 28

Configura la tua app

Nel file build.gradle a livello di progetto, includi il repository Maven di Google e il repository centrale Maven in entrambe le sezioni buildscript e allprojects:

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

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

Aggiungi la dipendenza da Google Play Services per l'API SMS Retriever al file di build Gradle del modulo, solitamente app/build.gradle:

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

1. Ottenere il numero di telefono dell'utente

Puoi ottenere il numero di telefono dell'utente nel modo più appropriato per la tua app. Spesso, l'esperienza utente migliore è utilizzare il selettore di suggerimenti per chiedere all'utente di scegliere tra i numeri di telefono memorizzati sul dispositivo ed evitare così di dover digitare manualmente un numero di telefono. Per utilizzare il selettore di suggerimenti:

// 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. Avvia il recupero di SMS

Quando è tutto pronto per verificare il numero di telefono dell'utente, recupera un'istanza dell'oggetto SmsRetrieverClient, chiama startSmsRetriever e associa ascoltatori di successo e fallimento all'attività di recupero dell'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
    // ...
  }
});

L'attività di recupero degli SMS ascolterà per un massimo di cinque minuti un messaggio SMS contenente una stringa univoca che identifica la tua app.

3. Invia il numero di telefono al tuo server

Dopo aver ottenuto il numero di telefono dell'utente e aver iniziato a monitorare i messaggi SMS, invia il numero di telefono al tuo server di verifica utilizzando qualsiasi metodo (di solito con una richiesta POST HTTPS).

Il server genera un messaggio di verifica e lo invia tramite SMS al numero di telefono specificato. Consulta la sezione Eseguire la verifica SMS sul server.

4. Ricevere messaggi di verifica

Quando un messaggio di verifica viene ricevuto sul dispositivo dell'utente, Play Services invia esplicitamente alla tua app un Intent SmsRetriever.SMS_RETRIEVED_ACTION contenente il testo del messaggio. Utilizza un BroadcastReceiver per ricevere questo messaggio di verifica.

Nell'handler BroadcastReceiver di onReceive, recupera il testo del messaggio di verifica (e, facoltativamente, l'indirizzo del mittente) dagli extra dell'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:
          // (Optional) Get SMS Sender address - only available in
          // GMS version 24.20 onwards, else it will return null
          String senderAddress = extras.getString(SmsRetriever.EXTRA_SMS_ORIGINATING_ADDRESS);
          // Get SMS message contents
          String message = extras.getString(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;
      }
    }
  }
}

Registra questo BroadcastReceiver con il filtro intent com.google.android.gms.auth.api.phone.SMS_RETRIEVED (il valore della costante SmsRetriever.SMS_RETRIEVED_ACTION) e la permissione com.google.android.gms.auth.api.phone.permission.SEND (il valore della costante SmsRetriever.SEND_PERMISSION) nel file AndroidManifest.xml della tua app, come nell'esempio seguente, o utilizzando dinamicamente 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. Invia il codice una tantum del messaggio di verifica al tuo server

Ora che hai il testo del messaggio di verifica, utilizza un'espressione regolare o un'altra logica per ottenere il codice una tantum dal messaggio. Il formato del codice una tantum dipende da come lo hai implementato nel server.

Infine, invia il codice una tantum al server tramite una connessione sicura. Quando il tuo server riceve il codice una tantum, registra che il numero di telefono è stato verificato.