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

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

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

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

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

الخطوات التالية مطلوبة للوصول في وضع عدم الاتصال:

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

قبل البدء

قبل أن تتمكّن من دمج ميزة "تسجيل الدخول بحساب 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. من شاشة واجهات برمجة التطبيقات والخدمات & gt; بيانات الاعتماد في وحدة تحكم واجهة برمجة تطبيقات Google، نزِّل ملف client_secret.json لتطبيق الويب واحفظه في موقع يمكن للخادم الوصول إليه. سجِّل معرِّف العميل لبيانات الاعتماد للرجوع إليه لاحقًا.
  3. أعِد تشغيل تطبيقك من جهة الخادم ليكون جاهزًا لقبول الطلبات من تطبيق برامج الألعاب.

إجراء تسجيل الدخول على البرنامج

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

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

  1. أنشئ برنامج تسجيل دخول من خلال كائن GoogleSignInOptions. في GoogleSignInOptions.Builder لضبط تسجيل الدخول، يجب تحديد GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN.
  2. يجب أيضًا تحديد أنّ لعبتك تتطلّب رمز مصادقة للخادم الخلفي من خلال استدعاء طريقة GoogleSignInOptions.Builder.requestServerAuthCode() مع ضبط معرّف العميل للخادم. ستسترد رمز المصادقة لاحقًا من رموز الدخول على خادم الخلفية، كما هو موضح في الحصول على رمز مصادقة الخادم.
  3. استدعِ الطريقة GoogleSignIn.getClient() ومرِّر الخيارات التي سبق لك ضبطها. إذا نجحت المكالمة، تعرض واجهة برمجة تطبيقات تسجيل الدخول إلى Google نسخة افتراضية من 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 بالنيابة عن اللاعب، ويمكنك تخزين الرمز المميز للتحديث اختياريًا للحصول على رمز دخول جديد عند انتهاء صلاحية رمز الدخول.

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

/**
 * 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 من خادم خلفية نيابة عن مشغل تم تسجيل الدخول إليه، راجع تمكين الدخول من جانب الخادم.

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

لتسجيل خروج اللاعبين من لعبتك، يمكنك اتّباع طريقة signOut() على GoogleSignInClient. للحصول على مثال لمقتطف شفرة، راجع الخروج من المشغّل.

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

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

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

اللاعب

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

أصدقاء

تأكد من مراجعة دليل الأصدقاء الذي يفسّر الأصدقاء بمزيد من التفصيل.

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

الإنجازات

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

  • هل تريد الحصول على قائمة بالإنجازات الحالية؟ يُمْكِنُ إِجْرَاءْ مُكَالَمَة عَبْرَ تَطْبِيقْ إنجاز تعريفات .
  • ويمكنك دمج ذلك مع مكالمة إلى الإنجازات.list لمعرفة تلك التي فتحها اللاعب.
  • هل حقق اللاعب إنجازًا؟ استخدِم الإنجازات.
  • هل أحرز اللاعب تقدمًا نحو إنجاز جزئي؟ يمكنك استخدام الإنجازات.
  • هل تصحح أخطاء لعبة لم يتم إنتاجها بعد؟ حاوِل استدعاء nmentsments.reset أو الإنجازات.resetAll من واجهات برمجة تطبيقات الإدارة لإعادة ضبط الإنجازات إلى حالتها الأصلية.

لوحة الصدارة

تأكد من مراجعة دليل لوحات الصدارة، الذي يفسر لوحات الصدارة بمزيد من التفصيل.

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