التطبيق العكسي لنظام التشغيل iOS

يؤدي استخدام ميزة "قلب التطبيقات" (App Flip) المستنِد إلى بروتوكول OAuth إلى فتح تطبيق iOS من أحد تطبيقات Google. لمساعدة مستخدم تطبيق Google على ربط حسابه بسهولة أكبر. عليك إجراء تغييرات طفيفة على رمز تطبيق iOS لتنفيذ هذه الميزة.

ستتعرّف في هذا المستند على كيفية تعديل تطبيق iOS لدعم ميزة App Flip.

تجربة النموذج

نموذج تطبيق ميزة "قلب التطبيق" تعرض عملية دمج لربط الحساب على نظام iOS يتوافق مع App Flip. يمكنك استخدام هذا التطبيق للتحقّق من طريقة الردّ على رسالة App Flip واردة عامة. من تطبيقات الأجهزة الجوّالة من Google.

تم ضبط نموذج التطبيق مسبقًا للدمج مع أداة اختبار قلب التطبيق). iOS، الذي يمكنك استخدامه للتحقّق من تكامل تطبيق iOS مع ميزة App Flip قبل يمكنك إعداد ربط الحساب بـ Google. يحاكي هذا التطبيق الرابط العام. يتم تشغيلها بواسطة تطبيقات Google المتوافقة مع الأجهزة الجوّالة عند تفعيل ميزة "قلب التطبيقات".

آلية العمل

في ما يلي خطوات العملية التي يتّخذها تطبيق Google وتطبيقك عند يحدث قلب التطبيق:

  1. يحاول تطبيق Google فتح الرابط العام لتطبيقك. من الممكن افتح التطبيق إذا كان مثبّتًا على جهاز المستخدم ومرتبطًا الرابط العام. راجِع إتاحة الروابط العامة لمعرفة التفاصيل.

  2. يتحقّق تطبيقك من ترميز المَعلمتَين client_id وredirect_uri. في عنوان URL الوارد مع الرابط العام المتوقع لـ Google.

  3. يطلب تطبيقك رمز تفويض من خادم OAuth2. في النهاية يعرض التطبيق رمز تفويض أو خطأ تطبيق Google. وللقيام بذلك، يتم فتح رابط Google العام مع ملحق المَعلمات لرمز التفويض أو الخطأ.

  4. يعالج تطبيق Google الرابط العام الوارد من Google ويستمر في بقية التدفق. إذا تم تقديم رمز تفويض، سيتم على الفور. يحدث تبادل الرموز المميزة بين الخوادم، بالطريقة نفسها وهو ما يحدث في تدفق ربط OAuth المستند إلى المتصفح. إذا كان رمز الخطأ يستمر تدفق الربط مع الخيارات البديلة.

تعديل تطبيق iOS لدعم ميزة "قلب التطبيقات"

لإتاحة ميزة "قلب التطبيقات"، عليك إجراء التغييرات التالية على الرمز في تطبيق iOS:

  1. استخدِم الاسم المعرِّف "NSUserActivityTypeBrowsingWeb" في ميزة "تفويض التطبيقات".
  2. التقاط المَعلمتَين redirect_uri وstate من عنوان URL لاستخدامهما لاحقًا
  3. تأكَّد من تطابق redirect_uri مع هذا التنسيق:
    https://oauth-redirect.googleusercontent.com/a/GOOGLE_APP_BUNDLE_ID
    https://oauth-redirect-sandbox.googleusercontent.com/a/GOOGLE_APP_BUNDLE_ID
  4. تحقَّق من تطابُق معرِّف العميل مع القيمة المتوقَّعة. استخدِم ما يلي: نموذج التعليمات البرمجية:

    func application(_ application: UIApplication,
                     continue userActivity: NSUserActivity,
                     restorationHandler: @escaping ([Any]?) -> Void) -> Bool
    {
        guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
            let incomingURL = userActivity.webpageURL,
            let components = URLComponents(url: incomingURL, resolvingAgainstBaseURL: false),
            let params = components.queryItems else {
                return false
        }
    
        if let clientId = params.filter({$0.name == "client_id"}).first?.value,
            let state = params.filter({$0.name == "state"}).first?.value,
            let redirectUri = params.filter({$0.name == "redirect_uri"}).first?.value {
    
            // Save the redirect_uri and state for later...
    
            // Verify the client id
            return (clientId == GOOGLE_CLIENT_ID)
        } else {
            // Missing required parameters
            return false
        }
    }
    
  5. بعد نجاح التفويض، اطلب معرّف الموارد المنتظم (URI) لإعادة التوجيه مع الحصول على الإذن الرمز. استخدِم نموذج الرمز البرمجي التالي:

    func returnAuthCode(code: String, state: String, redirectUri: String) {
        var redirectURL = URL(string: redirectUri)
        var components = URLComponents(url: redirectURL, resolvingAgainstBaseURL: false)
    
        // Return the authorization code and original state
        let paramAuthCode = URLQueryItem(name: "code", value: code)
        let paramState = URLQueryItem(name: "state", value: state)
        components?.queryItems = [paramAuthCode, paramState]
        if let resultURL = components?.url {
            UIApplication.shared.open(
                resultURL,
                options: [UIApplicationOpenURLOptionUniversalLinksOnly : true],
                completionHandler: nil)
        }
    }
    
  6. إذا حدث خطأ، أرفِق نتيجة خطأ بمعرّف الموارد المنتظم (URI) لإعادة التوجيه بدلاً من ذلك. استخدِم نموذج الرمز البرمجي التالي:

    func returnError(redirectUri: String) {
        var redirectURL = URL(string: redirectUri)
        var components = URLComponents(url: redirectURL, resolvingAgainstBaseURL: false)
    
        // Return the authorization code and original state
        let paramError = URLQueryItem(name: "error", value: "invalid_request")
        let paramDescription = URLQueryItem(name: "error_description", value: "Invalid Request")
        components?.queryItems = [paramError, paramDescription]
        if let resultURL = components?.url {
            UIApplication.shared.open(
                resultURL,
                options: [UIApplicationOpenURLOptionUniversalLinksOnly : true],
                completionHandler: nil)
        }
    }
    

عند فتح هذا التطبيق من خلال تطبيق Google، يتضمّن الرابط العام لتطبيقك ما يلي: مَعلمات طلب البحث:

  • client_id (String): Google client_id المسجَّل ضمن تطبيقك.
  • scope (List of String): قائمة بالنطاقات المفصولة بمسافات مطلوبة
  • state (String): رقم تعريف غير تستخدمه Google للتحقّق من أنّ التفويض هي استجابة لطلب Google الصادر.
  • redirect_uri (String): رابط Google العام. "قلب" معرّف الموارد المنتظم (URI) المطلوب فتحه تطبيق Google واجتياز النتائج

المَعلمات المستخدَمة عند عرض نتيجة التفويض بنجاح:

  • code (String): قيمة رمز التفويض، في حال توفّرها.
  • state (String): القيمة الدقيقة التي يتم تلقّيها من الرابط العام الوارد

المَعلمات التي يتم استخدامها عند عرض نتيجة التفويض بشكل غير ناجح:

  • error (String)، مع القيم التالية:

    • cancelled: خطأ يمكن إصلاحه. سيحاول تطبيق Google استخدام الحساب باستخدام عنوان URL للتفويض. بعض الأمثلة هي فشل المستخدم لتسجيل الدخول، أو عدم اتصال الجهاز بالإنترنت أو انتهاء مهلة الاتصال.
    • unrecoverable: خطأ غير قابل للإصلاح. على سبيل المثال، يحاول المستخدم الربط بحساب غير مفعَّل.سيلغي تطبيق Google ربط الحساب.
    • invalid_request: معلَمات الطلب غير صالحة أو غير متوفّرة يمكن إصلاح هذا الخطأ. سيحاول تطبيق Google ربط الحسابات باستخدام عنوان URL للتفويض.
    • access_denied: يرفض المستخدم طلب الموافقة. هذا خطأ لا يمكن إصلاحه؛ يلغي تطبيق Google الربط.
  • error_description (String، اختياري): رسالة خطأ سهلة الاستخدام

بالنسبة إلى جميع أنواع الأخطاء، يجب عرض بيانات الاستجابة على REDIRECT_URI للتأكّد من ترتيب الإجراء الاحتياطي المناسب.

تعديل نقطة نهاية التفويض لإتاحة استخدام ميزة "قلب التطبيقات"

يمكنك ضبط النظام الأساسي لقبول الطلبات باستخدام عناوين URL لإعادة التوجيه لميزة App Flip من Google:

  • تطبيق Google Home
    https://oauth-redirect.googleusercontent.com/a/com.google.Chromecast.dev
    https://oauth-redirect.googleusercontent.com/a/com.google.Chromecast.enterprise
    https://oauth-redirect.googleusercontent.com/a/com.google.Chromecast
    https://oauth-redirect-sandbox.googleusercontent.com/a/com.google.Chromecast.dev
    https://oauth-redirect-sandbox.googleusercontent.com/a/com.google.Chromecast.enterprise
    https://oauth-redirect-sandbox.googleusercontent.com/a/com.google.Chromecast
    
  • تطبيق "مساعد Google"
    https://oauth-redirect.googleusercontent.com/a/com.google.OPA.dev
    https://oauth-redirect.googleusercontent.com/a/com.google.OPA.enterprise
    https://oauth-redirect.googleusercontent.com/a/com.google.OPA
    https://oauth-redirect-sandbox.googleusercontent.com/a/com.google.OPA.dev
    https://oauth-redirect-sandbox.googleusercontent.com/a/com.google.OPA.enterprise
    https://oauth-redirect-sandbox.googleusercontent.com/a/com.google.OPA
    

تأكّد من أنّ client_id وعنوان URL المحدَّدين من خلال المَعلمة redirect_uri تتطابق مع القيم المتوقعة عند تلقي طلب. إذا كانت عملية التحقّق من العميل الأخطاء، يمكنك إرجاع الخطأ invalid_request إلى redirect_uri.