Yêu cầu đồng ý một lần để đọc mã xác minh qua SMS

Trang này mô tả cách sử dụng SMS User Consent API để yêu cầu sự đồng ý của người dùng đọc một tin nhắn xác minh SMS. Nếu người dùng đồng ý, API sẽ trả về nội dung của tin nhắn. Từ đó, bạn có thể lấy mã xác minh và hoàn tất quy trình xác minh.

Cài đặt các phần phụ thuộc

Thêm thành phần xác thực Dịch vụ Play vào tệp build.gradle của ứng dụng:

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. Lấy số điện thoại của người dùng

Nếu bạn không có số điện thoại của người dùng, hãy yêu cầu họ cung cấp số điện thoại trước khi bắt đầu quy trình xác minh bằng SMS.

Bạn có thể lấy số điện thoại của người dùng theo cách phù hợp với ứng dụng của mình. Hãy cân nhắc sử dụng trình chọn gợi ý Smart Lock cho mật khẩu để giúp người dùng điền số điện thoại nếu thông tin đó không bắt buộc để tạo tài khoản của người dùng. Cách sử dụng bộ chọn gợi ý:

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. Bắt đầu nghe tin nhắn đến

Tiếp theo, hãy gọi phương thức startSmsUserConsent() của SMS User Consent API để bắt đầu theo dõi các tin nhắn đến. Nếu bạn biết số điện thoại mà tin nhắn SMS sẽ được gửi đến, hãy chỉ định số điện thoại đó (nếu không, hãy truyền null). Bằng cách này, SMS User Consent API sẽ chỉ kích hoạt trên các tin nhắn từ số này.

Cách bắt đầu nghe:

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

Sau khi lắng nghe tin nhắn SMS đến, bạn có thể yêu cầu hệ thống xác minh gửi mã xác minh đến số điện thoại của người dùng mà bạn đã nhận được ở bước đầu tiên.

Trong 5 phút tiếp theo, khi thiết bị nhận được một tin nhắn SMS có chứa mã một lần, Dịch vụ Play sẽ truyền tin đến ứng dụng của bạn một ý định nhắc người dùng cấp quyền đọc tin nhắn. Một thông báo chỉ kích hoạt thông báo truyền tin nếu đáp ứng các tiêu chí sau:

  • Thông báo này chứa một chuỗi gồm 4 đến 10 ký tự chữ và số, trong đó có ít nhất một chữ số.
  • Nếu bạn chỉ định số điện thoại của người gửi, thì tin nhắn đó được gửi bằng số điện thoại đó.

Xử lý các thông báo này bằng một bộ nhận tín hiệu truyền tin có quyền SEND_PERMISSION và phản hồi các ý định SMS_RETRIEVED_ACTION. Cách tạo và đăng ký bộ nhận tín hiệu truyền tin:

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

Bằng cách bắt đầu một hoạt động cho EXTRA_CONSENT_INTENT, bạn sẽ nhắc người dùng cấp Quyền một lần để đọc nội dung của thông báo.

3. Nhận mã xác minh qua tin nhắn

Trong phương thức onActivityResult(), hãy xử lý phản hồi của người dùng đối với yêu cầu cấp quyền của bạn. Nếu nhận được mã kết quả RESULT_OK, tức là người dùng đã cấp quyền đọc nội dung của tin nhắn và bạn có thể lấy văn bản tin nhắn từ ý định.

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

Sau khi có văn bản tin nhắn, bạn có thể phân tích mã xác minh và tự động điền vào biểu mẫu hoặc hoàn tất quy trình xác minh.