카탈로그 가져오기
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 안드로이드 개발자 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로 이동한 후 사이드 메뉴에서 사용자 및 권한을 클릭하고 서비스 계정을 새 사용자로 추가합니다.
- 저장을 클릭하고.
- 가져오기 시작을 클릭합니다. 카탈로그 가져오기가 즉시 시작됩니다.
- 웹사이트 빌더로 생성한 웹 스토어에서 가상 아이템을 판매하려면 관리자 페이지에서 아이템 그룹을 구성한 후 각 아이템마다 하나 이상의 그룹을 할당합니다.
- 아이템 이미지를 표시하려면 자신의 관리자 페이지에 이미지를 업로드합니다.
PlayFab 카탈로그 가져오기
PlayFab 은 게임 개발자에게 카탈로그 및 수익 창출 관리를 위한, 이미 준비된 서버 솔루션을 제공합니다. PlayFab 과 통합 이후, 엑솔라 솔루션을 사용하여 카탈로그를 PlayFab 에서 스토어로 가져올 수 있습니다.
- 관리자 페이지에서 프로젝트를 엽니다.
- 측면 메뉴에서 저장을 클릭합니다.
- 카탈로그 관리 창에서, 구성을 클릭합니다.
- 외부 플랫폼과 통합 창에서, 구성을 클릭합니다.
- PlayFab 창에서, 구성을 클릭합니다.
- 아이템 가져오기 탭에서 다음을 지정합니다:
- 타이틀 ID — PlayFab 프로젝트 ID.
- 비밀 키 — PlayFab 프로젝트 키.
- 저장을 클릭합니다.
- PlayFab과 사용자 인벤토리를 동기화합니다 (선택 사항):
- 인벤토리 동기화로 이동해 다음을 지정합니다:
- 타이틀 ID — PlayFab 프로젝트 ID.
- 비밀 키 — PlayFab 프로젝트 비밀 키.
- PlayFab과 사용자 인벤토리 동기화 토글을 켜기로 설정합니다.
- 저장을 클릭합니다.
- 인벤토리 동기화로 이동해 다음을 지정합니다:
- 아이템 가져오기 탭으로 이동해 가져오기 시작을 클릭합니다. 카탈로그 가져오기가 즉시 시작됩니다.
- 웹사이트 빌더로 생성한 웹 스토어에서 가상 아이템을 판매하려면 관리자 페이지에서 아이템 그룹을 구성한 후 각 아이템마다 하나 이상의 그룹을 할당합니다.
- 아이템 이미지를 표시하려면, 관리자 페이지에 이미지를 업로드합니다.
가져오기가 성공적으로 완료되었는지 확인하고, 사이드 메뉴의 스토어 섹션으로 이동하여 아이템, 통화 및 번들이 가상 통화, 가상 아이템, 및 번들 탭에 활성화되어 있는지 확인합니다.
카탈로그 다시 가져오기
카탈로그를 다시 가져올 경우 다음 사항을 고려해야 합니다.
- 스토어에서 이미 있는 아이템이 업데이트됩니다.
- 스토어에서 사용할 수 없는 아이템이 추가됩니다.
- 가져오기 소스에서 이미 제거된 아이템이 스토어에 남아 있게 됩니다. 관리자 페이지에서 이를 삭제하거나 API를 통해 이를 삭제할 수 있습니다.
API를 통한 아이템 생성 자동화
시스템에서 데이터를 기반으로 다수의 아이템을 생성해야 하는 경우 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 키 값을 입력하면 나중에 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;
}
- 가상 아이템을 생성하기 위해 엑솔라 API에
POST
요청을 전송하는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
함수를 추가합니다. 이 함수는 엑솔라 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;
}
- 아이템 목록을 살펴보고 엑솔라 측 시스템에 해당 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();
오자 또는 기타 텍스트 오류를 찾으셨나요? 텍스트를 선택하고 컨트롤+엔터를 누르세요.