בקשת הסכמה חד-פעמית לקריאת קוד אימות ב-SMS

בדף הזה מוסבר איך להשתמש ב-SMS User Consent API כדי לבקש את הסכמת המשתמשים לקריאה של הודעת אימות אחת ב-SMS. אם המשתמש מביע הסכמה, ה-API יחזיר את הטקסט של ההודעה, שממנו תוכלו לקבל את קוד האימות ולהשלים את תהליך האימות.

יחסי תלות של התקנות

יש לכלול את רכיב ההרשאה של Play Services בקובץ 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. איתור מספר הטלפון של המשתמש

אם מספר הטלפון של המשתמש לא נמצא ברשותכם, תוכלו לבקש אותו לפני שתתחילו תהליך אימות ב-SMS.

תוכלו למצוא את מספר הטלפון של המשתמשים באופן שמתאים לאפליקציה שלכם. כדאי להשתמש בבורר הרמזים של 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
            }
        // ...
    }
}

Java

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 כדי להתחיל להאזין להודעות נכנסות. אם ידוע לך מהו מספר הטלפון שממנו תישלח הודעת ה-SMS, עליך לציין אותו (אחרת, צריך להעביר את null). כך, ממשק ה-API של הסכמה למשתמשים ב-SMS יופעל רק בהודעות שנשלחות מהמספר הזה.

כדי להתחיל להאזין:

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 */)

Java

// 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 */);

כשאתם מאזינים להודעות SMS נכנסות, מערכת האימות יכולה לשלוח את קוד האימות למספר הטלפון של המשתמש, שאותו קיבלתם בשלב הראשון.

במשך חמש הדקות הבאות, כשהמכשיר יקבל הודעת SMS שמכילה קוד חד-פעמי, אפליקציית Play Services ישדרה לאפליקציה כוונה לבקש מהמשתמש הרשאה לקרוא את ההודעה. הודעה מפעילה את השידור רק אם היא עומדת בקריטריונים הבאים:

  • ההודעה מכילה מחרוזת אלפאנומרית בת 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)
}

Java

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, המשתמש העניק הרשאה לקרוא את תוכן ההודעה, ואפשר לקבל את טקסט ההודעה מתוך Intent.

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

Java

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

כשתקבלו את הטקסט של ההודעה, תוכלו לנתח את קוד האימות ולמלא את הטופס באופן אוטומטי או להשלים את תהליך האימות בדרך אחרת.