طلب موافقة لمرّة واحدة لقراءة رمز إثبات الهوية عبر الرسائل القصيرة SMS

تشرح هذه الصفحة كيفية استخدام واجهة برمجة التطبيقات SMS User Consent API لطلب موافقة المستخدم على قراءة رسالة SMS واحدة لإثبات الهوية. إذا وافق المستخدم، تعرض واجهة برمجة التطبيقات نص الرسالة، ويمكنك من خلاله الحصول على رمز إثبات الهوية وإكمال عملية إثبات الهوية.

تثبيت الطلبات المرتبطة

أدرِج مكوّن مصادقة "خدمات Play" في ملف build.gradle الخاص بتطبيقك:

implementation 'com.google.android.gms:play-services-auth:17.0.0'
implementation 'com.google.android.gms:play-services-auth-api-phone:17.4.0'

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

إذا لم يكن لديك رقم هاتف المستخدم، اطلبه قبل بدء عملية إثبات الهوية عبر الرسائل القصيرة.

يمكنك الحصول على رقم هاتف المستخدم بطريقة مناسبة لتطبيقك. ننصحك باستخدام أداة اختيار تلميحات "ميزة Smart Lock لكلمات المرور" لمساعدة المستخدم في ملء رقم هاتفه إذا لم يكن مطلوبًا لإنشاء حساب المستخدم. لاستخدام أداة اختيار التلميحات، اتّبِع الخطوات التالية:

Kotlin

private val CREDENTIAL_PICKER_REQUEST = 1  // Set to an unused request code

// Construct a request for phone numbers and show the picker
private fun requestHint() {
    val hintRequest = HintRequest.Builder()
        .setPhoneNumberIdentifierSupported(true)
        .build()
    val credentialsClient = Credentials.getClient(this)
    val intent = credentialsClient.getHintPickerIntent(hintRequest)
    startIntentSenderForResult(
        intent.intentSender,
        CREDENTIAL_PICKER_REQUEST,
        null, 0, 0, 0
    )
}

public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    when (requestCode) {
        CREDENTIAL_PICKER_REQUEST ->
            // Obtain the phone number from the result
            if (resultCode == Activity.RESULT_OK && data != null) {
                val credential = data.getParcelableExtra<Credential>(Credential.EXTRA_KEY)
                // credential.getId();  <-- will need to process phone number string
            }
        // ...
    }
}

جافا

private static final int CREDENTIAL_PICKER_REQUEST = 1;  // Set to an unused request code

// Construct a request for phone numbers and show the picker
private void requestHint() throws IntentSender.SendIntentException {
    HintRequest hintRequest = new HintRequest.Builder()
            .setPhoneNumberIdentifierSupported(true)
            .build();
    PendingIntent intent = Credentials.getClient(this).getHintPickerIntent(hintRequest);
    startIntentSenderForResult(intent.getIntentSender(),
            RESOLVE_HINT, null, 0, 0, 0);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        case CREDENTIAL_PICKER_REQUEST:
            // Obtain the phone number from the result
            if (resultCode == RESULT_OK) {
                Credential credential = data.getParcelableExtra(Credential.EXTRA_KEY);
                // credential.getId();  <-- will need to process phone number string
            }
            break;
        // ...
    }
}

2- بدء الاستماع إلى الرسائل الواردة

بعد ذلك، استدعِ طريقة startSmsUserConsent() في واجهة برمجة التطبيقات SMS User Consent API لبدء الاستماع إلى الرسائل الواردة. إذا كنت تعرف رقم الهاتف الذي سترد منه الرسالة القصيرة، حدِّده (وإلا مرِّر null). بهذه الطريقة، لن يتم تفعيل واجهة برمجة التطبيقات SMS User Consent API إلا للرسائل الواردة من هذا الرقم.

لبدء الاستماع، اتّبِع الخطوات التالية:

Kotlin

// Start listening for SMS User Consent broadcasts from senderPhoneNumber
// The Task<Void> will be successful if SmsRetriever was able to start
// SMS User Consent, and will error if there was an error starting.
val task = SmsRetriever.getClient(context).startSmsUserConsent(senderPhoneNumber /* or null */)

جافا

// Start listening for SMS User Consent broadcasts from senderPhoneNumber
// The Task<Void> will be successful if SmsRetriever was able to start
// SMS User Consent, and will error if there was an error starting.
Task<Void> task = SmsRetriever.getClient(context).startSmsUserConsent(senderPhoneNumber /* or null */);

بعد بدء الاستماع إلى الرسائل القصيرة الواردة، يمكنك أن تطلب من نظام إثبات الهوية إرسال رمز التحقّق إلى رقم هاتف المستخدم الذي حصلت عليه في الخطوة الأولى.

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

  • تحتوي الرسالة على سلسلة أبجدية رقمية تتألف من 4 إلى 10 أحرف وتحتوي على رقم واحد على الأقل.
  • إذا حدّدت رقم هاتف المُرسِل، يجب أن تكون الرسالة مرسَلة من هذا الرقم.

يمكنك معالجة عمليات البث هذه باستخدام جهاز استقبال البث الذي لديه إذن SEND_PERMISSION ويستجيب لأغراض SMS_RETRIEVED_ACTION. لإنشاء جهاز استقبال البث وتسجيله، اتّبِع الخطوات التالية:

Kotlin

private val SMS_CONSENT_REQUEST = 2  // Set to an unused request code
private val smsVerificationReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (SmsRetriever.SMS_RETRIEVED_ACTION == intent.action) {
            val extras = intent.extras
            val smsRetrieverStatus = extras?.get(SmsRetriever.EXTRA_STATUS) as Status

            when (smsRetrieverStatus.statusCode) {
                CommonStatusCodes.SUCCESS -> {
                    // Get consent intent
                    val consentIntent = extras.getParcelable<Intent>(SmsRetriever.EXTRA_CONSENT_INTENT)
                    try {
                        // Start activity to show consent dialog to user, activity must be started in
                        // 5 minutes, otherwise you'll receive another TIMEOUT intent
                        startActivityForResult(consentIntent, SMS_CONSENT_REQUEST)
                    } catch (e: ActivityNotFoundException) {
                        // Handle the exception ...
                    }
                }
                CommonStatusCodes.TIMEOUT -> {
                    // Time out occurred, handle the error.
                }
            }
        }
    }
}

override fun onCreate(savedInstanceState: Bundle?) {
    // ...

    val intentFilter = IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION)
    registerReceiver(smsVerificationReceiver, SmsRetriever.SEND_PERMISSION, intentFilter)
}

جافا

private static final int SMS_CONSENT_REQUEST = 2;  // Set to an unused request code
private final BroadcastReceiver smsVerificationReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (SmsRetriever.SMS_RETRIEVED_ACTION.equals(intent.getAction())) {
            Bundle extras = intent.getExtras();
            Status smsRetrieverStatus = (Status) extras.get(SmsRetriever.EXTRA_STATUS);

            switch (smsRetrieverStatus.getStatusCode()) {
                case CommonStatusCodes.SUCCESS:
                    // Get consent intent
                    Intent consentIntent = extras.getParcelable(SmsRetriever.EXTRA_CONSENT_INTENT);
                    try {
                        // Start activity to show consent dialog to user, activity must be started in
                        // 5 minutes, otherwise you'll receive another TIMEOUT intent
                        startActivityForResult(consentIntent, SMS_CONSENT_REQUEST);
                    } catch (ActivityNotFoundException e) {
                        // Handle the exception ...
                    }
                    break;
                case CommonStatusCodes.TIMEOUT:
                    // Time out occurred, handle the error.
                    break;
            }
        }
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // ...

    IntentFilter intentFilter = new IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION);
    registerReceiver(smsVerificationReceiver, SmsRetriever.SEND_PERMISSION, intentFilter);
}

من خلال بدء نشاط لـ EXTRA_CONSENT_INTENT، تطلب من المستخدم إذنًا لمرة واحدة بقراءة محتوى الرسالة.

‫3- الحصول على رمز التحقّق من رسالة

في طريقة onActivityResult()، عالِج استجابة المستخدم لطلب الإذن. إذا حصلت على رمز نتيجة RESULT_OK، يكون المستخدم قد منح الإذن بقراءة محتوى الرسالة، ويمكنك الحصول على نص الرسالة من الغرض.

Kotlin

public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    when (requestCode) {
        // ...
        SMS_CONSENT_REQUEST ->
            // Obtain the phone number from the result
            if (resultCode == Activity.RESULT_OK && data != null) {
                // Get SMS message content
                val message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)
                // Extract one-time code from the message and complete verification
                // `message` contains the entire text of the SMS message, so you will need
                // to parse the string.
                val oneTimeCode = parseOneTimeCode(message) // define this function

                // send one time code to the server
            } else {
                // Consent denied. User can type OTC manually.
            }
    }
}

جافا

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        // ...
        case SMS_CONSENT_REQUEST:
            if (resultCode == RESULT_OK) {
                // Get SMS message content
                String message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE);
                // Extract one-time code from the message and complete verification
                // `sms` contains the entire text of the SMS message, so you will need
                // to parse the string.
                String oneTimeCode = parseOneTimeCode(message); // define this function

                // send one time code to the server
            } else {
                // Consent canceled, handle the error ...
            }
            break;
    }
}

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