Android Uygulamasında SMS Doğrulaması İsteme

Telefon numaralarını otomatik olarak doğrulamak için doğrulama akışının hem istemci hem de sunucu bölümlerini uygulamanız gerekir. Bu dokümanda, istemci bölümünün bir Android uygulamasında nasıl uygulanacağı açıklanmaktadır.

Bir Android uygulamasında telefon numarası doğrulama akışını başlatmak için telefon numarasını doğrulama sunucunuza gönderir ve SMS Retriever API'yi çağırarak uygulamanız için tek seferlik bir kod içeren SMS mesajını dinlemeye başlarsınız. Mesajı aldıktan sonra, doğrulama işlemini tamamlamak için tek seferlik kodu sunucunuza geri gönderirsiniz.

Başlamadan önce

Uygulamanızı hazırlamak için aşağıdaki bölümlerde açıklanan adımları tamamlayın.

Uygulama ön koşulları

Uygulamanızın derleme dosyasının aşağıdaki değerleri kullandığından emin olun:

  • MinSdkVersion 19 veya sonraki sürümler
  • derlenenSdkVersion 28 veya sonraki sürümler

Uygulamanızı yapılandırma

Proje düzeyindeki build.gradle dosyanıza, hem buildscript hem de allprojects bölümlerinize Google'ın Maven deposu ile Maven merkezi deposunu ekleyin:

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

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

SMS Retriever API'ye ilişkin Google Play Hizmetleri bağımlılığını modülünüzün Gradle derleme dosyasına ekleyin. Bu dosya genellikle app/build.gradle olur:

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

1. Kullanıcının telefon numarasını alın

Kullanıcının telefon numarasını uygulamanız için en uygun yöntemle edinebilirsiniz. Genellikle en iyi kullanıcı deneyimi, kullanıcıdan cihazda depolanan telefon numaraları arasından seçim yapmasını istemek ve böylece manuel olarak telefon numarası yazmak zorunda kalmamak için ipucu seçiciyi kullanmaktır. İpucu seçiciyi kullanmak için:

// 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 retriever'ı başlatın

Kullanıcının telefon numarasını doğrulamaya hazır olduğunuzda SmsRetrieverClient nesnesinin bir örneğini alın, startSmsRetriever öğesini arayın ve başarı ve başarısızlık dinleyicilerini SMS alma görevine ekleyin:

// 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 alma görevi, uygulamanızı tanımlayan benzersiz bir dize içeren SMS mesajlarını beş dakikaya kadar dinler.

3. Telefon numarasını sunucunuza gönderin

Kullanıcının telefon numarasını edindikten ve SMS mesajlarını dinlemeye başladıktan sonra, herhangi bir yöntemi (genellikle HTTPS POST isteği ile) kullanarak kullanıcının telefon numarasını doğrulama sunucunuza gönderin.

Sunucunuz bir doğrulama mesajı oluşturur ve bu mesajı belirttiğiniz telefon numarasına SMS ile gönderir. Sunucuda SMS Doğrulaması gerçekleştirme sayfasına göz atın.

4. Doğrulama mesajları alma

Kullanıcının cihazına bir doğrulama mesajı alındığında Play Hizmetleri, uygulamanıza açık bir şekilde mesaj metnini içeren bir SmsRetriever.SMS_RETRIEVED_ACTION Amacı yayınlar. Bu doğrulama mesajını almak için BroadcastReceiver kullanın.

BroadcastReceiver'in onReceive işleyicisinde, Intent'in ekstralarından doğrulama mesajı metnini alın:

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

Bu BroadcastReceiver öğesini, aşağıdaki örnekte olduğu gibi uygulamanızın AndroidManifest.xml dosyasında com.google.android.gms.auth.api.phone.SMS_RETRIEVED (SmsRetriever.SMS_RETRIEVED_ACTION sabitinin değeri) ve izni com.google.android.gms.auth.api.phone.permission.SEND (SmsRetriever.SEND_PERMISSION sabitinin değeri) ile kaydedin veya Context.registerReceiver politikasını kullanarak dinamik olarak kaydedin.

<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. Doğrulama mesajındaki tek seferlik kodu sunucunuza gönderin

Doğrulama mesajı metnine sahip olduğunuza göre artık mesajdan tek seferlik kodu almak için normal ifade veya başka bir mantık kullanabilirsiniz. Tek seferlik kodun biçimi, bu kodu sunucunuza nasıl uyguladığınıza bağlıdır.

Son olarak, tek kullanımlık kodu sunucunuza güvenli bir bağlantı üzerinden gönderin. Sunucunuz tek kullanımlık kodu aldığında, telefon numarasının doğrulandığını kaydeder.

İsteğe bağlı: Telefon numarasını Şifreler için Smart Lock ile kaydetme

İsteğe bağlı olarak, kullanıcı telefon numarasını doğruladıktan sonra, kullanıcıdan bu telefon numarası hesabını Şifreler için Smart Lock ile kaydetmesini isteyebilirsiniz. Böylece bu numara, telefon numarasını tekrar yazmak veya seçmek zorunda kalmadan diğer uygulamalarda ve diğer cihazlarda otomatik olarak kullanılabilir:

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

Ardından, kullanıcı uygulamayı yeniden yükledikten veya yeni bir cihaza yükledikten sonra, kayıtlı telefon numarasını kullanıcıdan telefon numarasını tekrar sormasına gerek kalmadan alabilirsiniz:

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