Unity3d — Android: проверка пользователя на собственном сервере Node.JS

в 8:07, , рубрики: Gamedev, Google API, node.js, unity3d, разработка игр

Для реализации проверки пользователя вашего android приложения, созданного в unity3d, на своем node.js сервере, вам понадобится:

Приложение в GooglePlay (опубликованное даже в режиме альфа-тестирования)
— Плагин GooglePlayGames for Unity3D
— Доступ в консоль Google Cloud
— Ваш Node.JS-сервер
— Модуль GoogleApis для node.js: npm install googleapis --save

Если ваше приложение еще в режиме альфа/бета-версии в GooglePlay — не забудьте добавить в список тестировщиков аккаунт, с помощью которого собираетесь тестировать. Также ваше приложение должно быть подключено в Игровых Сервисах.

image

Клиент

Распаковываем в unity3d плагин GooglePlayForUnity3d. Открываем Window/ GooglePlayGames/Setup/Android Setup.

Первые два поля можно оставить без изменений. Для информации по Resources Definition — идем в консоль GooglePlay, раздел Игровые сервисы, Достижения. Вводим минимум 5 достижений (если их нет) и находим ссылку “Получить ресурсы”. Нажимаем, открываем раздел Android и копируем все в Unity3d в поле Resources Definition.

image

Включаем GooglePlus API. В поле Web App Client Id вводим идентификатор вида ХХХХХХ.apps.googleusercontent.com, его можно получить в консоли GoogleCloud (будет описано ниже).

image

Нажимаем Setup. Если последует запросы на изменение версий файлов с 10.0.1 на 10.2.0 — лучше отказаться и выбрать “Keep”.

Небольшое отступление — если у вас в папке Plugins/Android есть файлы sdk (*.aar) версии выше 10.0.1 — замените их на версию 10.0.1 — найти их можно в установленной у вас sdk (sdkextrasgooglem2repositorycomgoogleandroidgms) — это временный шаг — только с данной версией.

Далее добавляем в клиенте GoogleAuth.cs который будет получать серверный токен.

GoogleAuth.cs

using System;
using System.Collections;
using GooglePlayGames;
using GooglePlayGames.BasicApi;
using UnityEngine;

public class GoogleAuth:MonoBehaviour
{
    /// <summary>
    /// Возвращает серверный токен для проверки на сервере
    /// </summary>
    /// <param name="callback"></param>
    public void Auth(Action<string> callback)
    {
        InitAuth(() =>
        {
            GetServerToken(callback);
        });
    }

    private void InitAuth(Action callback)
    {
        var config = new PlayGamesClientConfiguration.Builder()
        .AddOauthScope("profile")
        .AddOauthScope("email")
        .Build();
        PlayGamesPlatform.InitializeInstance(config);
        PlayGamesPlatform.Activate();
        Social.localUser.Authenticate((success, str) =>
        {
            if (success)
                callback();
            else
                Debug.Log("Error on Social Authenticate: " + str);
        });
    }

    private void GetServerToken(Action<string> callback)
    {
        StartCoroutine(ReadToken((serverToken,empty) =>
        {
            callback(serverToken);
        }));
    }

    private IEnumerator ReadToken(Action<string, string> callback)
    {
        yield return null;
        if (!PlayGamesPlatform.Instance.IsAuthenticated()) //Проверка текущего состояния
        {
            PlayGamesPlatform.Instance.Authenticate((result, msg) => //аутентификация без показа уведомлений игроку
            {
                if (!result)
                {
                    PlayGamesPlatform.Instance.Authenticate(
                        (result2, msg2) => //аутентификация с показом окна googleplay игроку
                        {
                            if (!result2)
                            {
                                PlayGamesPlatform.Instance.GetIdToken(
                                    val => //пробуем получить IdToken и перезапускаем авторизацию
                                    {
                                        StartCoroutine(ReadToken(callback));
                                    });
                            }
                        }, false);
                }
            }, true);
        }
        else
        {
                PlayGamesPlatform.Instance.GetServerAuthCode(
                    (status, code) => //получаем токен для проверки на своем сервере
                    {
                        if (status != CommonStatusCodes.Success || string.IsNullOrEmpty(code))
                            StartCoroutine(ReadToken(callback));
                        else
                            callback(code, null);
                    });
            
        }
    }
}

Прикрепляем его на сцене к какому-либо GameObject.

Для получения серверного токена необходимо вызвать метод Auth с обратным вызовом в котором и будет серверный токен. Места возникновения ошибок вы можете видеть в классе GoogleAuth — можете либо выводить сообщения пользователям, либо отправлять статистику и т.п.

В AndroidManifest.xml добавляем:

<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
  <uses-permission android:name="android.permission.USE_CREDENTIALS"/>
  <uses-permission android:name="android.permission.INTERNET"/>
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

Сервер

Необходим файл содержащий идентификационные данные вашего сервера для GooglePlay. Открываем консоль Cloud Google (https://console.cloud.google.com/apis/credentials?project=ид_вашего_проекта).

Находим в разделе Идентификаторы клиентов OAuth 2.0 идентификатор с типом «Веб-приложение». Открываем идентификатор и скачиваем client-secret (файл, который заканчивается apps.googleusercontent.com.json):

image

Сохраняем в папку с серверным приложением. Указанный в том же окне идентификатор клиента копируем и вставляем в клиентскую часть (Unity3d) в окне GooglePlayGames — Android configuration в поле «Web App Client id» которое раньше оставляли не заполненным.

Как вы будете доставлять необходимые данные из вашего приложения на ваш сервер не столь важно, тут на ваш выбор ( в т.ч. express, websocket, socket.io и т.д.).

Создаем класс, который будет проверять полученный от приложения токен:

GooglePlayAuth.js

"use strict";
const fs = require('fs');
const https = require("https");
const google = require('googleapis');

/**
 * Путь к файлу полученному в консоли GoogleCloud
 */
const _clientSecret = "client_secret.apps.googleusercontent.com.json";
const _userInfoUrl = "https://www.googleapis.com/games/v1/players/me";

let oauth2Client;

/**
 * 
 */
class GooglePlayAuth {
    /**
     * Единоразовая инициализация
     * @param callback
     */
    static Init(callback) {
        fs.readFile(_clientSecret, function (err, content) {
            if (err) {
                callback(err);
                return;
            }
            const credentials = JSON.parse(content);
            oauth2Client = new google.auth.OAuth2(credentials.web.client_id, credentials.web.client_secret, credentials.web.redirect_uris[0]);
            callback(null);
        });
    }
    /**
     * Проверка пользователя 
     * @param serverToken
     * @param callback
     */
    static Verify(serverToken,callback) {
        oauth2Client.getToken(serverToken, function (err, token) {
            if (err) {
                callback(`Error while retrieve access token: ${err}`);
                return;
            }
            oauth2Client.credentials = token;
            //Получение информации о пользователе
            require("https").get(`${_userInfoUrl}?access_token=${token.access_token}`, function (res) {
                res.on("data", function (d) {
                    let userData = {};
                    try {
                        userData = JSON.parse(d);
                    } catch (er) {
                        callback(`Error parse user data ${er}`);
                        return;
                    }
                    if (userData.playerId == null) {
                        callback(`Error read playerId: ${userData}`);
                        return;
                    }
                    //все в порядке - возвращаем данные пользователя в модуль подключения
                    callback(null, userData);
                });
            }).on("error", function (err) {
                callback(`Fail request: ${err}`);
            });
        });
    }
}

module.exports = GooglePlayAuth;

При запуске сервера не забудьте вызвать GooglePlayAuth.Init.

Полученный от клиентского приложения серверный токен отправляем в GooglePlayAuth.Verify, который вернет в обратном вызове либо ошибку, либо данные пользователя, полученные от сервиса Google.

Спасибо за внимание!

Автор: McRain

Источник

Поделиться

* - обязательные к заполнению поля