# Virtual Store

**URL:** https://heroiclabs.com/docs/hiro/unity/economy/virtual-store/
**Keywords:** virtual store, hiro
**Categories:** hiro, unity, virtual-store

---


# Virtual Store

## Listing store items

You can list available store items.

```csharp
foreach (var storeItem in economySystem.StoreItems)
{
    Debug.Log($"{storeItem.Name} - {storeItem.Description}). Cost: ");

    if (!string.IsNullOrEmpty(storeItem.Cost.Sku))
    {
        Debug.Log($"{storeItem.Cost.Sku}");
    }
    else
    {
        foreach (var currencyKvp in storeItem.Cost.Currencies)
        {
            Debug.Log($"{currencyKvp.Key}: {currencyKvp.Value}");
        }
    }
}
```

## Refreshing the store

You can refresh the economy system's store data.

```csharp
await economySystem.RefreshStoreAsync();
```

## Making a purchase intent

You can make a purchase intent for a user, which is useful to differentiate product purchases that use the same SKU code.

```csharp
await economySystem.PurchaseIntentAsync(storeItem);
```

Alternatively you can specify a store item id and SKU code.

```csharp
await economySystem.PurchaseIntentAsync("<itemId1>", "<sku>");
```

## Purchasing a store item

You can purchase a store item for a user.

```csharp
await economySystem.PurchaseStoreItemAsync("<itemId1>", "<receipt>");
```

## Getting the active store type

You can get the active store type.

```csharp
Debug.Log($"Active store type is {economySystem.ActiveStoreType}");
```

## Filtering store items by category

Filter the cached store items to a specific category using `GetStoreItemsByCategory`.

```csharp
var items = economySystem.GetStoreItemsByCategory("coin_packs");
foreach (var item in items)
{
    Debug.Log($"{item.Name} - {item.Description}");
}
```
Passing an empty or null category returns all store items.

## Purchasing store items

The purchase flow depends on whether the store item is configured for game currency purchase (no `sku`) or in-app purchase (has `sku`). See [Virtual Store purchases](/hiro/concepts/economy/virtual-store/#purchases) for details on how SKU configuration affects purchases.

This example shows how to handle both purchase types based on the store item's configuration:

```csharp
public async Task BuyStoreItem(EconomyListStoreItem storeItem)
{
    if (string.IsNullOrEmpty(storeItem.Cost.Sku))
    {
        // Soft currency purchase - server deducts currency and grants reward
        IEconomyPurchaseAck result = await _economySystem.PurchaseStoreItemAsync(storeItem.Id);

        // Show reward animation UI.
        ShowRewardAnimationUI(result.Reward); // Your custom function.
    }
    else
    {
        // Hard currency purchase - requires platform IAP flow
        try
        {
            var result = await _unityPurchasingSystem.BuyProductByIdAsync(storeItem.Id);
            AnalyticsSendReceipt(result.receipt); // Your custom function.

            // Show reward animation UI.
            ShowRewardAnimationUI(storeItem.Reward); // Your custom function.
        }
        catch (PurchaseFailureException e)
        {
            switch (e.Reason)
            {
                case UnityEngine.Purchasing.PurchaseFailureReason.UserCancelled:
                    // Popup some UI.
                    break;
                case UnityEngine.Purchasing.PurchaseFailureReason.PaymentDeclined:
                    // Popup some UI.
                    break;
                case UnityEngine.Purchasing.PurchaseFailureReason.ExistingPurchasePending:
                    // Popup some UI.
                    break;
                case UnityEngine.Purchasing.PurchaseFailureReason.PurchasingUnavailable:
                case UnityEngine.Purchasing.PurchaseFailureReason.ProductUnavailable:
                case UnityEngine.Purchasing.PurchaseFailureReason.SignatureInvalid:
                case UnityEngine.Purchasing.PurchaseFailureReason.DuplicateTransaction:
                case UnityEngine.Purchasing.PurchaseFailureReason.Unknown:
                    break;
            }
        }
    }
}
```

{{< note "important" >}}
Soft currency purchases will fail if the store item has a `sku` but you haven't configured IAP validation on your server. Remove the `sku` from items that should only be purchasable with soft currency.
{{< /note >}}
