توصیه میکنیم از PgsGamesSignInClient برای احراز هویت بازیکنان و انتقال ایمن هویت بازیکن به سرور backend استفاده کنید. این امر به بازی شما امکان میدهد تا هویت و سایر دادههای بازیکن را به طور ایمن بازیابی کند، بدون اینکه در حین عبور از دستگاه در معرض دستکاریهای احتمالی قرار گیرد.
پس از احراز هویت موفقیتآمیز بازیکن، میتوانید یک کد یکبار مصرف ویژه (به نام کد احراز هویت سرور ) را از Play Games Services v2 Native SDK (بتا) درخواست کنید که کلاینت آن را به سرور ارسال میکند. سپس، در سرور، کد احراز هویت سرور را با یک توکن OAuth 2.0 که سرور میتواند برای برقراری تماس با API Google Play Games Services از آن استفاده کند، مبادله کنید.
برای راهنمایی بیشتر در مورد افزودن احراز هویت در بازیهایتان، به احراز هویت پلتفرم مراجعه کنید.
برای دسترسی آفلاین، مراحل زیر لازم است:
- در کنسول گوگل پلی: یک اعتبارنامه برای سرور بازی خود ایجاد کنید. نوع اعتبارنامه برای کلاینت OAuth، «وب» خواهد بود.
- در برنامه اندروید: به عنوان بخشی از احراز هویت پلتفرم، یک کد احراز هویت سرور برای اعتبارنامه سرور خود درخواست کنید و آن را به سرور خود ارسال کنید.
PgsGamesSignInClientمیتواند هنگام درخواست دسترسی سمت سرور به APIهای وب Play Games Services، سه محدوده OAuth 2.0 درخواست کند. محدودههای اختیاری عبارتند ازPGS_AUTH_SCOPE_EMAIL،PGS_AUTH_SCOPE_PROFILEوPGS_AUTH_SCOPE_OPENID. دو محدوده پیشفرض عبارتند ازDRIVE_APPFOLDERوGAMES_LITE. - روی سرور بازی خود: کد احراز هویت سرور را با استفاده از سرویسهای احراز هویت گوگل با یک توکن دسترسی OAuth جایگزین کنید و سپس از آن برای فراخوانی APIهای REST سرویسهای Play Games استفاده کنید.
قبل از اینکه شروع کنی
ابتدا باید بازی خود را به کنسول گوگل پلی اضافه کنید، همانطور که در بخش «راهاندازی سرویسهای بازیهای گوگل پلی» توضیح داده شده است.
ایجاد یک برنامه وب سمت سرور
سرویسهای بازی گوگل پلی پشتیبانی بکاند برای بازیهای وب ارائه نمیدهد. با این حال، پشتیبانی بکاند سرور را برای سرور بازی اندروید شما فراهم میکند.
اگر میخواهید از APIهای REST برای سرویسهای بازیهای گوگل پلی در برنامه سمت سرور خود استفاده کنید، این مراحل را دنبال کنید:
- در کنسول گوگل پلی ، یک بازی را انتخاب کنید.
- به سرویسهای بازیهای Play > راهاندازی و مدیریت > پیکربندی بروید.
- برای رفتن به صفحه افزودن اعتبارنامه، گزینه افزودن اعتبارنامه (Add credential) را انتخاب کنید. نوع اعتبارنامه را Game server انتخاب کنید و به بخش Authorization بروید.
- اگر سرور بازی شما از قبل شناسه کلاینت OAuth دارد، آن را از منوی کشویی انتخاب کنید. پس از ذخیره تغییرات، به بخش بعدی بروید.
- اگر شناسه کلاینت OAuth موجود برای سرور بازی خود ندارید، میتوانید یکی ایجاد کنید.
- روی ایجاد کلاینت OAuth کلیک کنید و پیوند ایجاد شناسه کلاینت OAuth را دنبال کنید.
- این شما را به صفحه ایجاد شناسه کلاینت OAuth در پلتفرم ابری گوگل برای پروژه مرتبط با بازیتان هدایت میکند.
- فرم صفحه را پر کنید و روی ایجاد کلیک کنید. حتماً نوع برنامه را روی برنامه وب تنظیم کنید.
- به بخش مجوزها در صفحه افزودن اعتبارنامه برگردید، کلاینت OAuth تازه ایجاد شده را انتخاب کنید و تغییرات خود را ذخیره کنید.
دریافت کد احراز هویت سرور
برای بازیابی کد احراز هویت سرور که بازی شما میتواند برای توکنهای دسترسی در سرور بکاند شما استفاده کند:
- تابع
PgsGamesSignInClient_requestServerSideAccessرا از سمت کلاینت فراخوانی کنید.- مطمئن شوید که از شناسه کلاینت OAuth ثبتشده برای سرور بازی خود استفاده میکنید و نه از شناسه کلاینت OAuth برنامه اندروید خود.
- (اختیاری) اگر سرور بازی شما نیاز به دسترسی آفلاین (دسترسی طولانی مدت با استفاده از توکن refresh) به سرویسهای بازیهای Play دارد، میتوانید پارامتر
force_refresh_tokenروی true تنظیم کنید.
(اختیاری) به عنوان بخشی از احراز هویت، کاربران جدید باید برای دسترسی به حوزههای بیشتر، با یک صفحه رضایت واحد مواجه شوند. پس از پذیرش رضایت، پارامتر
scopesPgsAuthScopeرا با حوزههای OAuthPGS_AUTH_SCOPE_EMAIL،PGS_AUTH_SCOPE_PROFILEوPGS_AUTH_SCOPE_OPENIDتنظیم میکنید. اگر کاربران رضایت را رد کنند، فقط دو حوزه پیشفرضDRIVE_APPFOLDERوGAMES_LITEبه backend ارسال میشوند.
صفحه رضایت برای محدودههای اضافی OAuth. (برای بزرگنمایی کلیک کنید). // #include "google/games/pgs_games_sign_in_client.h" // 1. Define the Callback // This function is called when the server-side access request completes. // It provides the authorization code (on success) or an error (on failure). void OnServerSideAccessCallback(void* context, PgsError error, const char* serverAuthCode) { if (error == PgsError_Success) { if (serverAuthCode != nullptr) { __android_log_print(ANDROID_LOG_INFO, "Games", "Received Server Auth Code: %s", serverAuthCode); // Send 'serverAuthCode' to your backend server immediately. // Your server will exchange this code for an OAuth access token. } } else { __android_log_print(ANDROID_LOG_ERROR, "Games", "Failed to get server auth code. Error: %d", error); } } // 2. Define the Wrapper Function void RequestServerAccess(PgsGamesSignInClient* signInClient) { if (signInClient == nullptr) { return; } // This must match the "Web client ID" from your Google Cloud Console // (linked to your Play Console Game Server Credential). const char* SERVER_CLIENT_ID = "xxxx"; // Set to 'true' if your server needs a Refresh Token (long-lived access). // Set to 'false' if you only need an Access Token (short-lived). bool forceRefreshToken = false; // Call the API PgsGamesSignInClient_requestServerSideAccess( signInClient, SERVER_CLIENT_ID, forceRefreshToken, OnServerSideAccessCallback, // The callback defined nullptr // User context (optional, passed to callback) ); } // 3. Example Usage void TriggerSignInProcess(PgsGamesClient* gamesClient) { // Obtain the Sign-In Client from the main Games Client PgsGamesSignInClient* signInClient = PgsGamesClient_getSignInClient(gamesClient); RequestServerAccess(signInClient); }
کد تایید OAuth را به سرور backend خود ارسال کنید تا مبادله شود، شناسه بازیکن با APIهای REST سرویسهای Play Games تأیید شود و سپس با بازی شما احراز هویت شود.
ارسال کد احراز هویت سرور
کد احراز هویت سرور را برای تبادل توکنهای دسترسی و بهروزرسانی به سرور بکاند خود ارسال کنید. از توکن دسترسی برای فراخوانی API خدمات بازیهای Play از طرف بازیکن استفاده کنید و به صورت اختیاری، توکن بهروزرسانی را ذخیره کنید تا پس از انقضای توکن دسترسی، یک توکن دسترسی جدید دریافت کنید.
برای اطلاعات بیشتر در مورد نحوه عملکرد شناسههای پخشکننده، به شناسههای پخشکننده نسل بعدی مراجعه کنید.
قطعه کد زیر نشان میدهد که چگونه میتوانید کد سمت سرور را در زبان برنامهنویسی ++C پیادهسازی کنید تا کد احراز هویت سرور را با توکنهای دسترسی مبادله کنید.
جاوا
/** * Exchanges the authcode for an access token credential. The credential * is 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 Cloud // console. This is used to identify your web application. The // contents of this file shouldn't 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(); TokenVerifier(tokenResponse); 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; }
شما میتوانید با استفاده از کتابخانههای کلاینت API گوگل در جاوا یا پایتون، محدودههای OAuth را بازیابی کنید تا شیء GoogleIdTokenVerifier را دریافت کنید. قطعه کد زیر پیادهسازی آن را در زبان برنامهنویسی جاوا نشان میدهد.
جاوا
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload; import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier; /** * Gets the GoogleIdTokenVerifier object and additional OAuth scopes. * If additional OAuth scopes are not requested, the idToken will be null. * * @param tokenResponse - the tokenResponse passed from the exchangeAuthCode * function. * **/ void TokenVerifier(GoogleTokenResponse tokenResponse) { string idTokenString = tokenResponse.getIdToken(); GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory) // Specify the WEB_CLIENT_ID of the app that accesses the backend: .setAudience(Collections.singletonList(WEB_CLIENT_ID)) // Or, if multiple clients access the backend: //.setAudience(Arrays.asList(WEB_CLIENT_ID_1, WEB_CLIENT_ID_2, WEB_CLIENT_ID_3)) .build(); GoogleIdToken idToken = verifier.verify(idTokenString); // The idToken can be null if additional OAuth scopes are not requested. if (idToken != null) { Payload payload = idToken.getPayload(); // Print user identifier String userId = payload.getSubject(); System.out.println("User ID: " + userId); // Get profile information from payload String email = payload.getEmail(); boolean emailVerified = Boolean.valueOf(payload.getEmailVerified()); String name = (String) payload.get("name"); String pictureUrl = (String) payload.get("picture"); String locale = (String) payload.get("locale"); String familyName = (String) payload.get("family_name"); String givenName = (String) payload.get("given_name"); // This ID is unique to each Google Account, making it suitable for use as // a primary key during account lookup. Email is not a good choice because // it can be changed by the user. String sub = payload.getSubject(); // Use or store profile information // ... } else { System.out.println("Invalid ID token."); } }
فراخوانی APIهای REST از سرور
برای شرح کامل فراخوانیهای API موجود، به APIهای REST برای سرویسهای بازیهای Google Play مراجعه کنید.
نمونههایی از فراخوانیهای REST API که ممکن است برای شما مفید باشند عبارتند از:
بازیکن
میخواهید با شناسه و اطلاعات پروفایل بازیکن احراز هویت شوید؟ با استفاده از شناسه 'me' با Players.get تماس بگیرید.
دستاوردها
برای جزئیات بیشتر به راهنمای دستاوردها مراجعه کنید.
برای دریافت لیستی از دستاوردهای فعلی، AchievementDefinitions.list را فراخوانی کنید.
این را با فراخوانی Achievements.list ترکیب کنید تا بفهمید کدام یک از موارد قفل شده توسط بازیکن فعال شده است.
برای باز کردن قفل یک دستاورد بازیکن، Achievements.unlock را فراخوانی کنید.
برای گزارش پیشرفت در یک دستاورد و اطلاع از اینکه آیا بازیکن آن را قفلگشایی کرده است یا خیر، تابع Achievements.increment را فراخوانی کنید.
اگر در حال اشکالزدایی بازیای هستید که به مرحله تولید نرسیده است، میتوانید Achievements.reset یا Achievements.resetAll را از رابطهای برنامهنویسی کاربردی مدیریت (Management APIs) فراخوانی کنید تا دستاوردها را به حالت اولیهشان بازنشانی کنید.