导入目录
通过JSON导入来创建和更新商品目录
您可以通过从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,在侧边栏中单击Users and permissions,然后将服务帐户添加为新用户。
- 单击保存。
- 单击开始导入。目录导入将立即开始。
- 要在通过建站器创建的网页商城中销售虚拟物品,请在发布商帐户中配置物品组,然后为每个物品分配一个或多个组。
- 要显示物品图片,请在您的发布商帐户中上传图片。
从PlayFab导入目录
PlayFab为游戏开发者提供现成可用的服务器解决方案,用于目录管理与游戏营收。集成PlayFab后,您可以从PlayFab导入目录到商店以使用艾克索拉解决方案。
- 在发布商帐户中打开您的项目。
- 在侧边栏中单击商店。
- 在目录管理窗格中,单击配置。
- 在与外部平台集成窗格中,单击配置。
- 在PlayFab窗格中,单击配置。
- 在商品导入选项卡中指定:
- 游戏ID — PlayFab中的项目ID。
- 密钥 — PlayFab中的项目密钥。
- 单击保存。
- 让用户物品库与PlayFab同步(可选):
- 前往物品库同步并指定:
- 游戏ID — PlayFab中的项目ID。
- 密钥 — PlayFab中的项目密钥。
- 将用户物品库与PlayFab同步开关设置为开。
- 单击保存。
- 前往物品库同步并指定:
- 前往商品导入选项卡,然后单击开始导入。目录导入将立即开始。
- 要在通过建站器创建的网页商城中销售虚拟物品,请在发布商帐户中配置物品组,然后为每个物品分配一个或多个组。
- 要显示物品图片,请在您的发布商帐户中上传图片。
要检查导入是否成功完成,请前往侧边栏中的商店部分,确保虚拟货币、虚拟物品和捆绑包选项卡中启用了虚拟物品、货币和捆绑包。
重新导入目录
重新导入目录时,需考虑以下情况:
- 已在商店中的商品将被更新。
- 不在商店中的商品将被添加。
- 已从导入源中删除的商品将保留在商店中。您可以在发布商帐户中删除或通过API删除。
通过API自动创建商品
如需根据自己系统的数据创建大量商品,可使用API自动化该过程。
您需要:
如要使用商品组,请预先通过发布商帐户界面创建组。
如要使用多种商品类型,应按照下列顺序进行创建:
- 在发布商帐户中创建商品组。
- 虚拟货币。
- 虚拟物品。
- 虚拟货币套餐。
- 捆绑包。
下面是一个脚本示例,它重复调用创建虚拟物品方法来创建虚拟物品。
该脚本使用JavaScript和JavaScript运行时引擎 — Node.js开发。
- 导入
“node-fetch”
模块的fetch
函数以向艾克索拉服务器发送HTTP请求。
- javascript
import fetch from "node-fetch";
- 设置请求授权所需的常量。不要插入
<your project_id from PA>
和<your api key from PA>
,而应插入项目ID和API密钥的值,它们将使用Base64编码以便后续在API请求中使用。
- 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;
}
- 实现您系统专用的
prepareData
函数以根据创建虚拟物品API调用中的数据格式来格式化商品数据。
- javascript
function prepareData(items) {
// format items in accordance with API requirements
return formattedItems;
}
- 添加
createItem
函数,它向艾克索拉API发送POST
请求来创建虚拟物品
- 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),
});
}
- 添加
checkItemExist
函数,它检查指定SKU的虚拟物品是否存在。该函数向艾克索拉API发送一个GET
请求:- 如收到包含
404
HTTP代码的响应,说明指定SKU的商品不存在,需要创建。 - 如收到包含
200
HTTP代码的响应,说明找到了指定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;
}
- 添加
createItems
函数,它检查商品列表以查找艾克索拉侧是否存在您系统中SKU指定的商品。如没有该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。