בקש אימות SMS באפליקציית Android

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

כדי להתחיל את זרימת אימות מספר הטלפון באפליקציית Android, אתה שולח את מספר הטלפון לשרת האימות שלך ומתקשר לממשק ה- API של Retriever SMS כדי להתחיל להאזין להודעת SMS המכילה קוד חד פעמי לאפליקציה שלך. לאחר קבלת ההודעה, אתה שולח את הקוד החד פעמי לשרת שלך כדי להשלים את תהליך האימות.

לפני שאתה מתחיל

כדי להכין את האפליקציה שלך, בצע את השלבים בסעיפים הבאים.

דרישות מוקדמות לאפליקציות

ודא שקובץ ה- build של האפליקציה שלך משתמש בערכים הבאים:

  • גרסת minSdk של 19 ומעלה
  • גרסת compileSdkVision של 28 ומעלה

הגדר את האפליקציה שלך

בקובץ build.gradle פרויקט ברמה שלך, כולל מאגר מייבן של גוגל ואת מאגר מרכזי מייבן בשני שלך buildscript ו allprojects סעיפים:

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

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

מוסיפים את בשירותי Google Play תלות עבור ה- API רטריבר SMS כדי שלך לבנות הקובץ Gradle של מודול , אשר נפוץ app/build.gradle :

dependencies {
  implementation 'com.google.android.gms:play-services-auth:19.2.0'
  implementation 'com.google.android.gms:play-services-auth-api-phone:17.5.1'
}

1. השג את מספר הטלפון של המשתמש

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

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

2. הפעל את רטריבר ה- 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 via 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 המכילה מחרוזת ייחודית המזהה את האפליקציה שלך.

3. שלח את מספר הטלפון לשרת שלך

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

השרת שלך יוצר הודעת אימות ושולח אותה באמצעות SMS למספר הטלפון שציינת. ראה בצע אימות באמצעות SMS על שרת .

4. קבל הודעות אימות

כאשר הודעת אימות מתקבלת על במכשיר המשתמש, שירותי Play משדרים במפורש האפליקציה שלכם SmsRetriever.SMS_RETRIEVED_ACTION כוונות, המכילה את הטקסט של ההודעה. השתמש BroadcastReceiver לקבל הודעת אימות זו.

בשנות ה BroadcastReceiver של onReceive המטפל, לקבל את הטקסט של הודעת האימות מהניצבים של כוונות:

/**
 * BroadcastReceiver to wait for SMS messages. This can be registered either
 * in the AndroidManifest or at runtime.  Should filter 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:
          // Get SMS message contents
          String message = (String) extras.get(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>

5. שלח את הקוד החד-פעמי מהודעת האימות לשרת שלך

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

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

אופציונלי: שמור את מספר הטלפון באמצעות Smart Lock for Passwords

לחלופין, לאחר שהמשתמש אימת את מספר הטלפון שלו, תוכל לבקש מהמשתמש לשמור את מספר הטלפון הזה באמצעות Smart Lock for Passwords כך שהוא יהיה זמין אוטומטית באפליקציות אחרות ובמכשירים אחרים מבלי שתצטרך להקליד או לבחור את מספר הטלפון שוב :

Credential credential = new Credential.Builder(phoneNumberString)
        .setAccountType("https://signin.example.com")  // a URL specific to the app
        .setName(displayName)  // optional: a display name if available
        .build();
Auth.CredentialsApi.save(apiClient, credential).setResultCallback(
            new ResultCallback() {
                public void onResult(Result result) {
                    Status status = result.getStatus();
                    if (status.isSuccess()) {
                        Log.d(TAG, "SAVE: OK");  // already saved
                    } else if (status.hasResolution()) {
                        // Prompt the user to save
                        status.startResolutionForResult(this, RC_SAVE);
                    }
                }
            });

לאחר מכן, לאחר שהמשתמש יתקין מחדש את האפליקציה או יתקין את האפליקציה במכשיר חדש, תוכל לאחזר את מספר הטלפון השמור מבלי לשאול את המשתמש שוב את מספר הטלפון שלו:

// On the next install, retrieve the phone number
mCredentialRequest = new CredentialRequest.Builder()
    .setAccountTypes("https://signin.example.com")  // the URL specific to the developer
    .build();
Auth.CredentialsApi.request(apiClient, mCredentialRequest).setResultCallback(
    new ResultCallback<CredentialRequestResult>() {
        public void onResult(CredentialRequestResult credentialRequestResult) {
            if (credentialRequestResult.getStatus().isSuccess()) {
                credentialRequestResult.getCredential().getId();  // this is the phone number
            }
        }
    });

// Then, initiate verification and sign the user in (same as original verification logic)