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

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

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

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

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

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

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

إعداد تطبيقك

في ملف build.gradle على مستوى المشروع، ضُمِّن مستودع Google Maven ومستودع 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.5.1'
  implementation 'com.google.android.gms:play-services-auth-api-phone:18.3.0'
}

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

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

// 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، وأرفِق مستمعَين للنجاح والفشل بمهمة استرداد الرسائل القصيرة SMS:

// 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 لمدة تصل إلى خمس دقائق لرسالة SMS تتضمّن سلسلة فريدة تحدّد تطبيقك.

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

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

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

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

عند تلقّي رسالة تحقّق على جهاز المستخدم، تبثّ خدمات Play بشكلٍ صريح إلى تطبيقك Intent ‏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: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>

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

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

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