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, bir 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 doğrulama kodunu telefon sunucunuza gönderir ve uygulamanız için tek kullanımlık bir kod içeren SMS mesajı almaya başlamak için SMS Lookup API'yi çağırırsı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 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 derSdkVersion

Uygulamanızı yapılandırma

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

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

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

Google Play HizmetleriBağımlılığını SMS Retriever API'sinin Modülün Gradle derleme dosyanıza genellikle app/build.gradle olması için ekleyin:

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. Kullanıcının telefon numarasını alın

Kullanıcının telefon numarasını uygulamanıza uygun şekilde edinebilirsiniz. Genellikle en iyi kullanıcı deneyimi, kullanıcının cihazda depolanan telefon numaralarından seçim yapmasını istemek için ipucu seçiciyi kullanmaktır. Böylece, bir telefon numarasını manuel olarak yazmak zorunda kalmazsınız. İ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ı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 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 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 HTTPS POST isteğiyle) doğrulama sunucunuza gönderin.

Sunucunuz bir doğrulama mesajı oluşturur ve SMS ile belirlediğiniz telefon numarasına gönderir. Sunucuda SMS Doğrulaması gerçekleştirme konusuna bakın.

4. Doğrulama mesajları alma

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

BroadcastReceiver kullanıcısının 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 com.google.android.gms.auth.api.phone.SMS_RETRIEVED kullanarak uygulamanızın AndroidManifest.xml dosyasında intent filtresiyle com.google.android.gms.auth.api.phone.SMS_RETRIEVED (SmsRetriever.SMS_RETRIEVED_ACTION sabit değerinin değeri) ve izni (SmsRetriever.SEND_PERMISSION sabit değerinin değeri) 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 kullanımlık kodu sunucunuza gönderin

Doğrulama mesajı metnini aldığınıza göre, mesajdan tek seferlik kod almak için normal bir ifade veya başka bir mantık kullanabilirsiniz. Tek kullanımlık kodun biçimi, kodu sunucunuza nasıl uyguladığınıza bağlıdır.

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

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

İsteğe bağlı olarak, kullanıcı telefon numarasını doğruladıktan sonra kullanıcının bu telefon numarası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 telefon numarasını tekrar 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)