BaaS認証によるゲーム内ストアを利用する

ゲーム内ストアをBaaSの認可システムと併用することで、ゲーム内アイテムを販売することができます。この場合の相互作用は次のとおりです:

  1. ユーザーは、BaaSの認証システムを介してアプリケーションにログインします。
  2. BaaSサービスは、ユーザーIDを渡してエクソラサーバーにユーザー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. FirebasePlayFabの説明に従って、既成の機能をプロジェクトに追加してください。

サーバーOAuth 2.0クライアントをセットアップする

  1. パブリッシャーアカウントでプロジェクトを開き、ログインセクションに移動します。
  2. ログインプロジェクトのパネルでの構成するをクリックします。
  3. セキュリティブロックに移動してOAuth 2.0セクションに移動します。
  4. OAuth 2.0を追加するをクリックします。
  5. OAuth 2.0のリダイレクトURIを指定します。
  6. サーバー(サーバー・トゥ・サーバー接続)チェックボックスを入ります。
  7. 接続をクリックします。
  8. クライアントIDと秘密鍵をコピーして保存してください。

Firebaseプロジェクトにクラウド機能を追加する

  1. Firebaseプロジェクトを初期化します
  2. ユーザーJWTの受信機能をインポートして設定します。そこで:

ユーザー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. ユーザーJWTを受信するための機能コードを含むJSファイルを作成します。そこで:

お知らせ
既にプロジェクトでクラウドスクリプトを使用している場合は、ユーザー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を自分で操作するためのメソッドを実装するか、Xsolla SDKを使用します。

この記事は役に立ちましたか?
ありがとうございます!
改善できることはありますか? メッセージ
申し訳ありません
この記事が参考にならなかった理由を説明してください。 メッセージ
ご意見ありがとうございました!
あなたのメッセージを確認し、体験を向上させるために利用させていただきます。
このページを評価する
このページを評価する
改善できることはありますか?

答えたくない

ご意見ありがとうございました!

お役立ちリンク

最終更新日: 2022年10月21日

誤字脱字などのテキストエラーを見つけましたか? テキストを選択し、Ctrl+Enterを押します。

問題を報告する
当社は常にコンテンツを見直しています。お客様のご意見は改善に役立ちます。
フォローアップ用のメールをご提供してください
ご意見ありがとうございました!