درخواست تأیید پیامک در یک برنامه Android

برای تأیید خودکار شماره تلفن‌ها، باید هر دو بخش کلاینت و سرور جریان تأیید را پیاده‌سازی کنید. این سند نحوه پیاده‌سازی بخش کلاینت را در یک برنامه اندروید شرح می‌دهد.

برای شروع فرآیند تأیید شماره تلفن در یک برنامه اندروید، شماره تلفن را به سرور تأیید خود ارسال می‌کنید و API بازیابی پیامک (SMS Retriever API) را فراخوانی می‌کنید تا شروع به گوش دادن به یک پیام کوتاه حاوی کد یکبار مصرف برای برنامه شما کند. پس از دریافت پیام، کد یکبار مصرف را برای تکمیل فرآیند تأیید به سرور خود ارسال می‌کنید.

برای آماده‌سازی برنامه خود، مراحل بخش‌های زیر را تکمیل کنید.

پیش‌نیازهای برنامه

مطمئن شوید که فایل ساخت برنامه شما از مقادیر زیر استفاده می‌کند:

  • حداقل نسخه SDK از ۱۹ یا بالاتر
  • یک compileSdkVersion با نسخه ۲۸ یا بالاتر

برنامه خود را پیکربندی کنید

در فایل build.gradle در سطح پروژه، مخزن Maven گوگل و مخزن مرکزی Maven را هم در بخش‌های buildscript و هم allprojects خود وارد کنید:

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

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

وابستگی سرویس‌های گوگل پلی را برای API مربوط به SMS Retriever به فایل Gradle build ماژول خود که معمولاً app/build.gradle است، اضافه کنید:

dependencies {
  implementation 'com.google.android.gms:play-services-auth:21.4.0'
  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
      }
  }
}

بازیابی پیامک را شروع کنید

وقتی آماده تأیید شماره تلفن کاربر شدید، یک نمونه از شیء 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
    // ...
  }
});

وظیفه بازیابی پیامک تا پنج دقیقه منتظر دریافت پیامکی می‌ماند که حاوی رشته‌ای منحصر به فرد است که برنامه شما را شناسایی می‌کند.

شماره تلفن را به سرور خود ارسال کنید

پس از اینکه شماره تلفن کاربر را دریافت کردید و شروع به گوش دادن به پیامک‌ها کردید، شماره تلفن کاربر را با استفاده از هر روشی (معمولاً با یک درخواست HTTPS POST) به سرور تأیید خود ارسال کنید.

سرور شما یک پیام تأیید ایجاد می‌کند و آن را از طریق پیامک به شماره تلفنی که مشخص کرده‌اید ارسال می‌کند. به بخش «انجام تأیید پیامکی روی سرور» مراجعه کنید.

دریافت پیام‌های تأیید

وقتی یک پیام تأیید در دستگاه کاربر دریافت می‌شود، سرویس‌های Play به صراحت یک SmsRetriever.SMS_RETRIEVED_ACTION Intent را که حاوی متن پیام است، به برنامه شما ارسال می‌کنند. برای دریافت این پیام تأیید از 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 ، از موارد زیر استفاده کنید:

  • فیلتر هدف: 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>

کد یکبار مصرف را از پیام تأیید به سرور خود ارسال کنید

حالا که متن پیام تأیید را دارید، از یک عبارت منظم یا منطق دیگری برای دریافت کد یکبار مصرف از پیام استفاده کنید. قالب کد یکبار مصرف بستگی به نحوه پیاده‌سازی آن در سرور شما دارد.

در نهایت، کد یکبار مصرف را از طریق یک اتصال امن به سرور خود ارسال کنید. وقتی سرور شما کد یکبار مصرف را دریافت می‌کند، ثبت می‌کند که شماره تلفن تأیید شده است.

،

برای تأیید خودکار شماره تلفن‌ها، باید هر دو بخش کلاینت و سرور جریان تأیید را پیاده‌سازی کنید. این سند نحوه پیاده‌سازی بخش کلاینت را در یک برنامه اندروید شرح می‌دهد.

برای شروع فرآیند تأیید شماره تلفن در یک برنامه اندروید، شماره تلفن را به سرور تأیید خود ارسال می‌کنید و API بازیابی پیامک (SMS Retriever API) را فراخوانی می‌کنید تا شروع به گوش دادن به یک پیام کوتاه حاوی کد یکبار مصرف برای برنامه شما کند. پس از دریافت پیام، کد یکبار مصرف را برای تکمیل فرآیند تأیید به سرور خود ارسال می‌کنید.

برای آماده‌سازی برنامه خود، مراحل بخش‌های زیر را تکمیل کنید.

پیش‌نیازهای برنامه

مطمئن شوید که فایل ساخت برنامه شما از مقادیر زیر استفاده می‌کند:

  • حداقل نسخه SDK از ۱۹ یا بالاتر
  • یک compileSdkVersion با نسخه ۲۸ یا بالاتر

برنامه خود را پیکربندی کنید

در فایل build.gradle در سطح پروژه، مخزن Maven گوگل و مخزن مرکزی Maven را هم در بخش‌های buildscript و هم allprojects خود وارد کنید:

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

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

وابستگی سرویس‌های گوگل پلی را برای API مربوط به SMS Retriever به فایل Gradle build ماژول خود که معمولاً app/build.gradle است، اضافه کنید:

dependencies {
  implementation 'com.google.android.gms:play-services-auth:21.4.0'
  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
      }
  }
}

بازیابی پیامک را شروع کنید

وقتی آماده تأیید شماره تلفن کاربر شدید، یک نمونه از شیء 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
    // ...
  }
});

وظیفه بازیابی پیامک تا پنج دقیقه منتظر دریافت پیامکی می‌ماند که حاوی رشته‌ای منحصر به فرد است که برنامه شما را شناسایی می‌کند.

شماره تلفن را به سرور خود ارسال کنید

پس از اینکه شماره تلفن کاربر را دریافت کردید و شروع به گوش دادن به پیامک‌ها کردید، شماره تلفن کاربر را با استفاده از هر روشی (معمولاً با یک درخواست HTTPS POST) به سرور تأیید خود ارسال کنید.

سرور شما یک پیام تأیید ایجاد می‌کند و آن را از طریق پیامک به شماره تلفنی که مشخص کرده‌اید ارسال می‌کند. به بخش «انجام تأیید پیامکی روی سرور» مراجعه کنید.

دریافت پیام‌های تأیید

وقتی یک پیام تأیید در دستگاه کاربر دریافت می‌شود، سرویس‌های Play به صراحت یک SmsRetriever.SMS_RETRIEVED_ACTION Intent را که حاوی متن پیام است، به برنامه شما ارسال می‌کنند. برای دریافت این پیام تأیید از 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 ، از موارد زیر استفاده کنید:

  • فیلتر هدف: 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>

کد یکبار مصرف را از پیام تأیید به سرور خود ارسال کنید

حالا که متن پیام تأیید را دارید، از یک عبارت منظم یا منطق دیگری برای دریافت کد یکبار مصرف از پیام استفاده کنید. قالب کد یکبار مصرف بستگی به نحوه پیاده‌سازی آن در سرور شما دارد.

در نهایت، کد یکبار مصرف را از طریق یک اتصال امن به سرور خود ارسال کنید. وقتی سرور شما کد یکبار مصرف را دریافت می‌کند، ثبت می‌کند که شماره تلفن تأیید شده است.