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, Android uygulamasında istemci bölümünün nasıl uygulanacağı açıklanmaktadır.

Bir Android uygulamasında telefon numarası doğrulama akışını başlatmak için telefon numaranızı doğrulama sunucunuza gönderir ve uygulamanız için tek kullanımlık bir kod içeren SMS mesajını almaya başlamak üzere SMS Receiver API'yi ararsı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 yer alan adımları tamamlayın.

Uygulama ön koşulları

Uygulamanızın derleme dosyasında aşağıdaki değerlerin kullanıldığından emin olun:

  • 19 veya üzeri bir MinSdkVersion
  • 28 veya daha yüksek bir CompSdkVersion

Uygulamanızı yapılandırma

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

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

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

SMS Receiver API için Google Play Hizmetleri bağımlılığını genellikle modülünüzün Gradle derleme dosyasına ekleyin. Bu dosya genellikle app/build.gradle şeklindedir:

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

1. Kullanıcının telefon numarasını öğrenebilirsiniz

Kullanıcının telefon numarasını uygulamanıza uygun herhangi bir şekilde alabilirsiniz. Genellikle en iyi kullanıcı deneyimi, kullanıcıdan cihazda kayıtlı telefon numaraları arasından seçim yapmasını istemek için kullanılacak ve telefon numarasını manuel olarak yazmaktan kaçınmanızdı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 alıcısını başlat

Kullanıcının telefon numarasını doğrulamaya hazır olduğunuzda SmsRetrieverClient nesnesinin bir örneğini alın, startSmsRetriever yöntemini çağırın ve SMS alma görevine başarılı ve başarısız dinleyiciler 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 bir SMS mesajı için beş dakikaya kadar dinler.

3. Telefon numarasını sunucunuza gönderin

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

Sunucunuz bir doğrulama mesajı oluşturur ve SMS ile belirttiğiniz telefon numarasına gönderir. Sunucuda SMS Doğrulaması gerçekleştirme bölümüne bakın.

4. Doğrulama mesajlarını alma

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

BroadcastReceiver onReceive işleyicisinde, doğrulama mesajının metnini Intent'in ekstralarından 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 veya Context.registerReceiver kullanarak dinamik olarak uygulamanızın AndroidManifest.xml dosyasında intent filtresi com.google.android.gms.auth.api.phone.SMS_RETRIEVED (SmsRetriever.SMS_RETRIEVED_ACTION sabit değeri) ve com.google.android.gms.auth.api.phone.permission.SEND (SmsRetriever.SEND_PERMISSION sabit değerinin değeri) ile 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 iletisindeki tek kullanımlık kodu sunucunuza gönderin

Artık doğrulama iletisinin metni aldığınıza göre bir normal ifade veya başka bir mantık kullanarak mesajdaki tek kullanımlık kodu alabilirsiniz. Tek kullanımlık kodun biçimi, sunucunuzda nasıl uyguladığınıza bağlıdır.

Son olarak, tek seferlik kodu güvenli bir bağlantı üzerinden sunucunuza gönderin. Sunucunuz tek kullanımlık kodu aldığında, telefon numarasının doğrulanmış olduğunu 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, 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);
                    }
                }
            });

Kullanıcı uygulamayı yeniden yükledikten veya uygulamayı yeni bir cihaza yükledikten sonra, kayıtlı telefon numarasını kullanıcıdan tekrar telefon numarasını istemeden 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)