Использование Внутриигрового магазина с BaaS-авторизацией

Вы можете использовать Внутриигровой магазин для продажи внутриигровых товаров совместно с системой авторизации BaaS-сервисов. При этом сценарий взаимодействия будет следующим:

  1. Пользователь авторизуется в вашем приложении через систему авторизации BaaS-сервиса.
  2. BaaS-сервис запрашивает у серверов Иксоллы JSON Web Token (JWT) пользователя, передавая идентификатор пользователя.
  3. Сервер Иксоллы возвращает JWT пользователя в BaaS-сервис.
  4. BaaS-сервис передает JWT пользователя приложению.
  5. Приложение использует JWT пользователя для взаимодействия с серверами Иксоллы с помощью API.

Примечание
Если вы еще не реализовали логику для авторизации пользователей, вы можете подключить Авторизацию Иксоллы и настроить хранение пользовательских данных в PlayFab или Firebase. Вы сможете использовать Login API, чтобы аутентифицировать пользователей и получать JWT для взаимодействия с API других продуктов Иксоллы.

Для получения JWT пользователя:

  1. В Личном кабинете подключите к проекту стандартный вариант авторизации.
  2. Настройте серверный OAuth 2.0-клиент.
  3. Добавьте в ваш проект готовые функции, следуя инструкциям для Firebase и PlayFab.

Настройка серверного OAuth 2.0-клиента

  1. Откройте ваш проект в Личном кабинете и перейдите в раздел Авторизация.
  2. Нажмите Настроить в панели нужного варианта авторизации.
  3. На странице навигации перейдите к блоку Безопасность и выберите раздел OAuth 2.0 аутентификация.
  4. Нажмите Добавить OAuth 2.0.
  5. Укажите URI переадресации OAuth 2.0.
  6. Установите флажок Серверная (соединение server-to-server).
  7. Нажмите Подключить.
  8. Скопируйте и сохраните ID клиента и секретный ключ.

Добавление облачной функции в проект Firebase

  1. Инициализируйте свой проект Firebase.
  2. Импортируйте функцию получения JWT пользователя, где:
    • <ProjectID> — ID проекта, который можно найти в Личном кабинете рядом с названием вашего проекта.
    • <LoginID> — ID варианта авторизации. Чтобы получить его, откройте ваш проект в Личном кабинете, перейдите в раздел Авторизация > Дашборд и нажмите Скопировать ID рядом с названием варианта авторизации.
    • <OAuthClientID> — ID клиента, полученный при настройке серверного OAuth 2.0-клиента.
    • <OAuthSecretKey> — секретный ключ, полученный при настройке серверного OAuth 2.0-клиента.

Код функции получения JWT пользователя:

Copy
Full screen
Small screen
const projectId = "<ProjectID>";
const loginProjectId = "<LoginID>";

const serverOauthClientId = <OAuthClientID>;
const serverOauthClientSecret = "<OAuthSecretKey>";

exports.getXsollaLoginToken = functions.https.onCall((data, context) => {
  if (!context.auth) {
    throw new functions.https.HttpsError(
        "failed-precondition",
        "The function must be called while authenticated."
    );
  }

  const postData =
      "grant_type=client_credentials" +
      `&client_secret=${serverOauthClientSecret}`+
      `&client_id=${serverOauthClientId}`;

  const options = {
    hostname: "login.xsolla.com",
    port: 443,
    path: "/api/oauth2/token",
    method: "POST",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
      "Content-Length": postData.length,
    },
  };

  return new Promise( (resolve, reject) => {
    const req = https.request(options, (res) => {
      if (res.statusCode !== 200) {
        reject(
            new functions.https.HttpsError(
                "internal",
                "Server token not received"
            )
        );
      }
      let body = [];
      res.on("data", (d) => {
        body.push(d);
      });
      res.on("end", () => {
        try {
          body = JSON.parse(Buffer.concat(body).toString());
        } catch (e) {
          reject(
              new functions.https.HttpsError(
                  "internal",
                  "Malformed server token response"
              )
          );
        }
        getClientToken(context.auth.uid, body.access_token, resolve, reject);
      });
    });
    req.on("error", (e) => {
      reject(new functions.https.HttpsError(
          "internal",
          "Internal error while server token flow"
      ));
    });

    req.write(postData);
    req.end();
  });
});

// eslint-disable-next-line require-jsdoc
function getClientToken(userId, serverToken, resolve, reject) {
  const postData = JSON.stringify(
      {
        "server_custom_id": userId,
      }
  );

  const path =
      "/api/users/login/server_custom_id?" +
      `projectId=${loginProjectId}&` +
      `publisher_project_id=${projectId}`;

  const options = {
    hostname: "login.xsolla.com",
    port: 443,
    path: path,
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Content-Length": postData.length,
      "X-Server-Authorization": serverToken,
    },
  };

  const req = https.request(options, (res) => {
    if (res.statusCode !== 200) {
      reject(
          new functions.https.HttpsError(
              "internal",
              "Client token not received"
          )
      );
    }
    let body = [];
    res.on("data", (d) => {
      body.push(d);
    });
    res.on("end", () => {
      try {
        body = JSON.parse(Buffer.concat(body).toString());
      } catch (e) {
        reject(
            new functions.https.HttpsError(
                "internal",
                "Malformed client token response"
            )
        );
      }
      resolve({
        "token": body.token,
      });
    });
  });
  req.on("error", (e) => {
    reject(new functions.https.HttpsError(
        "internal",
        "Internal error while client token flow"
    ));
  });

  req.write(postData);
  req.end();
}

  1. Запустите функцию в боевой среде в соответствии с примером.
  2. Добавьте клиентскую логику для вызова функции из приложения. Укажите имя функции — getXsollaLoginToken, передача параметров не требуется.
  3. В приложении реализуйте методы для работы с API самостоятельно или воспользуйтесь SDK Иксоллы.

Добавление облачного скрипта в проект PlayFab

  1. Создайте JS-файл с кодом функции получения JWT пользователя, где:
    • <ProjectID> — ID проекта, который можно найти в Личном кабинете рядом с названием вашего проекта.
    • <LoginID> — ID варианта авторизации. Чтобы получить его, откройте ваш проект в Личном кабинете, перейдите в раздел Авторизация > Дашборд и нажмите Скопировать ID рядом с названием варианта авторизации.
    • <OAuthClientID> — ID клиента, полученный при настройке серверного OAuth 2.0-клиента.
    • <OAuthSecretKey> — секретный ключ, полученный при настройке серверного OAuth 2.0-клиента.

Примечание
Если вы уже используете облачные скрипты в вашем проекте, добавьте функцию получения JWT пользователя в конец кода.

Код функции получения JWT пользователя:

Copy
Full screen
Small screen
handlers.GetXsollaLoginToken = function (args) {

    // TODO replace with production credentials
    const projectId = <ProjectID>;
    const loginProjectId = "<LoginID>";
    const serverOauthClientId = <OAuthClientID>;
    const serverOauthClientSecret = "<OAuthSecretKey>";

    const getServerTokenBody =
        "grant_type=client_credentials" +
        `&client_secret=${serverOauthClientSecret}` +
        `&client_id=${serverOauthClientId}`;

    const serverTokenResponse = JSON.parse(
        http.request(
            "https://login.xsolla.com/api/oauth2/token",
            "post",
            getServerTokenBody,
            "application/x-www-form-urlencoded",
            {})
    );

    let serverToken = ""
    if ('access_token' in serverTokenResponse) {
        serverToken = serverTokenResponse.access_token;
    } else {
        return {
            "error_message": "Server token not received"
        }
    }

    const getUserTokenHeaders = {
        "X-Server-Authorization": serverToken
    }

    const getUserTokenBody = JSON.stringify(
        {
            "server_custom_id": currentPlayerId,
        }
    );

    const getUserTokenPath =
        "/api/users/login/server_custom_id?" +
        `projectId=${loginProjectId}&` +
        `publisher_project_id=${projectId}`;

    const userTokenResponse = JSON.parse(
        http.request(
            "https://login.xsolla.com" + getUserTokenPath,
            "post",
            getUserTokenBody,
            "application/json",
            getUserTokenHeaders)
    );

    if ('token' in userTokenResponse) {
        return {
            "token": userTokenResponse.token
        }
    } else {
        return {
            "error_message": "User token not received"
        }
    }
}

  1. Перейдите к настройкам проекта в PlayFab.
  2. Загрузите файл облачного скрипта.
  3. Запустите облачный скрипт в боевой среде.
  4. Добавьте клиентскую логику для вызова функции из приложения. Укажите имя функции — GetXsollaLoginToken, передача параметров не требуется.

Пример вызова функции получения JWT пользователя:

Copy
Full screen
Small screen
kotlin
  • kotlin
  • C#
  • C++
val tokenRequest = PlayFabClientModels.ExecuteCloudScriptRequest()
tokenRequest.FunctionName = "GetXsollaLoginToken"
val res = PlayFabClientAPI.ExecuteCloudScript(tokenRequest)
val result = res.Result.FunctionResult as Map<*, *>
val token = result["token"]
val errorMessage = result["error_message"]
var tokenRequest = new ExecuteCloudScriptRequest{
  FunctionName = "GetXsollaLoginToken"
};

PlayFabClientAPI.ExecuteCloudScript(
  tokenRequest,
  scriptResult =>
  {
     var functionResult = scriptResult.FunctionResult as Dictionary<string, string>;
     var token = functionResult["token"];
  },
  playfabError => { Debug.LogError($"GetXsollaAccessToken error: {playfabError.ErrorMessage}"); });
void UMyClass::GetXsollaToken()
{
    FClientExecuteCloudScriptRequest tokenRequest;
    tokenRequest.FunctionName = TEXT("GGetXsollaLoginToken");

    UPlayFabClientAPI::FDelegateOnSuccessExecuteCloudScript onSuccess;
    onSuccess.BindUFunction(this, "OnTokenRecieved");

    UPlayFabClientAPI::FDelegateOnFailurePlayFabError onFailure;
    onSuccess.BindUFunction(this, "OnError");

    UPlayFabClientAPI::ExecuteCloudScript(tokenRequest, onSuccess, onFailure, nullptr);
}

void UMyClass::OnTokenRecieved(FClientExecuteCloudScriptResult result, UObject* customData)
{
    const FString& token = result.FunctionResult->GetStringField(TEXT("token"));

    // do something with a token
}

void UMyClass::OnError(FPlayFabError error, UObject* customData)
{
    // handle errors
}

Примечание
В примере для выполнения запроса к облачному скрипту используются методы PlayFab SDK. Вы можете реализовать запрос и обработку ответа самостоятельно без добавления PlayFab SDK в ваш проект.

  1. В приложении реализуйте методы для работы с API самостоятельно или воспользуйтесь SDK Иксоллы.

Была ли статья полезна?
Спасибо!
Что может сделать страницу еще лучше? Сообщение
Жаль, что так произошло
Расскажите, почему статья не была полезна. Сообщение
Спасибо за обратную связь!
Ваши мысли и идеи помогут нам улучшить ваш пользовательский опыт.
Оценить страницу
Оценить страницу
Что может сделать страницу еще лучше?

В другой раз

Спасибо за обратную связь!

Полезные ссылки

Последнее обновление: 8 августа 2022

Нашли опечатку или ошибку в тексте? Выделите ее и нажмите Ctrl+Enter.

Сообщите о проблеме
Мы постоянно улучшаем качество нашей документации. Ваш отзыв поможет нам в этом.
Укажите email-адрес, чтобы мы могли связаться с вами
Спасибо за обратную связь!