Game Sales / エクソーラカタログをインポート

エクソーラカタログをインポート

JSONインポートを使用してアイテムカタログを作成および更新する

JSONファイルからのインポートを使用して、アイテムの作成、更新、非アクティブ化を行うことができます。

お知らせ
APIコールを使用して、またはアドミンページで手動でアイテムを作成、更新、または無効化できます。ただし、アイテムごとに個別のリクエストやアクションを実行する必要があります。インポートを使用すると、1つのJSONファイルで指定することで、複数のアイテムに対してこれらのアクションを同時に実行できます。

このツールを使用すると、次のことが可能になります:

機能:

  • 以下のタイプのアイテムをサポート:
    • 仮想アイテム
    • 仮想通貨
    • 仮想通貨パッケージ
    • バンドル
  • データの検証。ファイルの構造やデータ形式が要件を満たしていない場合、インポート時にエラーのリストが表示されます。

制限事項:

お知らせ
事前に作成されたアイテムの場合は、CSVファイルから地域の価格をインポートできます。

アイテムカタログのインポート

アイテムカタログをファイルからインポートするには:

  1. アドミンページでプロジェクトを開きます。
  2. サイドメニューで、「ストア」にクリックして仮想通貨仮想アイテム、またはバンドルセクションに移動します。
  3. アイテムをインポート」をクリックします。

  1. アクションを選択します:
    • 新規アイテムの追加 — 新しいSKUを持つアイテムのみが追加されます。
    • 新規アイテムの追加、既存アイテムの更新 — 新しいSKUのアイテムが追加され、既存のアイテムのデータが更新されます。
    • 新規アイテムの追加、既存アイテムの更新、欠落アイテムの無効化 — ファイルからSKUを持つアイテムが追加/更新されます。カタログにアイテムがあるが、ファイルにそのようなSKUがない場合、アドミンページのアイテムのステータスは一部利用可能(アイテムは個別に購入できませんが、バンドルまたはボーナスの一部として購入できます)に変更されます。

  1. インポート用のファイルを記入します:
    • ダウンロードウィンドウでファイルテンプレートをダウンロードし、以下の例に従って入力します。
    • アイテムをエクスポートし、エクスポートされたファイルをテンプレートとして使用します。
    • 独自のJSONファイルを作成し、以下の例に従って記入します。

完全なJSONファイルの例:

Copy
Full screen
Small screen

{
    "virtual_currency": [
        {
            "sku": "Gem_test_import",
            "name": {
                "en": "Gem_test_import"
            },
            "type": "virtual_currency",
            "description": {
                "en": "my test imported currency"
            },
            "image_url": "https://cdn3.xsolla.com/img/misc/merchant/default-dc-image.png",
            "description": {
                "en": "my test imported currency",
                "de": "meine importierte Testwährung"
            },
            "attributes": [],
            "is_free": false,
            "order": 1,
            "groups": [],
            "regional_prices": [],
            "prices": [
                {
                    "amount": 2,
                    "currency": "USD",
                    "is_default": true,
                    "is_enabled": true
                }
            ],
            "media_list": [],
            "vc_prices": [],
            "is_enabled": true,
            "is_show_in_store": true,
            "regions": [],
            "limits": {
                "per_user": null,
                "per_item": null,
                "recurrent_schedule": null
            },
            "periods": [],
            "inventory_options": {
                "consumable": true,
                "expiration_period": null
            },
            "is_hard": false
        }
    ],
    "virtual_items": [
        {
            "sku": "event_access_test_import",
            "name": {
                "en": "Special Event Access_test_import"
            },
            "type": "virtual_good",
            "description": {
                "en": "Get special event access as a bonus only on your first purchase. Find the right doggy at the Robo-Dog Exhibition!"
            },
            "image_url": "https://cdn3.xsolla.com/img/misc/images/1e3ef1a96cc9dd8d98bc124d5d6fad79.png",
            "long_description": null,
            "attributes": [],
            "is_free": false,
            "order": 1,
            "groups": [
                "my_test_group"
            ],
            "regional_prices": [],
            "prices": [
                {
                    "amount": 35,
                    "currency": "USD",
                    "is_default": true,
                    "is_enabled": true
                }
            ],
            "media_list": [],
            "vc_prices": [],
            "is_enabled": true,
            "is_show_in_store": true,
            "regions": [],
            "limits": {
                "per_user": null,
                "per_item": null,
                "recurrent_schedule": null
            },
            "periods": [],
            "inventory_options": {
                "consumable": true,
                "expiration_period": null
            }
        }
    ],
    "virtual_currency_packages": [
        {
            "item_id": 441982,
            "sku": "small_gold_pack_test_import",
            "type": "bundle",
            "name": {
                "en": "Small gold pack"
            },
            "bundle_type": "virtual_currency_package",
            "description": {
                "en": "Gold x100"
            },
            "image_url": "https://cdn3.xsolla.com/img/misc/images/ba43c46ea75fd5713c210f5736993a92.png",
            "vc_prices": [],
            "regional_prices": [],
            "prices": [
                {
                    "amount": 5,
                    "currency": "USD",
                    "is_default": true,
                    "is_enabled": true
                }
            ],
            "is_enabled": true,
            "is_show_in_store": true,
            "regions": [],
            "limits": {
                "per_user": null,
                "per_item": null,
                "recurrent_schedule": null
            },
            "periods": [],
            "attributes": [],
            "long_description": null,
            "media_list": [],
            "order": 100000000,
            "is_free": false,
            "groups": [],
            "content": [
                {
                    "sku": "Gem_test_import",
                    "quantity": 100
                }
            ]
        }
    ],
    "bundles": [
        {
            "item_id": 684024,
            "sku": "start_pack_test_import_test_import",
            "type": "bundle",
            "name": {
                "en": "Legendary Start Pack"
            },
            "bundle_type": "standard",
            "description": {
                "en": "Crystal x 1\nGem x 1"
            },
            "image_url": "https://cdn3.xsolla.com/img/misc/merchant/default-dc-image.png",
            "regional_prices": [],
            "prices": [
                {
                    "amount": 20,
                    "currency": "USD",
                    "is_default": true,
                    "is_enabled": true
                }
            ],
            "virtual_prices": [],
            "is_enabled": true,
            "is_show_in_store": true,
            "regions": [],
            "limits": {
                "per_user": null,
                "per_item": null,
                "recurrent_schedule": null
            },
            "periods": [],
            "attributes": [],
            "long_description": null,
            "media_list": [],
            "order": 5,
            "is_free": false,
            "groups": [
                "my_test_group"
            ],
            "content": [
                {
                    "sku": "Gem_test_import",
                    "quantity": 1
                },
                {
                    "sku": "event_access_test_import",
                    "quantity": 1
                }
            ]
        }
    ]
}

  1. インポートウィンドウの対応するフィールドに完全なファイルをアップロードします。
  2. インポート中にエラーが発生した場合は、そのエラーのリストと修正推奨事項がインポートウィンドウに表示されます。ファイルに必要な変更を加え、再度アップロードしてください。

アップロードに成功すると、指定したSKUのアイテムが作成、更新、または無効になります。

アイテムカタログのエクスポート

アイテムまたはアイテムカタログをJSONファイルにエクスポートするには:

  1. アドミンページでプロジェクトを開きます。
  2. サイドメニューで、「ストア」にクリックして仮想通貨仮想アイテム、またはバンドルセクションに移動します。
  3. アイテムをエクスポート」をクリックします。

  1. アクションを選択します:
    • すべてのアイテムのエクスポート — このプロジェクトのすべてのタイプのアイテムカタログ全体がエクスポートされます。例えば、仮想通貨セクションに移動してすべてのアイテムをエクスポートすると、JSONファイルにはプロジェクトの仮想通貨、仮想通貨パッケージ、バーチャルアイテム、ゲームキーパッケージが含まれます。
    • 選択されたアイテムのみのエクスポート — 開いたウィンドウでエクスポートするアイテムを選択します。

  1. エクスポート」をクリックします。

JSONファイルのダウンロードが自動的に開始されます。

外部プラットフォームからカタログをインポートする

外部プラットフォームからアイテムやサブスクリプションをインポートし、ユーザーインベントリを同期させることができます。

注意
インポート後、インポートソースとエクソーラのアイテムカタログとサブスクリプションに加えられた変更を、以下の方法で同期させることができます:カタログをインポートできない場合は、アドミンページまたはAPIメソッドでアイテムおよびサブスクリプションカタログを構成してください。

Google Playからカタログをインポートする

注意

インポートを開始する前に、Google PlayプロジェクトでGoogle Play Android Developer APIが有効になっていることを確認してください。https://console.developers.google.com/apis/api/androidpublisher.googleapis.com/overview?project={project_id}にアクセスしてください。project_idはGoogle PlayのプロジェクトIDです。このAPIが無効になっている場合は、有効にしてください。設定の適用には時間がかかるため、設定を有効にした直後にインポートを試みると失敗する可能性があります。数分待ってから再試行してください。

  1. アドミンページであなたのプロジェクトを開きます。
  2. サイドメニューでストアをクリックします。
  3. カラログ管理ペインで、構成するをクリックします。
  4. 外部プラットフォームとの統合 ペインで、構成するをクリックします。
  5. Google Playペインで、構成するをクリックします。
  6. アプリケーション ID — Google PlayのアプリIDを指定します。
お知らせ
アプリケーションIDは、Google Play Consoleで確認できます。サイドメニューで、すべてのアプリをクリックします。テーブルから必要なアプリを探します。そのIDは、名前とロゴの横にあるアプリの列で指定されます。
  1. 秘密鍵付きのJSONをアップロードします。
お知らせ
秘密鍵は、サービスアカウント作成時に生成されます。

  1. Google Play Consoleに移動して、サイドメニューでユーザーと権限をクリックしてサービスアカウントを新しいユーザーとして追加します。

  1. 保存するをクリックします。
  2. インポートを開始するをクリックします。カタログのインポートをすぐに開始します。
お知らせ
SKUはインポート元の製品IDに対応します。
  1. サイトビルダーで作成したウェブストアでバーチャルアイテムを販売するには、アドミンページでアイテムグループを設定し、各アイテムに1つまたは複数のグループを割り当てます
  2. アイテム画像を表示するには、アドミンページに画像をアップロードしてください。
お知らせ
バングラデシュユーザーには、カタログ価格がBDTではなく、デフォルトの通貨(USD)で表示されます。

PlayFabからカタログをインポートする

注意
サポートされているPlayFab APIバージョン:Economy v1

PlayFabは、ゲーム開発者にカタログやマネタイズを管理するためのすぐに使えるサーバーソリューションを提供しています。PlayFabとの統合後、エクソーラのソリューションを使用するために、PlayFabからストアにカタログをインポートすることができます。

お知らせ
PlayFabのプロジェクトIDと秘密プロジェクトキーが必要です。また、エクソーラにインポートしたいカタログは、PlayFabで基本(Base)として設定されている必要があります。

  1. アドミンページであなたのプロジェクトを開きます。
  2. サイドメニューストアをクリックします。
  3. カタログ管理ペインで構成するをクリックします。
  4. 外部プラットフォームとの統合ペインで構成するをクリックします。
  5. PlayFabペインで構成するをクリックします。
  6. アイテムインポートタブで以下を指定してください:
  7. 保存するをクリックします。
  8. ユーザーインベントリをPlayFabと同期させます(任意):
    1. インベントリ同期に移動して以下を指定してください:
    2. Set the PlayFabとユーザーインベントリを同期させるトグルをオンにします。
    3. 保存するをクリックします。
  9. アイテムインポートタブに移動してインポートを開始するをクリックします。カタログのインポートが自動的に始まります。
  10. サイトビルダーで作成したウェブストアで仮想アイテムを販売するには、アドミンページでアイテムグループを構成し、各アイテムに1つまたは複数のグループを割り当てます
  11. アイテム画像を表示するには、アドミンページに画像をアップロードしてください。

インポートが正常に完了したかどうかを確認するには、サイドメニューのストアセクションに移動し、仮想通貨仮想アイテムバンドルタブでアイテム、通貨、バンドルが有効になっていることを確認します。

注意
インポート結果を確認する際には、仮想通貨パッケージは1つの通貨のみを含むバンドルであることを考慮してください。PlayFabは仮想通貨RM(リアルマネー)を使用していますが、これは現実の通貨である1セント(100RM=1USD)と同等です。例えば、PlayFabから400RMをインポートした場合、あなたのアドミンページには4USDが表示されます。

カタログを再インポートする

カタログを再インポートする際には、以下の点を考慮する必要があります:

  • すでにストアに登録されているアイテムは更新されます。
  • ストアで販売していないアイテムが追加されます。
  • インポート元からすでに削除されたアイテムは、ストアに残ります。アドミンページまたはAPI経由で削除することができます。

API経由でのアイテムの自動作成

システムからのデータに基づいて複数のアイテムを作成する必要がある場合は、APIを使用してこのプロセスを自動化できます。

次のことを行う必要があります:

アイテムグループを使用する場合は、アドミンページインターフェースで事前に作成してください。

複数のタイプのアイテムを使用する場合は、次の順序で作成する必要があります:

  1. アドミンページのアイテムグループ。
  2. 仮想通貨。
  3. 仮想アイテム。
  4. 仮想通貨パッケージ。
  5. バンドル。

次は想アイテムを作成するメソッドを繰り返し呼び出して仮想アイテムを作成するスクリプトの例です。

スクリプトはJavaScriptとJavaScriptランタイムNode.jsを使って開発されています。

  1. エクソーラにHTTPリクエストを送信するために、“node-fetch”モジュールのfetch関数をインポートします。
Copy
Full screen
Small screen
import fetch from "node-fetch";
  1. リクエスト認証に必要な定数を設定します。の代わりに、プロジェクトIDとAPIキーの値を挿入し、これらは後続のAPIリクエストで使用するためにBase64でエンコードされます。
Copy
Full screen
Small screen
const projectId = <your project_id from PA>;

const apiKey = <your api key from PA>;

const buff = new Buffer(`${projectId}:${apiKey}`);

const basicAuth = buff.toString('base64')
  1. リクエストを送信する際に遅延を作成するために使用されるsleepヘルパー関数を実装します。これはAPIリクエストレート制限を超えないために必要です。
Copy
Full screen
Small screen
function sleep(ms) {

   return new Promise(resolve => setTimeout(resolve, ms));

}
  1. システムからアイテムデータを取得にはシステム固有のgetItems関数を実装します。
Copy
Full screen
Small screen
async function getItems() {

   // receive items from the original system or read from a pre-prepared file

   return items;

}
  1. 仮想アイテムを作成するAPIコールのデータフォーマットに従ってアイテムデータをフォーマットするには、システム固有のprepareData関数を実装します。
Copy
Full screen
Small screen
function prepareData(items) {

   // format items in accordance with API requirements

   return formattedItems;

}
  1. POSTリクエストをXsolla APIに送信して仮想アイテムを作成するcreateItem関数を追加します。
Copy
Full screen
Small screen
async function createItem(item) {

   const url = `https://store.xsolla.com/api/v2/project/${projectId}/admin/items/virtual_items`;



   return await fetch(url, {

       method: "POST",

       headers: {

           Authorization: "Basic " + basicAuth,

           "Content-Type": "application/json"

       },

       body: JSON.stringify(item),

   });

}
  1. 指定したSKUの仮想アイテムが存在するかどうかを確認するcheckItemExist関数を追加します。この関数はXsolla APIにGETリクエストを送信します:
    • 指定されたSKUのアイテムが見つからない場合は、404のHTTPコードの応答が受信され、作成する必要があります。
    • 200のHTTPコードを含む応答を受信した場合、指定されたSKUを持つアイテムが見つかり、作成する必要はありません。
Copy
Full screen
Small screen
async function checkItemExist(sku) {

   const url = `https://store.xsolla.com/api/v2/project/${projectId}/admin/items/virtual_items/sku/${sku}`;

   const response = await fetch(url, {

       method: "GET",

       headers: {

           Authorization: "Basic " + basicAuth

       }

   });

   return response.status !== 404;

}
  1. アイテムのリストを処理し、エクソーラ側にシステムのSKUを持つアイテムが存在するかどうかを確認するcreateItems関数を追加します。該当するSKUを持つアイテムがない場合、関数はアイテムを作成します。進行状況がコンソールに表示されます。
Copy
Full screen
Small screen
async function createItems(items) {

   let success = 0;

   let alreadyCreated = 0;

   for (let i = 0; i < items.length; i++) {

       const item = items[i];

       if (item['sku'] === undefined) {

           console.log(`${i} Field "sku" not specified`);

           continue;

       }

       const sku = item['sku'];

       if (await checkItemExist(sku)) {

           console.log(`${i} Item with sku "${sku}" already created`);

           alreadyCreated++;

           continue;

       }

       const response = await createItem(item);

       if (response.status === 201) {

           console.log(`${i} Item with sku "${sku}" successfully created`)

           success++;

       } else {

           const jsonData = await response.json();

           console.log(`${i} An error occurred while creating the items with sku "${sku}"`);

           console.log(jsonData);

       }

       // add a delay so as not to run into rate limits

       await sleep(500);

   }

   console.log(`${success} items out of ${items.length} created. ${alreadyCreated} items already existed`);

}
  1. 正しい順序で上記のすべての関数を呼び出すrun関数を追加します。
Copy
Full screen
Small screen
async function run() {

 const items = await getItems();

 const formattedItems = prepareData(items);

 await createItems(formattedItems);

}

完全なコードは:

Copy
Full screen
Small screen
import fetch from "node-fetch";

const projectId = <your project_id from PA>;
const apiKey = <your api key from PA>;
const buff = new Buffer(`${projectId}:${apiKey}`);
const basicAuth = buff.toString('base64')

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function getItems() {
    // receive items from the original system or read from a pre-prepared file
    return items;
}

function prepareData(items) {
    // format items in accordance with API requirements
    return formatedItems;
}

async function createItem(item) {
    const url = `https://store.xsolla.com/api/v2/project/${projectId}/admin/items/virtual_items`;

    return await fetch(url, {
        method: "POST",
        headers: {
            Authorization: "Basic " + basicAuth,
            "Content-Type": "application/json"
        },
        body: JSON.stringify(item),
    });
}

async function isItemExisted(sku) {
    const url = `https://store.xsolla.com/api/v2/project/${projectId}/admin/items/virtual_items/sku/${sku}`;
    const response = await fetch(url, {
        method: "GET",
        headers: {
            Authorization: "Basic " + basicAuth
        }
    });
    return response.status !== 404;
}

async function createItems(items) {
    let success = 0;
    let alreadyCreated = 0;
    for (let i = 0; i < items.length; i++) {
        const item = items[i];
        if (item['sku'] === undefined) {
            console.log(`${i} Field "sku" not specified`);
            continue;
        }
        const sku = item['sku'];
        if (await isItemExisted(sku)) {
            console.log(`${i} Item with sku "${sku}" already created`);
            alreadyCreated++;
            continue;
        }
        const response = await createItem(item);
        if (response.status === 201) {
            console.log(`${i} Item with sku "${sku}" successfully created`)
            success++;
        } else {
            const jsonData = await response.json();
            console.log(`${i} An error occurred while creating the items with sku "${sku}"`);
            console.log(jsonData);
        }
        // add a delay so as not to run into rate limits
        await sleep(500);
    }
    console.log(`${success} items out of ${items.length} created. ${alreadyCreated} items already existed`);
}

async function run() {
  const items = await getItems();
  const formattedItems = prepareData(items);
  await createItems(formattedItems);
}

run(); 
この記事は役に立ちましたか?
ありがとうございます!
改善できることはありますか? メッセージ
申し訳ありません
この記事が参考にならなかった理由を説明してください。 メッセージ
ご意見ありがとうございました!
あなたのメッセージを確認し、体験を向上させるために利用させていただきます。
最終更新日: 2024年11月8日

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

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