Solicitar verificação de SMS em um aplicativo Android

Para verificar automaticamente os números de telefone, você deve implementar as partes do cliente e do servidor do fluxo de verificação. Este documento descreve como implementar a parte do cliente em um aplicativo Android.

Para iniciar o fluxo de verificação do número de telefone em um aplicativo Android, você envia o número de telefone ao servidor de verificação e liga para a API SMS Retriever para começar a ouvir uma mensagem SMS contendo um código único para seu aplicativo. Depois de receber a mensagem, você envia o código único de volta ao servidor para concluir o processo de verificação.

Pré-requisitos

A API SMS Retriever está disponível apenas em dispositivos Android com o Play Services versão 10.2 e mais recente.

Instale dependências

Inclua o componente de autenticação do Play Services no arquivo build.gradle do seu aplicativo:

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. Obtenha o número de telefone do usuário

Você pode obter o número de telefone do usuário da maneira que for apropriada para seu aplicativo. Freqüentemente, é a melhor experiência do usuário usar o seletor de dicas para solicitar que o usuário escolha um dos números de telefone armazenados no dispositivo e, assim, evitar a necessidade de digitar manualmente um número de telefone. Para usar o seletor de dica:

// 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. Inicie o recuperador de SMS

Quando você estiver pronto para verificar o número de telefone do usuário, obtenha uma instância do objeto SmsRetrieverClient , chame startSmsRetriever e anexe ouvintes de sucesso e falha à tarefa de recuperação de 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
    // ...
  }
});

A tarefa de recuperação de SMS ouvirá por até cinco minutos uma mensagem SMS que contém uma string exclusiva que identifica seu aplicativo.

3. Envie o número de telefone para o seu servidor

Depois de obter o número de telefone do usuário e começar a ouvir mensagens SMS, envie o número de telefone do usuário para o servidor de verificação usando qualquer método (geralmente com uma solicitação HTTPS POST).

Seu servidor gera uma mensagem de verificação e a envia por SMS para o número de telefone que você especificou. Consulte Executar verificação de SMS no servidor .

4. Receber mensagens de verificação

Quando uma mensagem de verificação é recebida no dispositivo do usuário, o Play Services transmite explicitamente para seu aplicativo um SmsRetriever.SMS_RETRIEVED_ACTION , que contém o texto da mensagem. Use um BroadcastReceiver para receber esta mensagem de verificação.

No manipulador onReceive do BroadcastReceiver , obtenha o texto da mensagem de verificação dos extras do 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;
      }
    }
  }
}

Registre este BroadcastReceiver com o filtro de intent com.google.android.gms.auth.api.phone.SMS_RETRIEVED (o valor da constante SmsRetriever.SMS_RETRIEVED_ACTION ) e a permissão com.google.android.gms.auth.api.phone.permission.SEND (o valor da constante SmsRetriever.SEND_PERMISSION ) no arquivo AndroidManifest.xml do seu aplicativo, como no exemplo a seguir, ou dinamicamente usando 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. Envie o código único da mensagem de verificação para o seu servidor

Agora que você tem o texto da mensagem de verificação, use uma expressão regular ou outra lógica para obter o código único da mensagem. O formato do código de uso único depende de como você os implementou em seu servidor.

Por fim, envie o código único para o seu servidor por meio de uma conexão segura. Quando o servidor recebe o código único, ele registra que o número de telefone foi verificado.

Opcional: salve o número de telefone com o Smart Lock para senhas

Opcionalmente, após o usuário verificar seu número de telefone, você pode solicitar que o usuário salve essa conta de número de telefone com o Smart Lock para senhas para que esteja disponível automaticamente em outros aplicativos e em outros dispositivos sem ter que digitar ou selecionar o número de telefone novamente :

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

Então, depois que o usuário reinstalar o aplicativo ou instalar o aplicativo em um novo dispositivo, você poderá recuperar o número de telefone salvo sem ter que pedir novamente ao usuário o número de telefone:

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