카탈로그 가져오기

JSON 가져오기를 사용하여 아이템 카탈로그를 생성 및 업데이트

JSON 파일에서 가져오기를 사용하여 항목을 생성, 업데이트 또는 비활성화할 수 있습니다.

알림
API 호출 또는 관리자 페이지에서 수동으로 항목을 생성, 업데이트 또는 비활성화할 수 있습니다. 단, 각 항목에 대해 별도의 요청 또는 작업을 수행해야 합니다. 가져오기를 사용하면 단일 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 파일 다운로드가 자동으로 시작됩니다.

외부 플랫폼에서 카탈로그 가져오기

외부 플랫폼에서 아이템 및 정기 결제을 가져와서 사용자 인벤토리를 동기화할 수 있습니다.

주의
가져온 다음, 다음과 같은 방법으로 가져오기 원본 및 Xsolla에서 아이템 카탈로그 및 정기 결제 변경 사항을 동기화할 수 있습니다. 방법:카탈로그를 가져올 수 없는 경우 게시자 계정에서 아이템 및 정기 결제 카탈로그를 구성하거나 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가 비활성화되어 있으면 활성화해 주세요. 설정이 적용되는 데 시간이 다소 걸리므로 설정을 활성화한 후 바로 시도하면 가져오기가 실패할 수 있습니다. 몇 분 정도 기다렸다가 다시 시도해 주세요.

  1. 관리자 페이지에서 프로젝트를 엽니다.
  2. 측면 메뉴에서 스토어를 클릭합니다.
  3. 카탈로그 관리 창에서, 구성을 클릭합니다.
  4. 외부 플랫폼과 통합 창에서, 구성을 클릭합니다.
  5. Google Play 창에서, 구성을 클릭합니다.
  6. 애플리케이션 ID를 지정합니다 — Google Play의 앱 ID입니다.
알림
Google Play Console에서 애플리케이션 ID를 찾을 수 있습니다. 측면 메뉴에서, All apps를 클릭합니다. 표에서 필요한 앱을 찾습니다. ID는 이름과 로고 옆의 App 열에 지정됩니다.
  1. 개인 키로 JSON 업로드.
알림
서비스 계정 생성 시 개인 키가 생성됩니다.

  1. Google Play Console로 이동한 후 사이드 메뉴에서 사용자 및 권한을 클릭하고 서비스 계정을 새 사용자로 추가합니다.

  1. 저장을 클릭하고.
  2. 가져오기 시작을 클릭합니다. 카탈로그 가져오기가 즉시 시작됩니다.
알림
SKU 는 가져오기 소스의 제품 ID 에 해당합니다.
  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. PlayFab과 사용자 인벤토리 동기화 토글을 켜기로 설정합니다.
    3. 저장을 클릭합니다.
  9. 아이템 가져오기 탭으로 이동해 가져오기 시작을 클릭합니다. 카탈로그 가져오기가 즉시 시작됩니다.
  10. 웹사이트 빌더로 생성한 웹 스토어에서 가상 아이템을 판매하려면 관리자 페이지에서 아이템 그룹을 구성한 후 각 아이템마다 하나 이상의 그룹을 할당합니다.
  11. 아이템 이미지를 표시하려면, 관리자 페이지에 이미지를 업로드합니다.

가져오기가 성공적으로 완료되었는지 확인하고, 사이드 메뉴의 스토어 섹션으로 이동하여 아이템, 통화 및 번들이 가상 통화, 가상 아이템, 및 번들 탭에 활성화되어 있는지 확인합니다.

주의
가져오기 결과 확인 시, 가상 통화 패키지가 하나의 통화만 포함하는 번들인지를 고려하세요. PlayFab 은 실제 통화에 상당하는 가상 통화 RM (실제 돈) — 1 센트 (100 RM = 1 USD)을 사용합니다. 예를 들어, PlayFab 에서 400 RM 을 가져오면, 관리자 페이지에서 4달러가 보입니다.

카탈로그 다시 가져오기

카탈로그를 다시 가져올 경우 다음 사항을 고려해야 합니다.

  • 스토어에서 이미 있는 아이템이 업데이트됩니다.
  • 스토어에서 사용할 수 없는 아이템이 추가됩니다.
  • 가져오기 소스에서 이미 제거된 아이템이 스토어에 남아 있게 됩니다. 관리자 페이지에서 이를 삭제하거나 API를 통해 이를 삭제할 수 있습니다.

API를 통한 아이템 생성 자동화

시스템에서 데이터를 기반으로 다수의 아이템을 생성해야 하는 경우 API를 사용하여 이 프로세스를 자동화할 수 있습니다.

필요한 작업:

아이템 그룹을 사용하려면 관리자 페이지 인터페이스에서 아이템 그룹을 미리 생성하세요.

여러 유형의 아이템을 사용하려면 다음 순서로 생성해야 합니다.

  1. 관리자 페이지의 아이템 그룹
  2. 인게임 재화
  3. 가상 아이템
  4. 인게임 재화 패키지.
  5. 번들

다음은 가상 아이템 생성 메소드를 반복적으로 호출하여 가상 아이템을 생성하는 스크립트의 예시입니다.

이 스크립트는 JavaScript와 JavaScript 런타임인 Node.js를 사용하여 개발되었습니다.

  1. “node-fetch” 모듈의 fetch 함수를 가져와서 엑솔라 서버로 HTTP 요청을 전송합니다.
Copy
Full screen
Small screen
import fetch from "node-fetch";
  1. 요청 인증에 필요한 상수를 설정합니다. <your project_id from PA><your api key from PA> 대신 프로젝트 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. 가상 아이템을 생성하기 위해 엑솔라 API에 POST 요청을 전송하는 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 함수를 추가합니다. 이 함수는 엑솔라 API에 GET 요청을 보냅니다.
    • 404 HTTP 코드가 포함된 응답이 수신되면 지정된 SKU를 가진 아이템을 찾을 수 없으므로 해당 아이템을 생성해야 합니다.
    • 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일

오자 또는 기타 텍스트 오류를 찾으셨나요? 텍스트를 선택하고 컨트롤+엔터를 누르세요.

문제 보고
콘텐츠를 항상 검토합니다. 여러분의 피드백은 콘텐츠를 개선에 도움이 됩니다.
후속 조치를 위해 이메일을 제공해 주세요
의견을 보내 주셔서 감사드립니다!