Skip to content

Payments

Setup

  1. Open the Platforms section and add all the information about the Platform where the game is available. It's required to validate the purchases.
  2. Open the Products section and fill in all the information about your game's products. In most cases, you need the main table. However, if you have a different product ID, Name, or Price for other platforms, you can use the override section for each of the platforms.

Products versioning

If you add/delete products on the products page, users will see these changes even without deploy.

The same applies to migration. Let's say you want to migrate from the stage to the production environment. But you deleted a product on stage. After the migration, all current users on production will see the new products list without the deleted product.

Make changes with care

Be specifically care when you delete products.

Where to find needed data for validation for specific platforms?

Google Play

For Android, we need a License key.

  1. Open Play Console and select the app you want to find the license key for.
  2. Go to the Monetization setup page (Monetize ► Monetization setup).
  3. Your license key is under «Licensing».
  4. To properly check if the test account made the payment, you need to give us access to service account.
    • Create a service account.
    • Link it to the google play dev account.
    • In the dev console, on /api-access page go to the permissions. Service account
    • Give it needed permissions. Play console
    • Add service account email and private key to Balancy. Play console permissions

Problems with service account

If you have set up everything and validation still doesn't work, the problem is probably with the service account settings. This answer could help you.

iOS

For validating iOS payments, we need generated shared secret.

Amazon

  1. During Balancy initialization pass platform
    Balancy.Main.Init(new Balancy.AppConfig {
        ApiGameId = YOUR_GAME_ID,
        PublicKey = YOUR_PUBLIC_KEY,
        Environment = Balancy.Constants.Environment.Development,
        Platform = Constants.Platform.AmazonStore,
        OnReadyCallback = responseData => { Debug.Log("Balancy Initialized: " + responseData.Success); }
    });
    
  2. Add platform on the Balancy platforms page and set amazon shared key.

Amazon settings

You can read Amazon's documentation about IAP, also check Unity's documentation.

Basic Usage

To get all available products user asynchronous method GetProducts:

Payments.GetProducts(data =>
{
    if (data.Success)
    {
        foreach (var product in data.Products)
        {
            Debug.Log("product: " + product.Name + " => " + product.ProductId);
        }
    }
});

To get specific product you can use:

  1. Asynchronous GetProduct:

    Payments.GetProductById("gold.pack.1", (item) =>
    {
        if (item != null)
        {
            Debug.Log("product: " + item.Name + " => " + item.ProductId);
        }
    });
    
    2. Synchronous GetProduct:

    var product = Payments.GetProductById("gold.pack.1");
    

    Product could be null

    If you use synchronous method, it can return null, if you didn't call GetProducts before that. We'd recommend always to use async method. But if you decide to use sync version, at least, call GetProducts once before that.

Restore Purchases

When a user reinstalls your application they should be granted any Non-Consumable products they already own. On platforms that support it (e.g. Google Play and Universal Windows Applications) Balancy automatically restores any products the user owns during the first initialization following reinstallation.

On iOS platform you need to manually call Balancy.Payments.RestorePurchases().

To receive callback on successful restoration, subscribe on event Balancy.Payments.onProductWasRestored. Here you will be able to get product id.

Payments.onProductWasRestored += data =>
{
    if (data.Success)
    {
        Debug.Log("Product restored: " + data.ProductId);
    }
};

LiveOps Purchases

To get the list of all the payments the user made, call the following method (make sure to do that after OnSmartObjectsInitialized is invoked)

Balancy.LiveOps.Profile.GetPaymentsInfo();

Balancy Validation

//Single Offers
Balancy.LiveOps.GameOffers.PurchaseOffer(offerInfo, purchaseResponse =>
{
    Debug.Log("Purchase status " + purchaseResponse.Success + " for " + purchaseResponse.ProductId);
});

//Group Offers
Balancy.LiveOps.GameOffers.PurchaseOffer(offerGroupInfo, storeItem, purchaseResponse =>
{
    Debug.Log("Purchase status " + purchaseResponse.Success + " for " + purchaseResponse.ProductId);
});

//Store Items
Balancy.LiveOps.Store.PurchaseStoreItem(storeItem, purchaseResponse =>
{
    Debug.Log("Purchase status " + purchaseResponse.Success + " for " + purchaseResponse.ProductId);
});

There are additional methods, which are available for StoreItem:

bool isFree = storeItem.IsFree();
bool isEnoughResources = storeItem.IsEnoughResources();
int watchedAdsCount = storeItem.GetWatchedAds();
int requiredAdsCount = storeItem.GetRequiredAdsToWatch();

If you use Ads as a price, use the following method after an Ad was watched for the specific StoreItem. When storeItem.IsEnoughResources() to purchase the storeItem for Ads, invoke Balancy.LiveOps.Store.PurchaseStoreItem method.

Balancy.LiveOps.Store.AdWasWatchedForStoreItem(storeItem);

Custom Validation

If you use your payment/Validation system, you need to confirm the purchase with Balancy. This information will only be used for future Segmentation and will be saved in the profile history if the purchase is valid.

//unityProduct is what you receive from Unity payments, it's a type of UnityEngine.Purchasing.Product
var paymentInfo = new PaymentInfo
{
   Receipt = unityProduct.receipt,
   Price = (float)unityProduct.metadata.localizedPrice,
   Currency = unityProduct.metadata.isoCurrencyCode,
   ProductId = unityProduct.definition.id,
   OrderId = unityProduct.transactionID
};

//Offers
Balancy.LiveOps.GameOffers.OfferWasPurchased(offerInfo, paymentInfo, purchaseResponse =>
{
    Debug.Log("Purchase status " + purchaseResponse.Success + " for " + purchaseResponse.ProductId);
});

//Group Offers 
Balancy.LiveOps.GameOffers.OfferWasPurchased(offerGroupInfo, storeItem, paymentInfo, purchaseResponse =>
{
    Debug.Log("Purchase status " + purchaseResponse.Success + " for " + purchaseResponse.ProductId);
});

//Store Items
Balancy.LiveOps.Store.ItemWasPurchased(storeItem, paymentInfo, purchaseResponse =>
{
    Debug.Log("Purchase status " + purchaseResponse.Success + " for " + purchaseResponse.ProductId);
});

If you didn't migrate all the data to Balancy, but still want us to save payments history to use it in segmentation and conditions, it's best to use the method above Balancy.LiveOps.Store.ItemWasPurchased, passing null as StoreItem.

If you use payment system which Balancy is not supported (yet), you can bypass payment from your payments/validation system to Balancy without validation on our side:

Balancy.LiveOps.GameOffers.OfferWasPurchasedAndValidated(offerInfo, paymentInfo, Constants.Platform.Unknown, purchaseResponse =>
{
    Debug.Log("Purchase status " + purchaseResponse.Success + " for " + purchaseResponse.ProductId);
});

Balancy.LiveOps.GameOffers.OfferWasPurchasedAndValidated(offerGroupInfo, storeItem, paymentInfo, Constants.Platform.Unknown, purchaseResponse =>
{
    Debug.Log("Purchase status " + purchaseResponse.Success + " for " + purchaseResponse.ProductId);
});
In this case you need to fill paymentInfo by yourself with information from purchase.

Custom Payments

You can also use the Balancy payment system without LiveOps features. Be aware, using those methods for payments won't save any history in player's progress, thus won't affect segmentation and any other conditions. If you want to use history of payments in your LiveOps, use one of the methods above.

// Get a list Of Products:
Balancy.Payments.GetProducts(productsResponse =>
{
    Debug.Log("Products Received " + productsResponse.Success);
    if (productsResponse.Success)
        Debug.Log("Products Count: " + productsResponse.Products.Length);
});

// Make a purchase:
Balancy.Payments.PurchaseProduct(<product_id>, doneCallback =>
{
    Debug.Log("Purchase was made " + doneCallback.Success);
});

Product id

You should use the product id from the base product. For example, if a product has id com.mygame.gold1, and you overrode it for Android with com.mygame.gold1.android, you have to pass com.mygame.gold1 to the purchase method.