エクソーラカタログをインポート
JSONインポートを使用してアイテムカタログを作成および更新する
JSONファイルからのインポートを使用して、アイテムの作成、更新、非アクティブ化を行うことができます。
このツールを使用すると、次のことが可能になります:
機能:
- 以下のタイプのアイテムをサポート:
- 仮想アイテム
- 仮想通貨
- 仮想通貨パッケージ
- バンドル
- データの検証。ファイルの構造やデータ形式が要件を満たしていない場合、インポート時にエラーのリストが表示されます。
制限事項:
- インポートはゲームキー、プロモーション、リワードシステムには利用できません。
- アップロードするJSONファイルのサイズは7MBを超えないようにしてください。
- JSONファイルのパラメータ形式は、対応する製品作成方法で指定された形式と一致している必要があります:
アイテムカタログのインポート
アイテムカタログをファイルからインポートするには:
- アドミンページでプロジェクトを開きます。
- サイドメニューで、「ストア」にクリックして仮想通貨、仮想アイテム、またはバンドルセクションに移動します。
- 「アイテムをインポート」をクリックします。
- アクションを選択します:
- 新規アイテムの追加 — 新しいSKUを持つアイテムのみが追加されます。
- 新規アイテムの追加、既存アイテムの更新 — 新しいSKUのアイテムが追加され、既存のアイテムのデータが更新されます。
- 新規アイテムの追加、既存アイテムの更新、欠落アイテムの無効化 — ファイルからSKUを持つアイテムが追加/更新されます。カタログにアイテムがあるが、ファイルにそのようなSKUがない場合、アドミンページのアイテムのステータスは一部利用可能(アイテムは個別に購入できませんが、バンドルまたはボーナスの一部として購入できます)に変更されます。
- インポート用のファイルを記入します:
- ダウンロードウィンドウでファイルテンプレートをダウンロードし、以下の例に従って入力します。
- アイテムをエクスポートし、エクスポートされたファイルをテンプレートとして使用します。
- 独自のJSONファイルを作成し、以下の例に従って記入します。
完全なJSONファイルの例:
- json
{
"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
}
]
}
]
}
- インポートウィンドウの対応するフィールドに完全なファイルをアップロードします。
- インポート中にエラーが発生した場合は、そのエラーのリストと修正推奨事項がインポートウィンドウに表示されます。ファイルに必要な変更を加え、再度アップロードしてください。
アップロードに成功すると、指定したSKUのアイテムが作成、更新、または無効になります。
アイテムカタログのエクスポート
アイテムまたはアイテムカタログをJSONファイルにエクスポートするには:
- アドミンページでプロジェクトを開きます。
- サイドメニューで、「ストア」にクリックして仮想通貨、仮想アイテム、またはバンドルセクションに移動します。
- 「アイテムをエクスポート」をクリックします。
- アクションを選択します:
- すべてのアイテムのエクスポート — このプロジェクトのすべてのタイプのアイテムカタログ全体がエクスポートされます。例えば、仮想通貨セクションに移動してすべてのアイテムをエクスポートすると、JSONファイルにはプロジェクトの仮想通貨、仮想通貨パッケージ、バーチャルアイテム、ゲームキーパッケージが含まれます。
- 選択されたアイテムのみのエクスポート — 開いたウィンドウでエクスポートするアイテムを選択します。
- 「エクスポート」をクリックします。
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が無効になっている場合は、有効にしてください。設定の適用には時間がかかるため、設定を有効にした直後にインポートを試みると失敗する可能性があります。数分待ってから再試行してください。
- アドミンページであなたのプロジェクトを開きます。
- サイドメニューでストアをクリックします。
- カラログ管理ペインで、構成するをクリックします。
- 外部プラットフォームとの統合 ペインで、構成するをクリックします。
- Google Playペインで、構成するをクリックします。
- アプリケーション ID — Google PlayのアプリIDを指定します。
- 秘密鍵付きのJSONをアップロードします。
- Google Play Consoleに移動して、サイドメニューでユーザーと権限をクリックしてサービスアカウントを新しいユーザーとして追加します。
- 保存するをクリックします。
- インポートを開始するをクリックします。カタログのインポートをすぐに開始します。
- サイトビルダーで作成したウェブストアでバーチャルアイテムを販売するには、アドミンページでアイテムグループを設定し、各アイテムに1つまたは複数のグループを割り当てます。
- アイテム画像を表示するには、アドミンページに画像をアップロードしてください。
PlayFabからカタログをインポートする
PlayFabは、ゲーム開発者にカタログやマネタイズを管理するためのすぐに使えるサーバーソリューションを提供しています。PlayFabとの統合後、エクソーラのソリューションを使用するために、PlayFabからストアにカタログをインポートすることができます。
- アドミンページであなたのプロジェクトを開きます。
- サイドメニューストアをクリックします。
- カタログ管理ペインで構成するをクリックします。
- 外部プラットフォームとの統合ペインで構成するをクリックします。
- PlayFabペインで構成するをクリックします。
- アイテムインポートタブで以下を指定してください:
- タイトルID — PlayfabでのプロジェクトID。
- 秘密鍵 — PlayFabのプロジェクトのキー。
- 保存するをクリックします。
- ユーザーインベントリをPlayFabと同期させます(任意):
- インベントリ同期に移動して以下を指定してください:
- タイトルID — PlayfabでのプロジェクトID。
- 秘密鍵 — PlayFabのプロジェクトのキー。
- Set the PlayFabとユーザーインベントリを同期させるトグルをオンにします。
- 保存するをクリックします。
- インベントリ同期に移動して以下を指定してください:
- アイテムインポートタブに移動してインポートを開始するをクリックします。カタログのインポートが自動的に始まります。
- サイトビルダーで作成したウェブストアで仮想アイテムを販売するには、アドミンページでアイテムグループを構成し、各アイテムに1つまたは複数のグループを割り当てます。
- アイテム画像を表示するには、アドミンページに画像をアップロードしてください。
インポートが正常に完了したかどうかを確認するには、サイドメニューのストアセクションに移動し、仮想通貨、仮想アイテム、バンドルタブでアイテム、通貨、バンドルが有効になっていることを確認します。
カタログを再インポートする
カタログを再インポートする際には、以下の点を考慮する必要があります:
- すでにストアに登録されているアイテムは更新されます。
- ストアで販売していないアイテムが追加されます。
- インポート元からすでに削除されたアイテムは、ストアに残ります。アドミンページまたはAPI経由で削除することができます。
API経由でのアイテムの自動作成
システムからのデータに基づいて複数のアイテムを作成する必要がある場合は、APIを使用してこのプロセスを自動化できます。
次のことを行う必要があります:
- システムからアイテムデータをエクスポートします。
- エクスポートされたデータを、必須なアイテムタイプのAPIメソッドのデータ形式に一致する形式に変換します。
- エクスポートの各アイテムについて、必須なAPIメソッドを呼び出すスクリプトを作成します:
アイテムグループを使用する場合は、アドミンページインターフェースで事前に作成してください。
複数のタイプのアイテムを使用する場合は、次の順序で作成する必要があります:
- アドミンページのアイテムグループ。
- 仮想通貨。
- 仮想アイテム。
- 仮想通貨パッケージ。
- バンドル。
次は想アイテムを作成するメソッドを繰り返し呼び出して仮想アイテムを作成するスクリプトの例です。
スクリプトはJavaScriptとJavaScriptランタイムNode.jsを使って開発されています。
- エクソーラにHTTPリクエストを送信するために、
“node-fetch”
モジュールのfetch
関数をインポートします。
- javascript
import fetch from "node-fetch";
- リクエスト認証に必要な定数を設定します。
と の代わりに、プロジェクトIDとAPIキーの値を挿入し、これらは後続のAPIリクエストで使用するためにBase64でエンコードされます。
- javascript
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')
- リクエストを送信する際に遅延を作成するために使用される
sleep
ヘルパー関数を実装します。これはAPIリクエストレート制限を超えないために必要です。
- javascript
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
- システムからアイテムデータを取得にはシステム固有の
getItems
関数を実装します。
- javascript
async function getItems() {
// receive items from the original system or read from a pre-prepared file
return items;
}
- 仮想アイテムを作成するAPIコールのデータフォーマットに従ってアイテムデータをフォーマットするには、システム固有の
prepareData
関数を実装します。
- javascript
function prepareData(items) {
// format items in accordance with API requirements
return formattedItems;
}
POST
リクエストをXsolla APIに送信して仮想アイテムを作成するcreateItem
関数を追加します。
- javascript
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),
});
}
- 指定したSKUの仮想アイテムが存在するかどうかを確認する
checkItemExist
関数を追加します。この関数はXsolla APIにGET
リクエストを送信します:- 指定されたSKUのアイテムが見つからない場合は、
404
のHTTPコードの応答が受信され、作成する必要があります。 200
のHTTPコードを含む応答を受信した場合、指定されたSKUを持つアイテムが見つかり、作成する必要はありません。
- 指定されたSKUのアイテムが見つからない場合は、
- javascript
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;
}
- アイテムのリストを処理し、エクソーラ側にシステムのSKUを持つアイテムが存在するかどうかを確認する
createItems
関数を追加します。該当するSKUを持つアイテムがない場合、関数はアイテムを作成します。進行状況がコンソールに表示されます。
- javascript
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`);
}
- 正しい順序で上記のすべての関数を呼び出す
run
関数を追加します。
- javascript
async function run() {
const items = await getItems();
const formattedItems = prepareData(items);
await createItems(formattedItems);
}
完全なコードは:
- javascript
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();
誤字脱字などのテキストエラーを見つけましたか? テキストを選択し、Ctrl+Enterを押します。