היפוך האפליקציה ל-Android

קישור App Flip מבוסס-OAuth (App Flip) מכניס את אפליקציית Android שלכם אל תהליך הקישור של חשבון Google. תהליך מסורתי של קישור חשבונות מחייב שהמשתמש יזין את פרטי הכניסה שלו בדפדפן. השימוש ב-App Flip דוחה את המשתמש להיכנס לאפליקציה ל-Android, מה שמאפשר לכם למנף הרשאות. אם המשתמשים מחוברים לאפליקציה, הוא לא צריך להזין מחדש את פרטי הכניסה כדי לקשר את החשבון. כמות מינימלית של קוד נדרשים שינויים כדי להטמיע את App Flip באפליקציה ל-Android.

במסמך הזה נסביר איך לשנות את האפליקציה ל-Android כדי שתתמוך היפוך האפליקציות.

רוצה לנסות את הדוגמה?

אפליקציה לדוגמה לקישור של אפליקציות ההיפוך הדגמה של שילוב קישור חשבונות תואם App Flip ב-Android. שלך יכול להשתמש באפליקציה הזו כדי לאמת איך להגיב לכוונת רכישה נכנסת של האפליקציה מ: אפליקציות של Google לנייד.

האפליקציה לדוגמה מוגדרת מראש לשילוב עם App Flip Test Tool עבור ב-Android, שבו אפשר להשתמש כדי לאמת את השילוב של אפליקציה ל-Android עם האפליקציה צריך להפוך את האצבע לפני שמגדירים את קישור החשבונות ל-Google. האפליקציה הזו מדמה את Intent שמופעל על ידי אפליקציות של Google לנייד כש-App Flip מופעל.

איך זה עובד

כדי לבצע שילוב של App Flip, צריך לפעול לפי השלבים הבאים:

  1. Google app בודקת אם האפליקציה מותקנת במכשיר באמצעות שם החבילה.
  2. אפליקציית Google משתמשת בבדיקת חתימת חבילה כדי לאמת שההתקנה היא האפליקציה הנכונה.
  3. אפליקציית Google יוצרת כוונה להתחיל פעילות ייעודית באפליקציה שלכם. הכוונה הזו כוללת נתונים נוספים שנדרשים לקישור. הוא גם בודק כדי לבדוק אם האפליקציה שלך תומכת ב-App Flip על ידי טיפול ב-Intent הזה דרך מסגרת Android.
  4. האפליקציה שלכם מוודאת שהבקשה מגיעה מאפליקציית Google. כדי לעשות את זה, האפליקציה בודקת את חתימת החבילה ואת מזהה הלקוח שסופק.
  5. האפליקציה מבקשת קוד הרשאה משרת OAuth 2.0. ב בסוף התהליך הזה, הוא יחזיר קוד הרשאה או שגיאה אפליקציית Google.
  6. אפליקציית Google מאחזרת את התוצאה וממשיכה עם קישור החשבונות. אם המיקום מספק קוד הרשאה, המרת האסימון מתבצעת שרת לשרת, בדיוק כמו בקישור OAuth מבוסס-דפדפן. .

שינוי האפליקציה ל-Android לתמיכה ב-App Flip

כדי לתמוך ב-App Flip, צריך לבצע את השינויים הבאים בקוד באפליקציה ל-Android:

  1. הוספת <intent-filter> לקובץ AndroidManifest.xml עם פעולה מחרוזת שתואמת לערך שהזנת בשדה App Flip Intent.

    <activity android:name="AuthActivity">
      <!-- Handle the app flip intent -->
      <intent-filter>
        <action android:name="INTENT_ACTION_FROM_CONSOLE"/>
        <category android:name="android.intent.category.DEFAULT"/>
      </intent-filter>
    </activity>
    
  2. לאמת את החתימה של אפליקציית השיחות.

    private fun verifyFingerprint(
            expectedPackage: String,
            expectedFingerprint: String,
            algorithm: String
    ): Boolean {
    
        callingActivity?.packageName?.let {
            if (expectedPackage == it) {
                val packageInfo =
                    packageManager.getPackageInfo(it, PackageManager.GET_SIGNATURES)
                val signatures = packageInfo.signatures
                val input = ByteArrayInputStream(signatures[0].toByteArray())
    
                val certificateFactory = CertificateFactory.getInstance("X509")
                val certificate =
                    certificateFactory.generateCertificate(input) as X509Certificate
                val md = MessageDigest.getInstance(algorithm)
                val publicKey = md.digest(certificate.encoded)
                val fingerprint = publicKey.joinToString(":") { "%02X".format(it) }
    
                return (expectedFingerprint == fingerprint)
            }
        }
        return false
    }
    
  3. יש לחלץ את מזהה הלקוח מהפרמטרים של Intent ולוודא שהלקוח המזהה תואם לערך הצפוי.

    private const val EXPECTED_CLIENT = "<client-id-from-actions-console>"
    private const val EXPECTED_PACKAGE = "<google-app-package-name>"
    private const val EXPECTED_FINGERPRINT = "<google-app-signature>"
    private const val ALGORITHM = "SHA-256"
    ...
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        val clientId = intent.getStringExtra("CLIENT_ID")
    
        if (clientId == EXPECTED_CLIENT &&
            verifyFingerprint(EXPECTED_PACKAGE, EXPECTED_FINGERPRINT, ALGORITHM)) {
    
            // ...authorize the user...
        }
    }
    
  4. לאחר קבלת ההרשאה, יש להחזיר את קוד ההרשאה שהתקבל ל-Google.

    // Successful result
    val data = Intent().apply {
        putExtra("AUTHORIZATION_CODE", authCode)
    }
    setResult(Activity.RESULT_OK, data)
    finish()
    
  5. אם התרחשה שגיאה, צריך להחזיר תוצאת שגיאה.

    // Error result
    val error = Intent().apply {
        putExtra("ERROR_TYPE", 1)
        putExtra("ERROR_CODE", 1)
        putExtra("ERROR_DESCRIPTION", "Invalid Request")
    }
    setResult(-2, error)
    finish()
    

התוכן של כוונת ההשקה

כוונת הרכישה ב-Android שמפעילה את האפליקציה כוללת את השדות הבאים:

  • CLIENT_ID (String): בוצע רישום של client_id של Google במסגרת האפליקציה שלך.
  • SCOPE (String[]): רשימה של היקפים מבוקשים.
  • REDIRECT_URI (String): כתובת ה-URL להפניה אוטומטית.

התוכן של נתוני התגובות

הנתונים שמוחזרים לאפליקציית Google מוגדרים באפליקציה שלך בהתקשרות אל setResult(). הנתונים האלה כוללים:

  • AUTHORIZATION_CODE (String): הערך של קוד ההרשאה.
  • resultCode (int): דיווח על ההצלחה או הכישלון של התהליך, וגם מקבל אחד מהערכים הבאים:
    • Activity.RESULT_OK: סימן להצלחה. מוחזר קוד הרשאה.
    • Activity.RESULT_CANCELLED: אותות שהמשתמש ביטל את תהליך האימות. במקרה כזה, אפליקציית Google תנסה לקשר את החשבונות באמצעות את כתובת האתר להרשאה שלך.
    • -2: מציין שאירעה שגיאה. סוגים שונים של שגיאות נפרט בהמשך.
  • ERROR_TYPE (int): סוג השגיאה, שמשתמש באחת מהאפשרויות הבאות ערכים:
    • 1: שגיאה שניתנת לשחזור: אפליקציית Google תנסה לקשר את החשבון באמצעות את כתובת ה-URL של ההרשאה.
    • 2: שגיאה שאי אפשר לשחזר: אפליקציית Google מבטלת את קישור החשבון.
    • 3: פרמטרים לא חוקיים או חסרים של בקשה.
  • ERROR_CODE (int): מספר שלם שמייצג את אופי השגיאה. לראות המשמעות של כל קוד שגיאה, טבלת קודי שגיאה.
  • ERROR_DESCRIPTION (String, אופציונלי): הודעת סטטוס שקריאה לאנשים שמתאר את השגיאה.

צפוי ערך עבור ה-AUTHORIZATION_CODE כאשר resultCode == Activity.RESULT_OK. בכל שאר המקרים, הערך של השדה AUTHORIZATION_CODE צריך להיות ריק. אם הערך שלו הוא resultCode == -2, אז הערך של ערך ERROR_TYPE צפוי להתאכלס.

טבלה של קודי שגיאות

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

קוד שגיאה משמעות ניתנת לשחזור לא ניתן לביטול
1 INVALID_REQUEST
2 NO_INTERNET_CONNECTION
3 OFFLINE_MODE_ACTIVE
4 CONNECTION_TIMEOUT
5 INTERNAL_ERROR
6 AUTHENTICATION_SERVICE_UNAVAILABLE
8 CLIENT_VERIFICATION_FAILED
9 INVALID_CLIENT
10 INVALID_APP_ID
11 INVALID_REQUEST
12 AUTHENTICATION_SERVICE_UNKNOWN_ERROR
13 AUTHENTICATION_DENIED_BY_USER
14 CANCELLED_BY_USER
15 FAILURE_OTHER
16 USER_AUTHENTICATION_FAILED

עבור כל קודי השגיאה, צריך להחזיר את תוצאת השגיאה דרך setResult אל מוודאים שהחלופה המתאימה מופעלת.