Skip to content

Store

Beta

The store module is currently in beta. This is an invite only feature. If you are interested in using it, please get in touch with us.

The store module offers a simplified way to sell in-game items. It can work alongside your existing Xsolla integration. Using the buyItem method is required in order to enable in-app purchases on the CrazyGames mobile app. The method is also supported on the web.

Getting started

The module can be accessed like this:

window.CrazyGames.SDK.store;

The module can be accessed like this:

CrazySDK.Store;

Consult the Demo

For a demo, please consult the CrazySDK/Demo/StoreModule scene. You can run it directly in the Unity editor.

🟥 Not supported by the GameMaker SDK.

🟥 Not supported by the Construct SDK.

🟥 Not supported by the Godot SDK.

🟥 Not supported by the Cocos SDK.

Listing the catalog

Call getCatalogItems to read the virtual items configured in your Xsolla project.

try {
    const page = await window.CrazyGames.SDK.store.getCatalogItems();
    console.log("Catalog items", page);
} catch (e) {
    console.log("Catalog error", e);
}

Prices are per user

Xsolla personalizes prices and promotions per user, so the prices you get for a signed in player can differ from the ones a signed out player sees. Always display the prices returned by getCatalogItems rather than cached or hard-coded ones, so that what you show matches what buyItem charges.

Pagination

The method accepts an optional limit and offset, and returns at most 50 items per call, which is Xsolla's own maximum.

  • limit - how many items to return, an integer between 1 and 50. Defaults to 50
  • offset - how many items to skip, an integer, 0 or greater. Defaults to 0
const page = await window.CrazyGames.SDK.store.getCatalogItems({ limit: 10, offset: 10 });

Errors

The getCatalogItems method rejects with a StoreError, for example:

{
    "code": "catalogFetchFailed",
    "message": "Could not reach the Xsolla store API."
}

Possible error codes:

  • invalidArgument - the limit or offset you passed is not an integer in the allowed range
  • requestInProgress - a catalog request is already in progress, wait for it to finish before starting a new one
  • catalogFetchFailed - the catalog could not be retrieved from Xsolla (for example a network issue, or an invalid response)
  • unexpectedError - an unexpected error occurred
  • other

Call GetCatalogItems to read the virtual items configured in your Xsolla project.

CrazySDK.Store.GetCatalogItems(
    (error, catalog) =>
    {
        if (error != null)
        {
            Debug.LogError("Catalog error: " + error);
            return;
        }

        Debug.Log($"Catalog items: {catalog.items.Count}, has more: {catalog.hasMore}");
        foreach (var item in catalog.items)
        {
            Debug.Log("Catalog item: " + item);
        }
    }
);
// or
try
{
    var catalog = await CrazySDK.Store.GetCatalogItemsAsync();
    Debug.Log($"Catalog items: {catalog.items.Count}, has more: {catalog.hasMore}");
}
catch (SdkError e)
{
    Debug.LogError("Catalog error (async): " + e);
}

Prices are per user

Xsolla personalizes prices and promotions per user, so the prices you get for a signed in player can differ from the ones a signed out player sees. Always display the prices returned by GetCatalogItems rather than cached or hard-coded ones, so that what you show matches what BuyItem charges.

Pagination

Both methods have an overload accepting a limit and an offset, and return at most 50 items per call (StoreModule.MaxCatalogLimit), which is Xsolla's own maximum.

  • limit - how many items to return, an integer between 1 and 50
  • offset - how many items to skip, an integer, 0 or greater
CrazySDK.Store.GetCatalogItems(10, 10, (error, catalog) => { /* ... */ });
// or
var catalog = await CrazySDK.Store.GetCatalogItemsAsync(10, 10);

The overloads without these parameters request the first page, with a limit of 50 and an offset of 0.

Errors

The callback receives an SdkError as the first parameter (it is null when the call succeeds). The async version throws the SdkError instead.

Possible error codes:

  • invalidArgument - the limit or offset you passed is not an integer in the allowed range
  • requestInProgress - a catalog request is already in progress, wait for it to finish before starting a new one
  • catalogFetchFailed - the catalog could not be retrieved from Xsolla (for example a network issue, or an invalid response)
  • unexpectedError - an unexpected error occurred
  • other

🟥 Not supported by the GameMaker SDK.

🟥 Not supported by the Construct SDK.

🟥 Not supported by the Godot SDK.

🟥 Not supported by the Cocos SDK.

Getting the player inventory

Call getPlayerInventory to read the virtual items the signed in player owns in your Xsolla project.

try {
    const page = await window.CrazyGames.SDK.store.getPlayerInventory();
    console.log("Inventory items", page);
} catch (e) {
    console.log("Inventory error", e);
}

Each item has a sku, name, description, imageUrl and quantity. The quantity is null when Xsolla does not count the item.

Pagination

The method accepts an optional limit and offset, and returns at most 50 items per call, which is Xsolla's own maximum.

  • limit - how many items to return, an integer between 1 and 50. Defaults to 50
  • offset - how many items to skip, an integer, 0 or greater. Defaults to 0
const page = await window.CrazyGames.SDK.store.getPlayerInventory({ limit: 10, offset: 10 });

Errors

The getPlayerInventory method rejects with a StoreError, for example:

{
    "code": "userNotAuthenticated",
    "message": "The player must be signed in to read their inventory."
}

Possible error codes:

  • userNotAuthenticated - the user must be signed in to read their inventory
  • invalidArgument - the limit or offset you passed is not an integer in the allowed range
  • inventoryFetchFailed - the inventory could not be retrieved from Xsolla (for example a network issue, or an invalid response)
  • unexpectedError - an unexpected error occurred
  • other

Call GetPlayerInventory to read the virtual items the signed in player owns in your Xsolla project.

CrazySDK.Store.GetPlayerInventory(
    (error, inventory) =>
    {
        if (error != null)
        {
            Debug.LogError("Inventory error: " + error);
            return;
        }

        foreach (var item in inventory.items)
        {
            Debug.Log("Inventory item: " + item);
        }
    }
);
// or
try
{
    var inventory = await CrazySDK.Store.GetPlayerInventoryAsync();
    Debug.Log($"Inventory items: {inventory.items.Count}");
}
catch (SdkError e)
{
    Debug.LogError("Inventory error (async): " + e);
}

Each InventoryItem has a sku, name, description, imageUrl and quantity. The quantity is 0 when Xsolla does not count the item.

Pagination

Both methods have an overload accepting a limit and an offset, and return at most 50 items per call (StoreModule.MaxCatalogLimit), which is Xsolla's own maximum.

  • limit - how many items to return, an integer between 1 and 50
  • offset - how many items to skip, an integer, 0 or greater
CrazySDK.Store.GetPlayerInventory(10, 10, (error, inventory) => { /* ... */ });
// or
var inventory = await CrazySDK.Store.GetPlayerInventoryAsync(10, 10);

The overloads without these parameters request the first page, with a limit of 50 and an offset of 0.

Errors

The callback receives an SdkError as the first parameter (it is null when the call succeeds). The async version throws the SdkError instead.

Possible error codes:

  • userNotAuthenticated - the user must be signed in to read their inventory
  • invalidArgument - the limit or offset you passed is not an integer in the allowed range
  • requestInProgress - an inventory request is already in progress, wait for it to finish before starting a new one
  • inventoryFetchFailed - the inventory could not be retrieved from Xsolla (for example a network issue, or an invalid response)
  • unexpectedError - an unexpected error occurred
  • other

🟥 Not supported by the GameMaker SDK.

🟥 Not supported by the Construct SDK.

🟥 Not supported by the Godot SDK.

🟥 Not supported by the Cocos SDK.

Buying an item

Call buyItem with the item ID configured in your Xsolla project. The method opens the Xsolla Pay Station widget and resolves once the purchase is completed. Only one purchase can be in progress at a time.

try {
    const result = await window.CrazyGames.SDK.store.buyItem("your_item_id");
    console.log("Purchase completed", result); // { itemId: "your_item_id" }
    // the item can now be found in the Xsolla inventory
} catch (e) {
    console.log("Purchase error", e);
}

Warning

A successful buyItem call means the payment flow completed, but you should always confirm ownership on your back-end (or via the Xsolla inventory API) before granting valuable items. Never rely solely on the client-side result to unlock content.

Errors

The buyItem method rejects with a StoreError, for example:

{
    "code": "purchaseCancelled",
    "message": "The purchase was cancelled."
}

Possible error codes:

  • userNotAuthenticated - the user must be signed in to make a purchase
  • purchaseInitFailed - something went wrong while initiating the purchase with Xsolla
  • purchaseInProgress - a purchase is already in progress, wait for it to finish before starting a new one
  • purchaseCancelled - the user closed the payment widget without completing the purchase
  • unexpectedError - an unexpected error occurred (for example a network issue, or the payment widget failed to load)
  • other

Call BuyItem with the item ID configured in your Xsolla project. The method opens the Xsolla Pay Station widget and invokes the callback once the purchase is completed. Only one purchase can be in progress at a time.

CrazySDK.Store.BuyItem(
    "your_item_id",
    (error, result) =>
    {
        if (error != null)
        {
            Debug.LogError("Purchase error: " + error);
            return;
        }
        Debug.Log("Purchase completed: " + result);
        // the item can now be found in the Xsolla inventory
    }
);
// or
try
{
    var result = await CrazySDK.Store.BuyItemAsync("your_item_id");
    Debug.Log("Purchase completed: " + result);
}
catch (SdkError e)
{
    Debug.LogError("Purchase error (async): " + e);
}

Warning

A successful BuyItem call means the payment flow completed, but you should always confirm ownership on your back-end (or via the Xsolla inventory API) before granting valuable items. Never rely solely on the client-side result to unlock content.

Errors

The callback receives an SdkError as the first parameter (it is null when the purchase succeeds). The async version throws the SdkError instead.

Possible error codes:

  • userNotAuthenticated - the user must be signed in to make a purchase
  • purchaseInitFailed - something went wrong while initiating the purchase with Xsolla
  • purchaseInProgress - a purchase is already in progress, wait for it to finish before starting a new one
  • purchaseCancelled - the user closed the payment widget without completing the purchase
  • unexpectedError - an unexpected error occurred (for example a network issue, or the payment widget failed to load)
  • other

🟥 Not supported by the GameMaker SDK.

🟥 Not supported by the Construct SDK.

🟥 Not supported by the Godot SDK.

🟥 Not supported by the Cocos SDK.

Consuming an item

Call consumeItem with the item SKU and the quantity to remove from the signed in player's inventory, for example when the player uses a potion or spends a booster. The item must be configured as consumable in your Xsolla project.

try {
    await window.CrazyGames.SDK.store.consumeItem("your_item_sku", 1);
    console.log("Item consumed");
    // apply the effect of the item in your game
} catch (e) {
    console.log("Consume error", e);
}
  • sku - the SKU of the item, as configured in your Xsolla project
  • quantity - how many units to consume, an integer, 1 or greater

Errors

The consumeItem method rejects with a StoreError, for example:

{
    "code": "insufficientItemQuantity",
    "message": "The player does not own 3 of your_item_sku."
}

Possible error codes:

  • userNotAuthenticated - the user must be signed in to consume an item
  • invalidArgument - the sku is not a non-empty string, or the quantity is not an integer of 1 or greater
  • itemNotConsumable - the item is not configured as consumable in your Xsolla project
  • itemNotInInventory - the player does not own the item
  • insufficientItemQuantity - the player owns the item, but less than the requested quantity
  • consumeItemFailed - the item could not be consumed on Xsolla (for example a network issue)
  • unexpectedError - an unexpected error occurred
  • other

Call ConsumeItem with the item SKU and the quantity to remove from the signed in player's inventory, for example when the player uses a potion or spends a booster. The item must be configured as consumable in your Xsolla project. Only one consume request can be in progress at a time.

CrazySDK.Store.ConsumeItem(
    "your_item_sku",
    1,
    (error) =>
    {
        if (error != null)
        {
            Debug.LogError("Consume error: " + error);
            return;
        }
        Debug.Log("Item consumed");
        // apply the effect of the item in your game
    }
);
// or
try
{
    await CrazySDK.Store.ConsumeItemAsync("your_item_sku", 1);
    Debug.Log("Item consumed");
}
catch (SdkError e)
{
    Debug.LogError("Consume error (async): " + e);
}
  • sku - the SKU of the item, as configured in your Xsolla project
  • quantity - how many units to consume, 1 or greater

Errors

The callback receives an SdkError (it is null when the call succeeds). The async version throws the SdkError instead.

Possible error codes:

  • userNotAuthenticated - the user must be signed in to consume an item
  • invalidArgument - the sku is empty, or the quantity is less than 1
  • itemNotConsumable - the item is not configured as consumable in your Xsolla project
  • itemNotInInventory - the player does not own the item
  • insufficientItemQuantity - the player owns the item, but less than the requested quantity
  • requestInProgress - a consume request is already in progress, wait for it to finish before starting a new one
  • consumeItemFailed - the item could not be consumed on Xsolla (for example a network issue)
  • unexpectedError - an unexpected error occurred
  • other

🟥 Not supported by the GameMaker SDK.

🟥 Not supported by the Construct SDK.

🟥 Not supported by the Godot SDK.

🟥 Not supported by the Cocos SDK.

Sandbox mode

While developing, enable sandbox mode so purchases run against Xsolla's test environment, allowing you to buy items with fake money.

window.CrazyGames.SDK.store.setSandbox(true);

While developing, enable sandbox mode so purchases run against Xsolla's test environment, allowing you to buy items with fake money.

CrazySDK.Store.SetSandbox(true);

🟥 Not supported by the GameMaker SDK.

🟥 Not supported by the Construct SDK.

🟥 Not supported by the Godot SDK.

🟥 Not supported by the Cocos SDK.

Local Testing

When the SDK is in the local environment (on 127.0.0.1 or localhost), buyItem always simulates a successful purchase, getCatalogItems returns a fake catalog of three items (a regular one, a discounted one and a free one, honoring limit and offset), getPlayerInventory returns a fake inventory of two items (honoring limit and offset), consumeItem always simulates a successful consume, and setSandbox only logs the new value.

When you are running the game in the editor, BuyItem returns a hard-coded response, GetCatalogItems returns a fake catalog of three items (a regular one, a discounted one and a free one, honoring limit and offset), GetPlayerInventory returns a fake inventory of two items (honoring limit and offset), ConsumeItem always simulates a successful consume, and SetSandbox only logs the new value.

You can customize the response returned by BuyItem with the Buy Item Response field in the CrazySDK/Resources/CrazyGamesSettings object. The available values are:

  • Success - returns a successful PurchaseResult for the requested item ID
  • PurchaseCancelled - returns the purchaseCancelled error
  • UserLoggedOut - returns the userNotAuthenticated error
  • UnexpectedError - returns the unexpectedError error

🟥 Not supported by the GameMaker SDK.

🟥 Not supported by the Construct SDK.

🟥 Not supported by the Godot SDK.

🟥 Not supported by the Cocos SDK.

Ask AI