طلب إثبات الملكية عبر الرسائل القصيرة SMS في تطبيق Android

لتأكيد أرقام الهواتف تلقائيًا، عليك تنفيذ كل من جزأَي العميل والخادم في عملية التأكيد. يوضّح هذا المستند كيفية تنفيذ الجزء الخاص بالعميل في تطبيق Android.

لبدء عملية تأكيد رقم الهاتف في تطبيق Android، عليك إرسال رقم الهاتف إلى خادم التأكيد واستدعاء واجهة برمجة التطبيقات SMS Retriever API لبدء الاستماع إلى رسالة SMS تحتوي على رمز يُستخدم لمرة واحدة لتطبيقك. بعد تلقّي الرسالة، عليك إرسال الرمز الذي يُستخدم لمرة واحدة إلى الخادم لإكمال عملية التأكيد.

لإعداد تطبيقك، أكمِل الخطوات الواردة في الأقسام التالية.

المتطلبات الأساسية للتطبيق

تأكَّد من أنّ ملف إصدار تطبيقك يستخدم القيم التالية:

  • الإصدار 19 من حزمة minSdkVersion أو إصدار أحدث
  • ‫compileSdkVersion من الإصدار 28 أو إصدار أحدث

إعداد تطبيقك

في ملف build.gradle على مستوى المشروع، أدرِج مستودع Maven من Google ومستودع Maven المركزي في القسمَين buildscript وallprojects:

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

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

أضِف اعتمادية خدمات Google Play لواجهة SMS Retriever API إلى ملف Gradle الخاص بالوحدة، والذي يكون عادةً app/build.gradle:

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

الحصول على رقم هاتف المستخدم

يمكنك الحصول على رقم هاتف المستخدم بأي طريقة مناسبة لتطبيقك. وغالبًا ما تكون أفضل تجربة للمستخدم هي استخدام أداة اختيار التلميحات لمطالبة المستخدم بالاختيار من بين أرقام الهواتف المخزّنة على الجهاز، وبالتالي تجنُّب كتابة رقم الهاتف يدويًا. لاستخدام أداة اختيار التلميحات:

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

بدء استرداد الرسائل القصيرة SMS

عندما تكون مستعدًا لإثبات ملكية رقم هاتف المستخدم، احصل على مثيل من عنصر SmsRetrieverClient، واستدعِ startSmsRetriever، وأرفِق أدوات معالجة النجاح والفشل بمهمة استرداد الرسائل القصيرة:

// 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 using 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، أرسِل رقم هاتف المستخدم إلى خادم التحقّق باستخدام أي طريقة (عادةً من خلال طلب POST عبر HTTPS).

ينشئ الخادم رسالة تأكيد ويرسلها عبر رسالة قصيرة إلى رقم الهاتف الذي حدّدته. يُرجى الاطّلاع على إجراء عملية التحقّق من رسائل SMS على الخادم.

تلقّي رسائل التحقّق

عند تلقّي رسالة تأكيد على جهاز المستخدم، تبثّ "خدمات Play" بشكل صريح إلى تطبيقك طلب SmsRetriever.SMS_RETRIEVED_ACTION، الذي يحتوي على نص الرسالة. استخدِم BroadcastReceiver لتلقّي رسالة التحقّق هذه.

في معالج onReceive الخاص بـ BroadcastReceiver، يمكنك الحصول على نص رسالة التحقّق (وعنوان المُرسِل اختياريًا) من إضافات Intent:

/**
  *   BroadcastReceiver to wait for SMS messages. This can be registered either
  *   in the AndroidManifest or at runtime. Filters 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;
      }
    }
  }
}

لتسجيل BroadcastReceiver، يُرجى استخدام ما يلي:

  • intent filter: com.google.android.gms.auth.api.phone.SMS_RETRIEVED (قيمة الثابت SmsRetriever.SMS_RETRIEVED_ACTION)
  • الإذن: com.google.android.gms.auth.api.phone.permission.SEND (قيمة الثابت SmsRetriever.SEND_PERMISSION)

يمكنك تسجيل جهاز الاستقبال في ملف AndroidManifest.xml الخاص بتطبيقك، كما في المثال التالي، أو بشكل ديناميكي باستخدام 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>

أرسِل الرمز الذي يُستخدم لمرة واحدة من رسالة التحقّق إلى خادمك

بعد الحصول على نص رسالة التحقّق، استخدِم تعبيرًا عاديًا أو أي منطق آخر للحصول على الرمز الذي يتم استخدامه لمرة واحدة من الرسالة. يعتمد تنسيق الرمز الذي يُستخدم لمرة واحدة على كيفية تنفيذه في الخادم.

أخيرًا، أرسِل الرمز الذي يُستخدَم لمرة واحدة إلى الخادم عبر اتصال آمن. عندما يتلقّى الخادم الرمز الذي يُستخدم لمرة واحدة، يسجّل أنّه تم تأكيد رقم الهاتف.