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

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

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

قبل البدء

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

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

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

  • إصدار minSdkVersion به 19 أو أعلى
  • الإصدار 28 أو أعلى من واجهة برمجة التطبيقات SdkVersion

ضبط إعدادات تطبيقك

في ملف 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:21.0.0'
  implementation 'com.google.android.gms:play-services-auth-api-phone:18.0.2'
}

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

2. تشغيل برنامج استرداد الرسائل القصيرة 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 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 لمدة تصل إلى خمس دقائق بالنسبة إلى رسالة SMS التي تحتوي على سلسلة فريدة تعرِّف تطبيقك.

3- إرسال رقم الهاتف إلى خادمك

بعد حصولك على رقم هاتف المستخدم وبدء الاستماع إلى الرسائل القصيرة SMS، أرسل رقم هاتف المستخدم إلى خادم التحقق باستخدام أي طريقة (عادةً ما يكون ذلك من خلال طلب HTTPS POST).

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

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

عند تلقّي رسالة تحقُّق على جهاز المستخدم، ترسِل "خدمات 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.  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;
      }
    }
  }
}

يُرجى تسجيل BroadcastReceiver باستخدام فلتر الأهداف 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>

5- إرسال الرمز لمرة واحدة من رسالة التحقق إلى الخادم

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

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