تفعيل ميزة "الوصول من جهة الخادم" إلى "خدمات ألعاب Google Play"

إذا كانت لعبتك تستخدم خادم خلفية، ننصحك باستخدام تسجيل الدخول بحساب Google لمصادقة اللاعبين وتمرير هوية المشغل بشكل آمن إلى خادم الخلفية. وهذا من شأنه أيضًا تمكين لعبتك لاسترداد هوية اللاعب وبياناته الأخرى بأمان بدون إمكانية التلاعب بالجهاز أثناء المرور

في هذا السيناريو، تطلب اللعبة من اللاعب تسجيل الدخول إلى "خدمات ألعاب Google Play" كالمعتاد. عندما سجّل اللاعب الدخول بنجاح، يحتوي الكائن GoogleSignInAccount على رمز خاص يُستخدم لمرة واحدة. (يُسمّى رمز مصادقة الخادم) الذي يمرّره العميل إلى الخادم. ثم، على الخادم، قم بتبادل رمز مصادقة الخادم لرمز OAuth 2.0 المميز الذي يمكن للخادم استخدامه لإجراء اتصالات واجهة برمجة التطبيقات لخدمات ألعاب Google Play

للحصول على إرشادات إضافية حول إضافة تسجيل الدخول في ألعابك، يمكنك الاطّلاع على سجِّل الدخول إلى "ألعاب Android".

للاطّلاع على نموذج رمز مفصل يوضّح كيفية استخدام "تسجيل الدخول بحساب Google" لمصادقة المشغّلات، يُرجى مراجعة نموذج واحد (clientserverskeleton) على GitHub.

الخطوات التالية مطلوبة للوصول إلى المحتوى بلا إنترنت:

  1. في Google Play Console: أنشِئ بيانات اعتماد لخادم لعبتك. تشير رسالة الأشكال البيانية سيكون نوع بيانات الاعتماد الخاص بعميل OAuth هو "الويب".
  2. في تطبيق Android: كجزء من تسجيل الدخول، اطلب رمز مصادقة الخادم بيانات اعتماد الخادم، وتمريرها إلى الخادم.
  3. على خادم اللعبة: استبدال رمز مصادقة الخادم للدخول عبر بروتوكول OAuth باستخدام خدمات المصادقة من Google، ثم استخدم هذا الرقم لطلب واجهات برمجة تطبيقات RST في "خدمات ألعاب Play"

قبل البدء

قبل دمج "تسجيل الدخول بحساب Google" في لعبتك، عليك أولاً إضافة لعبتك إلى Google Play Console كما هو موضّح في إعداد "خدمات ألعاب Google Play":

إنشاء تطبيق ويب مرتبط من جهة الخادم للعبتك

لا توفّر "خدمات ألعاب Google Play" خلفية لألعاب الويب. ومع ذلك، فهي تتيح دعم خادم الخلفية لخادم ألعاب Android.

إذا كنت تريد استخدام صفحة واجهات برمجة تطبيقات REST الخاصة بـ "خدمات ألعاب Google Play" في التطبيق من جهة الخادم، اتّبِع الخطوات التالية:

  1. يمكنك إنشاء تطبيق ويب مرتبط للعبتك في قسم التطبيقات المرتبطة من Google Play Console لاحظ أن لا يتم استخدام launch_url لهذا المسار ويمكن تركه فارغًا.
  2. للحصول على معلومات بيانات الاعتماد الخاصة بتطبيقك، اتّبِع الخطوات التالية:
    1. من لعبتك في Google Play Console، انقر على تفاصيل اللعبة.
    2. مرِّر للأسفل وصولاً إلى قسم مشروع وحدة تحكم واجهة برمجة التطبيقات وانقر على الرابط. لمشروع وحدة تحكم واجهة برمجة التطبيقات.
    3. من واجهات برمجة التطبيقات الخدمات > شاشة بيانات الاعتماد في Google API وحدة التحكم، يمكنك تنزيل ملف client_secret.json لتطبيق الويب واحفظه في مكان يمكن لخادمك الوصول إليه. تسجيل بيانات العميل رقم تعريف بيانات الاعتماد للرجوع إليها لاحقًا.
  3. أعِد تشغيل تطبيقك من جهة الخادم كي يكون جاهزًا لقبول الطلبات من التطبيق العميل الخاص باللعبة.

جارٍ تسجيل الدخول على العميل

الفئة GoogleSignInClient هي نقطة الإدخال الرئيسية لاسترداد حساب المستخدم إلى مشغّل الفيديو، وتسجيل الدخول إلى المشغّل إذا لم يسبق له ذلك على تطبيقك في الخاص بك.

لإنشاء برنامج تسجيل دخول، يُرجى اتّباع الخطوات التالية:

  1. أنشِئ برنامج تسجيل دخول من خلال عنصر GoogleSignInOptions. في جلسة المعمل، GoogleSignInOptions.Builder لضبط إعدادات تسجيل الدخول، عليك تحديد GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN
  2. عليك أيضًا تحديد أنّ لعبتك تتطلّب مصادقة. لخادم الخلفية من خلال استدعاء GoogleSignInOptions.Builder.requestServerAuthCode() بمعرِّف عميل الخادم باعتباره . ستسترد رمز المصادقة لاحقًا لرموز الدخول على خادم الخلفية، كما هو موضّح في الحصول على رمز مصادقة الخادم.
  3. يمكنك استدعاء الطريقة GoogleSignIn.getClient() وتمرير الخيارات التي سبق لك ضبطها. إذا كانت المكالمة بنجاح، تعرض Google Sign-In API مثيلاً لـ GoogleSignInClient.
  4. بعد الحصول على مثيل GoogleSignInClient، عليك المتابعة لتسجيل الدخول إلى المشغّل. بدون تنبيه من onResume() الخاص بالنشاط، كما هو موضَّح في يتم تسجيل الدخول بدون صوت.

وفي ما يلي مثال لذلك:

private static final int RC_SIGN_IN = 9001;
private GoogleSignInClient mGoogleSignInClient;

private void startSignInForAuthCode() {

  // Client ID for your backend server.
  String webClientId = getString(R.string.webclient_id);

  GoogleSignInOptions signInOption = new
      GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
      .requestServerAuthCode(webClientId)
      .build();

  GoogleSignInClient signInClient = GoogleSignIn.getClient(this, signInOption);
  Intent intent = signInClient.getSignInIntent();
  startActivityForResult(intent, RC_SIGN_IN);
}

الحصول على رمز مصادقة الخادم

لاسترداد رمز مصادقة الخادم الذي يمكن للعبتك استخدامه لرموز الدخول على خادم الخلفية، الِاتِّصَالْ بِـ getServerAuthCode() على GoogleSignInAccount الذي يتم تسجيله من خلال "تسجيل الدخول باستخدام حساب Google" عند تسجيل الدخول بنجاح إلى اللاعب.

وفي ما يلي مثال لذلك:


// Auth code to send to backend server.
private String mServerAuthCode;

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  if (requestCode == RC_SIGN_IN) {
    GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
    if (result.isSuccess()) {
      mServerAuthCode = result.getSignInAccount().getServerAuthCode();
    } else {
      String message = result.getStatus().getStatusMessage();
      if (message == null || message.isEmpty()) {
        message = getString(R.string.signin_other_error);
      }
      new AlertDialog.Builder(this).setMessage(message)
          .setNeutralButton(android.R.string.ok, null).show();
    }
  }
}

استبدل رمز مصادقة الخادم برمز الدخول على الخادم

أرسِل رمز مصادقة الخادم إلى خادم الخلفية للحصول على رموز الدخول وإعادة التحميل. استخدِم رمز الدخول لطلب واجهة برمجة التطبيقات Google Play Games Services API نيابةً عن اللاعب، ويمكنك اختيار تخزين الرمز المميز للتحديث للحصول على رمز دخول جديد عند انتهاء صلاحية رمز الدخول.

يوضح مقتطف الرمز التالي كيفية تنفيذ الرمز من جانب الخادم في Java لتبادل رمز مصادقة الخادم برموز الدخول. من المهم باستخدام نموذج تطبيق clientserverskeleton:

/**
 * Exchanges the authcode for an access token credential.  The credential
 * is the associated with the given player.
 *
 * @param authCode - the non-null authcode passed from the client.
 * @param player   - the player object which the given authcode is
 *                 associated with.
 * @return the HTTP response code indicating the outcome of the exchange.
 */
private int exchangeAuthCode(String authCode, Player player) {
try {

    // The client_secret.json file is downloaded from the Google API
    // console.  This is used to identify your web application.  The
    // contents of this file should not be shared.
    //
    File secretFile = new File("client_secret.json");

    // If we don't have the file, we can't access any APIs, so return
    // an error.
    if (!secretFile.exists()) {
        log("Secret file : " + secretFile
                .getAbsolutePath() + "  does not exist!");
        return HttpServletResponse.SC_FORBIDDEN;
    }

    GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(
            JacksonFactory.getDefaultInstance(), new
            FileReader(secretFile));

    // Extract the application id of the game from the client id.
    String applicationId = extractApplicationId(clientSecrets
            .getDetails().getClientId());

    GoogleTokenResponse tokenResponse =
            new GoogleAuthorizationCodeTokenRequest(
            HTTPTransport,
            JacksonFactory.getDefaultInstance(),
            "https://oauth2.googleapis.com/token",
            clientSecrets.getDetails().getClientId(),
            clientSecrets.getDetails().getClientSecret(),
            authCode,
            "")
            .execute();

    log("hasRefresh == " + (tokenResponse.getRefreshToken() != null));
    log("Exchanging authCode: " + authCode + " for token");
    Credential credential = new Credential
            .Builder(BearerToken.authorizationHeaderAccessMethod())
            .setJsonFactory(JacksonFactory.getDefaultInstance())
            .setTransport(HTTPTransport)
            .setTokenServerEncodedUrl("https://www.googleapis.com/oauth2/v4/token")
            .setClientAuthentication(new HttpExecuteInterceptor() {
                @Override
                public void intercept(HttpRequest request)
                        throws IOException {
                        }
            })
            .build()
            .setFromTokenResponse(tokenResponse);

    player.setCredential(credential);

    // Now that we have a credential, we can access the Games API.
    PlayGamesAPI api = new PlayGamesAPI(player, applicationId,
            HTTPTransport, JacksonFactory.getDefaultInstance());

    // Call the verify method, which checks that the access token has
    // access to the Games API, and that the player id used by the
    // client matches the playerId associated with the accessToken.
    boolean ok = api.verifyPlayer();

    // Call a Games API on the server.
    if (ok) {
        ok = api.updatePlayerInfo();
        if (ok) {
            // persist the player.
            savePlayer(api.getPlayer());
        }
    }

    return ok ? HttpServletResponse.SC_OK :
            HttpServletResponse.SC_INTERNAL_SERVER_ERROR;

  } catch (IOException e) {
    e.printStackTrace();
  }
  return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
}

لمزيد من المعلومات حول الوصول إلى واجهات Google APIs من خادم خلفية بالنيابة عن مشغّل تم تسجيل الدخول إليه، يُرجى اتّباع الخطوات التالية: يُرجى الاطّلاع على تفعيل الوصول من جهة الخادم.

التعامل مع تسجيل خروج اللاعب

لتسجيل خروج اللاعبين من لعبتك، عليك طلب إجراء signOut() على GoogleSignInClient. بالنسبة إلى مثال مقتطف الرمز، يُرجى الاطّلاع على تسجيل خروج اللاعب

طلب واجهات برمجة تطبيقات REST من الخادم

يُرجى الرجوع إلى واجهات برمجة تطبيقات REST لخدمات "ألعاب Google Play" وصف كامل لطلبات البيانات من واجهة برمجة التطبيقات المتاحة.

في ما يلي أمثلة على طلبات واجهة برمجة التطبيقات REST API التي قد تكون مفيدة:

اللاعب

  • هل تريد الحصول على رقم تعريف اللاعب الذي سجّل الدخول وبيانات الملف الشخصي؟ الاتصال بـ Players.get مع 'me' كرقم التعريف.

أصدقاء

احرص على مراجعة دليل الأصدقاء الذي يشرح صفحة "الأصدقاء" بمزيد من التفصيل.

  • هل تريد استرداد قائمة أصدقاء اللاعب؟ يمكنك الاتصال بـ Players.list عبر 'friends_all' باعتباره collection.
  • تحقق مما إذا كان بإمكانك الوصول إلى قائمة الأصدقاء؟ اتصل على Players.get مقابل me، و راجِع الحقل profileSettings.friendsListVisibility في الردّ.

الإنجازات

احرص على مراجعة دليل الإنجازات الذي يوضّح الإنجازات. بمزيد من التفصيل.

  • هل تريد الحصول على قائمة بالإنجازات الحالية؟ ويمكنك إجراء مكالمة إلى AchievementDefinitions.list.
  • ويمكنك دمج هذه المعلومات من خلال مكالمة إلى Achievements.list لمعرفة الأهداف التي حقّقها اللاعب.
  • هل حقق اللاعب إنجازًا؟ استخدِم Achievements.unlock لفتح قفل الجهاز.
  • هل أحرز اللاعب تقدمًا نحو إنجاز جزئي؟ استخدِم Achievements.increment من أجل الإبلاغ عن مستوى التقدّم (ومعرفة ما إذا كان اللاعب قد فتح قفله)
  • هل تُجري تصحيح أخطاء لعبة لم يتم إصدارها بعد؟ محاولة الاتصال Achievements.reset أو Achievements.resetAll من واجهة برمجة تطبيقات الإدارة لإعادة تعيين الإنجازات إلى حالتها الأصلية.

أشكال ليدربورد

احرص على مراجعة دليل لوحات الصدارة الذي يشرح قوائم الصدارة بمزيد من التفصيل.

  • هل تريد الحصول على قائمة بجميع لوحات النتائج في اللعبة؟ يمكنك إجراء مكالمة مع Leaderboards.list.
  • هل انتهى اللاعب من إحدى الألعاب؟ ويمكنك إرسال نتيجته إلى Scores.submit ومعرفة ما إذا كان هذه نتيجة عالية جديدة.
  • هل تريد عرض لوحة صدارة؟ احصل على البيانات من Scores.list واعرضها على المستخدم.
  • استخدِم Scores.listWindow للعثور على مجموعة من النتائج القريبة من أعلى نتيجة للمستخدم.
  • للحصول على مزيد من المعلومات حول نتيجة اللاعب في لوحة صدارة معينة (على سبيل المثال، إذا كان أحد اللاعبين ضمن أعلى 12% من بين جميع اللاعبين)، واستدعِ Scores.get.
  • هل تعمل على تصحيح الأخطاء في لعبة؟ حاوِل الاتصال بـ Scores.reset من "الإدارة". واجهات برمجة التطبيقات لإعادة ضبط جميع النتائج لهذا اللاعب من لوحة صدارة معيَّنة