Available in the Gaming / Industries Circle
quantum | v2 switch to v1  

Backend Integration

目次

カスタムアセットサーバー統合

カスタムアセットサーバーからアイテム・通貨を読み込み、トーナメントの賞金やエントリー料として使用できます。 また、これらのアイテムを差し引いたりトーナメントへのサインアップを拒否したりできる(例:ユーザーの所持金が足りないなど)カスタムサーバー経由ですべてのサインアップをルートできます。

トップに戻る
 

サーバーからストアアイテムを読み込む

アイテムや通貨をカスタムサーバーから読み込むためには、アイテムを特定のJSONフォーマットで返すHTTPエンドポイントを作成する必要があります。 サーバーがアイテムを内部使用のために読み込み、アイテムと通貨を外部リソースから「読み込み済」とマークするようにこの操作を行います。

JSON フォーマット:

{
   items:[
       {
           id:"itemId1",
           name:"itemName1",
           image:"imageUrl (optional)"
       },
       {
           id:"itemId2",
           name:"itemName2",
           image:"imageUrl (optional)"
       }],   
   currencies:[
       {
           id:"currencyId1",
           name:"currencyName1"
       },
       {
           id:"currencyId2",
           name:"currencyName2"
       }]
}

エンドポイントはまた、status code 200 にレスポンスする必要があります。 常にインポートするすべてのアイテムを返します。 既に終了したアイテムと通貨は更新されます。

External store image

リクエストされるフォーマットで返すエンドポイントが表示されたら、Game Settings/Store Integrationへ移動し、「external store hookup」を有効にします。 プロバイダはCustom URLを選択します。 有効なHTTPパスと、サーバーからリクエストされる認証用のヘッダ・パラメータを挿入します。

Sync data nowボタンをクリックしてアイテムと通貨をインポートします。 トーナメントテンプレート賞とエントリー料の編集のときに、インポートしたアイテムにアクセスできるようになりました。

アセットにアップデートが生じた場合は、再度Sync data nowボタンをクリックしてインポートを行ってください。

トップに戻る
 

カスタムサーバー経由でのサインアップ

トーナメントサインアップをカスタムサーバーを通して計画するには、特定のJSONフォーマットを受け入れるHTTPエンドポイントを作成する必要があります。 各ユーザーのアインアップごとに、トーナメント、ユーザー、エントリー料などの情報が盛り込まれたペイロードでカスタムサーバーへのコールが行われます。

このHTTPコールは、JSONペイロードを含む userTicket と呼ばれるパラメータでのPOST送信です。

JSON フォーマット:

{
   isSignup:true,
   isSignout:false,
   userId:"64bit number as string",
   userExternalId:"string",
   ticketId:"64bit number as string",
   tournamentId:"64bit number as string",
   customRequirements:[{
    name:"string",
    value:"string"
   }],
   fees:{
    items:[{
       id:"64bit number as string",
       externalId:"string",
       amount:1
    }],
    currencies:[{
       id:"64bit number as string",
       externalId:"string",
       amount:1
    }]
   }
}

レスポンスが正常に行われると、HTTP status code 200 (拒否された場合は、別のコード)で待機状態となります。

External signup image

リクエストされるJSONフォーマットを受け入れるエンドポイントができたら、Game Settings/Tournament settings Integrationへ移動し、「external signup」を有効にします。 有効なHTTPパスと、サーバーからリクエストされる認証用のヘッダ・パラメータを挿入します。

この設定を行ったあと、クライアントからのすべてのサインアップが受け入れおよび確認前にカスタムサーバー経由でルーティングされるようになります。

トップに戻る
 

カスタムサーバーへのトーナメント結果レポート

カスタムサーバー経由でトーナメント結果を受信するには、特定のJSONフォーマットを受け入れるHTTPエンドポイントを作成する必要があります。 各トーナメントが終了するごとに、トーナメント、ユーザー、賞金などの情報が盛り込まれたペイロードでカスタムサーバーへのコールが行われます。

このHTTPコールは、JSONペイロードを含む jsonPayload と呼ばれるパラメータでのPOST送信です。

JSON フォーマット:

{
   "tournamentId":"64bit number as string",   
   "prizes":[{
       "ticketId":"64bit number as string",
       "userId":"64bit number as string",
       "userExternalId":"string",
       "place":1,
       "items":[{
           "id":"64bit number as string",
           "amount":1,
           "externalId":"string"}],
       "currencies":[{
           "id":"64bit number as string",
           "amount":1,
           "externalId":"string"}]
    }]
}

レスポンスが正常に行われると、HTTP status code 200 で待機状態となります。 失敗した場合、何度か繰り返されます。

External prize delivery image

リクエストされるJSONフォーマットを受け入れるエンドポイントができたら、Game Settings/Tournament settings Integrationへ移動します。 有効なHTTPパスと、サーバーからリクエストされる認証用のヘッダ・パラメータを挿入します。

トップに戻る
 

PlayFabアセットサーバー統合

Playfabバックエンドからアイテム・通貨を読み込み、トーナメントの賞金やエントリー料として使用できます。 また、これらのアイテムを差し引いたりトーナメントへのサインアップを拒否したりできる(例:ユーザーの所持金が足りないなど)カスタムCloudScript経由ですべてのサインアップをルートできます。

トップに戻る
 

PlayFab秘密鍵を作成する

PlayFab統合には、TitleIdSecretKey が必要となります。  playfabダッシュボードにログインして、ゲームを選択し、設定画面を開きましょう。

PlayFab game settings

API Featuresタブに TitleId があります。新しい SecretKey の作成はSecret Keyタブで行えます。 秘密鍵に有効期限を設定しないようにしてください。トーナメントダッシュボードで新しい秘密鍵を設定し忘れた場合、ゲームが停止状態になってしまいます。

トップに戻る
 

PlayFabプロバイダ経由でログインする

If you integrating with PlayFab services we strongly recommend enabling only PlayFab login provider in tournament dashboard. Also NOTE that if you will not use PlayFab login provider other integration features such as tournament signup or delivering prizes via cloudscript fail to work.

Dashboard playfab login provider image

Enter here TitleId & SecretKey and save changes.

In your game client, after you initialize and login with playfab you will get a session ticket. This session ticket is then passed to playfab login provider to authenticate user and login to tournaments. This process will ensure that system has correct and valid playfab id associated with user account.

string playfabId;
string playfabSessionTicket;
bool isPlayfabLoginFinished;

// coroutine
// ...
// login playfab client
PlayFab.PlayFabClientAPI.LoginWithCustomID(
    new PlayFab.ClientModels.LoginWithCustomIDRequest() {
        CreateAccount = true,
        CustomId = "customPlayfabId"
    },
    (result) =>
    {
        isPlayfabLoginFinished = true;
        // get playfab user id and session ticket (we will use it for authentication)
        playfabId = result.PlayFabId;
        playfabSessionTicket = result.SessionTicket;
    },
    (error) =>
    {
        isPlayfabLoginFinished = true;
    });
// wait until playfab login process finishes
yield return new WaitUntil(() => isPlayfabLoginFinished);
// use playfab login provider, pass playfab id and session ticket
yield return BackboneManager.Client.Login(
    Gimmebreak.Backbone.User.LoginProvider.Playfab(
        true,
        "NickName-" + playfabId,
        playfabSessionTicket,
        playfabId));

playfab idをユーザーアカウントと関連付けるには、 BackboneManager.Client.User.GetLoginId(LoginProvider.Platform.Playfab)を呼び出します。 記録されたPlayfabクライアントが記録されたトーナメントクライアントと一致するかの比較に使用されます。

トップに戻る
 

Playfabからストアのアイテムを読み込む

Game Settings/Store Integrationへ移動して「external store hookup」を有効にします。 プロバイダはPlayfabを選択します。 有効な title idsecret key を入力して変更を保存します。

External store playfab image

Sync data nowボタンをクリックして、アイテム・通貨を(プライマリカタログから)インポートします。 トーナメントテンプレート賞とエントリー料の編集のときにインポートしたアイテムにアクセスできるようになっているはずです。

アセットに何かしらのアップデートが生じた場合は、Sync data nowボタンをクリックして再度インポートを行ってください。

トップに戻る
 

Playfab CloudScript経由でのサインアップ

トーナメントサインアップをPlayfab CloudScript経由でルートするには、特定のJSONフォーマットを受け入れる関数を作成する必要があります。 各ユーザーがサインアップするごとに、トーナメント、ユーザー、エントリー料などの情報を含むペイロードで、このcloudscript関数への呼び出しが行われます。

CloudScript関数のパラメータである args には、JSONペイロードが含まれます。

JSON フォーマット:

{
   serverSecret:"string",
   isSignup:true,
   isSignout:false,
   userId:"64bit number as string",
   userPlayfablId:"string",
   ticketId:"64bit number as string",
   tournamentId:"64bit number as string",
   customRequirements:[{
    name:"string",
    value:"string"
   }],
   fees:{
    items:[{
       id:"64bit number as string",
       externalId:"string",
       amount:1
    }],
    currencies:[{
       id:"64bit number as string",
       externalId:"string",
       amount:1
    }]
   }
}

サインアップ・サインアウトくを処理するCloudScript関数のサンプルです:

// This is a example tournament signup/signout handler. If signup is requested
// check if user can sign up and deduct any required fees. If signout is requested
// return any deducted fees back to users account.
handlers.tournamentSignup = function(args, context){
  if (args.serverSecret == "secret") {
        if (args.isSignup) {
            // Check any custom requirement for the tournament. This can be
            // e.g. having required minimum rank. If player does not meet
            // specified criteria, the signup should be rejected.
            for (var i = 0; i < args.customRequirements.length; i++) {
                var name = args.customRequirements[i].name;
                var value = args.customRequirements[i].value;
                if (name == "testRequirement" &&
                    value == "reject") {
                    return { success: false };
                }
            }
            // Check if user has required signup fees.
            if (args.fees.items.length > 0 ||
                args.fees.currencies.length > 0) {
                // Get user inventory
                var userInvetoryResult = server.GetUserInventory({PlayFabId: currentPlayerId});
                // Check if user has enough currency
                for (var i = 0; i < args.fees.currencies.length; i++) {
                    var currencyFee = args.fees.currencies[i];
                    var userCurrency = userInvetoryResult.VirtualCurrency[currencyFee.externalId];
                    if (!userCurrency ||
                        userCurrency < currencyFee.amount) {
                        // User does not have required currency or amount
                        return { success: false };
                    }
                }
                // Sort user invetory items by id
                var userInventory = {};
                for (var i = 0; i < userInvetoryResult.Inventory.length; i++) {
                    var item = userInvetoryResult.Inventory[i];
                    if (!userInventory[item.ItemId]) {
                        userInventory[item.ItemId] = [];
                    }
                    userInventory[item.ItemId].push(item);
                }
                // Check if user has enough items
                for (var i = 0; i < args.fees.items.length; i++) {
                    var itemFee = args.fees.items[i];
                    var userItems = userInventory[itemFee.externalId];
                    if (!userItems ||
                        userItems.length < itemFee.amount) {
                        // User does not have required item or amount
                        return { success: false };
                    }
                }

                // Substract user's currencies
                for (var i = 0; i < args.fees.currencies.length; i++) {
                    var currencyFee = args.fees.currencies[i];
                    server.SubtractUserVirtualCurrency({PlayFabId: currentPlayerId, VirtualCurrency: currencyFee.externalId, Amount: currencyFee.amount });
                }

                // Revoke user's items
                var revokedItems = { Items: [] };
                for (var i = 0; i < args.fees.items.length; i++) {
                    var itemFee = args.fees.items[i];
                    for (var p = 0; p < itemFee.amount; p++) {
                        revokedItems.Items.push({PlayFabId: currentPlayerId, ItemInstanceId: userInventory[itemFee.externalId][p].ItemInstanceId});
                        // Maximum 25 items can be removed at once (Playfab documentation)
                        // If container is filled with 25 items, revoke and continue
                        if (revokedItems.Items.length == 25) {
                            server.RevokeInventoryItems(revokedItems);
                            revokedItems.Items = [];
                        }
                    }
                }
                // Check if any items should be revoked (last 25 items)
                if (revokedItems.Items.length > 0) {
                    server.RevokeInventoryItems(revokedItems);
                }

                // All fees deducted, confirm tournament signup
                return { success: true };
            }
            else {
                // No fees to deduct, confirm tournament signup
                return { success: true };
            }
        }
        if (args.isSignout) {
            // Return user's currencies
            for (var i = 0; i < args.fees.currencies.length; i++) {
                var currencyFee = args.fees.currencies[i];
                server.AddUserVirtualCurrency({PlayFabId: currentPlayerId, VirtualCurrency: currencyFee.externalId, Amount: currencyFee.amount });
            }
            // Return user's items
            var returnItems = { PlayFabId: currentPlayerId, ItemIds: [], Annotation: "Returned tournament fee items. TournamentId: " + args.tournamentId };
            for (var i = 0; i < args.fees.items.length; i++) {
                var itemFee = args.fees.items[i];
                for (var p = 0; p < itemFee.amount; p++) {
                    returnItems.ItemIds.push(itemFee.externalId);
                }
            }
            // Check if any items should be returned
            if (returnItems.ItemIds.length > 0) {
                server.GrantItemsToUser(returnItems);
            }
            // User fees has been returned
            return { success: true };
        }
    }
    return { success: false };
};

レスポンスが正常に行われると、{ success: true }(拒否された場は別)で待機状態となります。

External signup playfab image

リクエストされるJSONフォーマットを受け入れる関数ができたら、Game Settings/Tournament settings Integrationへ移動し、「external signup」を有効にします。 プロバイダはPlayfabを選択します。 有効な title idsecret keyCloudScript 関数名関数バージョン (修正番号)を挿入し、保存します。

希望する場合は変更可能な、すでに生成されたサーバーシークレットがあります。 Playfabユーザーが実行するのを防ぐため、cloud scriptでこちらを使用してください。

この設定を行ったあと、クライアントからのすべてのサインアップが受け入れおよび確認前にCloud script経由でルーティングされるようになります。

トップに戻る
 

Playfab CloudScript経由のトーナメント結果

Playfab CloudScript経由でトーナメント結果を受信するには、特定のJSONフォーマットを受け入れる関数を作成する必要があります。 各トーナメントが終わるごとに、トーナメント、ユーザー、賞金などの情報が盛り込まれたペイロードでcloudscript関数に呼び出しが行われます。

CloudScript関数パラメータである args にはJSONペイロードが含まれます。

JSON フォーマット:

{
   "serverSecret":"string",
   "tournamentId":"64bit number as string",   
   "prizes":[{
       "ticketId":"64bit number as string",
       "userId":"64bit number as string",
       "userPlayfabId":"string",
       "place":1,
       "items":[{
           "id":"64bit number as string",
           "amount":1,
           "externalId":"string"}],
       "currencies":[{
           "id":"64bit number as string",
           "amount":1,
           "externalId":"string"}]
    }]
}

賞金の受け渡しを処理するCloudScript関数のサンプルです。:

// This is example tournament prize delivery handler. Once tournament is finished
// all results will be provided togather with information which items and currencies
// should be granted to user.
handlers.tournamentPrizeDelivery = function(args, context){
  if (args.serverSecret == "secret" &&
        args.prizes) {
        for (var i = 0; i < args.prizes.length; i++) {
            var prize  = args.prizes[i];
            // Grant user currency prizes
            for (var p = 0; p < prize.currencies.length; p++) {
                var wonCurrency = {
                    PlayFabId: prize.userPlayfabId,
                    VirtualCurrency: prize.currencies[p].externalId,
                    Amount: prize.currencies[p].amount

                };
                server.AddUserVirtualCurrency(wonCurrency);
            }
            // Grant user item prizes
            var wonItems = {
                PlayFabId: prize.userPlayfabId,
                ItemIds: [],
                Annotation: "Won items in tournament. Place: " + prize.place + " TournamentId: " + args.tournamentId
            };
            for (var p = 0; p < prize.items.length; p++) {
                var itemPrize = prize.items[p];
                for (var c = 0; c < itemPrize.amount; c++) {
                    wonItems.ItemIds.push(itemPrize.externalId);
                }
            }
            if (wonItems.ItemIds.length > 0) {
                server.GrantItemsToUser(wonItems);
            }
        }
    }
};

レスポンスが正常に行われると、HTTP status code 200 で待機状態となります。失敗した場合、何度か再試行されます。

External prize delivery playfab image

リクエストされるフォーマットで返すエンドポイントができたら、Game Settings/Tournament settings Integrationへ移動し、「external prize delivery」を有効にします。 プロバイダはPlayfabを選択します。 有効な title idsecret keyCloudScript関数名関数バージョン (修正番号) を挿入して、保存します。

希望する場合は変更可能な、すでに生成されたサーバーシークレットがあります。 Playfabユーザーが実行するのを防ぐため、cloud scriptでこちらを使用してください。

ドキュメントのトップへ戻る