Knowledge base

Purchasing integration (Android)

Overview

Unity allows you to use its optimized monetization features without implementing Unity IAP. Use Unity Ads 3.0+ to create IAP Promos and leverage Personalized Placements while maintaining your own in-app purchasing solutions, by following these basic steps:

  1. Install Unity Ads SDK 3.0+ for your Project.
  2. Manually configure your Product Catalog on the Developer Dashboard.
  3. Configure an IAP Promo on the dashboard
  4. Implement a purchasing adapter in your game code, using the UnityMonetization API.
  5. Implement game logic and purchase events within the purchasing adapter.
  6. Initialize the purchasing adapter and Monetization SDK.

Implementation

The following instructions are for Android developers using Java.

  • If you are a Unity developer using custom IAP solutions, click here.
  • If you are an iOS developer using Objective-C, click here.

Importing the Unity Ads framework

Download the Unity Ads framework here, specifically unity-ads.aar. The UnityMonetization API requires SDK 3.0 or later.

Using Android Studio

  1. Create or open your existing Android project in Android Studio.
  2. Add a new module and import the unity-ads.aar file. Name the module "unity-ads", for example.
  3. Right-click on the module in the Project view, then select Open Module Settings > app, and add "unity-ads" module as a dependency.
  4. Add the following imports to your java Activity file:
import com.unity3d.services.IUnityServicesListener;
import com.unity3d.services.monetization.UnityMonetization;

Without Android Studio

If you can't use the .aar packages with your build system, Unity provides the same resources in a ZIP file (unity-ads.zip in GitHub releases). Follow these steps to use Unity Ads:

  1. Include classes.jar in your build.
  2. Manually merge the manifest from AndroidManifest.xml. Make sure you include both AdUnitActivity and AdUnitSoftwareActivity activities. You also need to add the INTERNET and ACCESS_NETWORK_STATE permissions.
  3. If you are using ProGuard, add all lines from proguard.txt to your ProGuard configuration.

Configuring your Product Catalog on the Developer Dashboard

Before implementing your purchasing adapter, navigate to the Operate tab of the Developer Dashboard, then follow the manual configuration instructions for populating a Product Catalog.

Configuring your Promotion on the Developer Dashboard

From the Operate tab of the Developer Dashboard, follow the instructions for configuring an IAP Promo.

Modifying your code

Implementing the purchasing adapter

In your game script, include the com.unity3d.services.purchasing.core.IPurchasingAdapter interface, then create a class that implements a purchasing adapter. You will use two functions, retrieveProducts and onPurchase, to define the game logic you want the purchasing adapter to use. These methods require a class using IPurchasingAdapter. You must implement them so the SDK can call them as needed when managing your Product transactions.

import com.unity3d.services.purchasing.core.IPurchasingAdapter;

private class UnityPurchasingAdapter implements IPurchasingAdapter {
    // Placeholder for retrieveProducts function
    // Placeholder for onPurchase function
}
Retrieving your Product Catalog

The SDK calls retrieveProducts to retrieve the list of available Products. The function must convert your IAP products into UnityMonetization.Product objects. This requires at minimum a productID, localizedPriceString, productType, isoCurrencyCode, and localizedTitle string for each Product.

The function takes an IRetrieveProductsListener listener. Call the listener’s onProductsRetrieved function to send the retrieved Products list back to the SDK.

Processing a purchase

The SDK calls onPurchase when a user clicks the buy button for a promotional asset. The purchase’s success or failure handling depends on your in-app purchasing implementation.

If the transaction succeeds, call the listener’s onTransactionComplete function using a TransactionDetails object.

If the transaction fails, call the listener’s onTransactionError function, using a TransactionError object.

Example IPurchasingAdapter implementation
import com.unity3d.services.purchasing.core.IPurchasingAdapter;

private class UnityPurchasingAdapter implements IPurchasingAdapter {
    @Override
    public void retrieveProducts (IRetrieveProductsListener listener) {

        // Query your Products here, convert them to Monetization.Products, then populate the Product list with them:
        listener.onProductsRetrieved (Arrays.asList (Product.newBuilder ()
            .withProductId ("100bronzeCoins")
            .withLocalizedTitle ("100 Bronze Coins")
            .withLocalizedPriceString ("$1.99")
            .withIsoCurrencyCode ("USD")
            .withProductType ("Consumable")
            .build ()));
    }

    @Override
    public void onPurchase (String productID, ITransactionListener listener, Map<String, Object> extras) {
        thirdPartyPurchasing.purchase (productId); // Generic third-party purchasing function

        // If purchase succeeds:
        listener.onTransactionComplete (TransactionDetails.newBuilder ()
                .withTransactionId ("ABCDE")
                .withReceipt ("Parsed receipt string here")
                .build ());

        // If purchase fails:
        listener.onTransactionError (TransactionErrorDetails.newBuilder ()
            .withTransactionError (TransactionError.NETWORK_ERROR)
            .withExceptionMessage ("Example: network connection dropped")
            .withStore (Store.GOOGLE_PLAY)
            .withStoreSpecificErrorCode ("Example: Google Play lost network connection")
            .build ());
        }
    }
}

Initializing the Purchasing Adapter and SDK

After you’ve implemented the purchasing adapter, you must provide a reference to it using the setAdapter method. Finally, you must initialize the SDK using your Project’s Game ID for the appropriate platform. You can locate the ID on the Operate tab of the Developer Dashboard by selecting a Project, then selecting Monetization > Platforms from the left navigation bar.

To avoid errors, implement these calls as early as possible in your game’s run-time life cycle. For example:

@Override
protected void onCreate (Bundle savedInstanceState) {
    super.onCreate (savedInstanceState);
    setContentView (R.layout.activity_main);

     UnityPurchasing.setAdapter (new UnityPurchasingAdapter ());

     UnityServices.initialize (this, unityGameID, this);
}

Back to top

Android API

UnityPurchasing

A static class that manages Purchasing Adapters, which are interfaces for the SDK to retrieve the information it needs from your custom IAP implementation. Access the necessary API by installing Unity Ads SDK 3.0+, and including the com.unity3d.services.purchasing.core.IPurchasingAdapter interface.

public class UnityPurchasing {    
    public static void setAdapter (IPurchasingAdapter adapter);
    public static IPurchasingAdapter getAdapter ();
}

IPurchasingAdapter

An adapter that you implement and pass back to the SDK.

public interface IPurchasingAdapter {
    void retrieveProducts (IRetrieveProductsListener listener);
    void onPurchase (String productID, ITransactionListener listener, Map<String, Object> extras);
}

retrieveProducts

The SDK calls this to retrieve the list of available Products.

void retrieveProducts (IRetrieveProductsListener listener);

Use the IRetrieveProductsListener to register your Product list.

IRetrieveProductsListener

An interface for an object that the SDK passes back to you through IPurchasingAdapter.

public interface IRetrieveProductsListener {
    void onProductsRetrieved (List<Product> availableProducts);
}

onProductsRetrieved

Registers your IAP products with the SDK. Your implementation must convert your IAP products into UnityMonetization.Product objects. This requires at minimum a productID, localizedPriceString, productType, isoCurrencyCode, and localizedTitle string for each Product. For more information on Product properties, see the section detailing the Product class below.

See the following example of an implemented retrieveProducts function:

@Override
public void retrieveProducts (IRetrieveProductsListener listener) {
    listener.onProductsRetrieved (Arrays.asList (Product.newBuilder ()
        .withProductId ("100BronzeCoins")     
        .withLocalizedTitle ("100 Bronze Coins")
        .withLocalizedPriceString ("$1.99")
        .withLocalizedPrice (1.99)
        .withIsoCurrencyCode ("USD")
        .withLocalizedDescription ("100 Bronze Coins at a new low price!")
        .withProductType ("Consumable")
        .build ()));
}
Product

An IAP product converted into an object that the SDK can use for optimizing monetization.

Set the following fields on the builder using the public static Builder newBuilder() method, then the public Product build() method to construct the final Product object.

Builder method Param type Description
withProductId String An internal reference ID for the Product.
withLocalizedTitle String A consumer-facing name for the Product, for store UI purposes.
withLocalizedPriceString String A consumer-facing price string, including the currency sign, for store UI purposes.
withLocalizedPrice Double The internal system value for the Product’s price.
withIsoCurrencyCode String The ISO code for the Product’s localized currency.
withLocalizedDescription String A consumer-facing Product description, for store UI purposes.
withProductType String Unity supports "Consumable", “Non-consumable”, and “Subscription” Product Types.

Use the following functions to retrieve Product properties:

public String getProductId ();
public String getLocalizedTitle ();
public String getLocalizedPriceString ();
public double getLocalizedPrice ();
public String getIsoCurrencyCode ();
public String getLocalizedDescription ();
public String getProductType ();

For more details on Product properties, see documentation on Defining Products.

onPurchase

The SDK calls this when a user clicks the buy button for a promotional asset. Unity passes the purchased Product’s ID to your in-app purchasing system. The purchase’s success or failure handling depends on your in-app purchasing implementation.

public void onPurchase (String productID, ITransactionListener listener, Map<String, Object> extras)
ITransactionListener

An interface for an object that the SDK passes back to you through IPurchasingAdapter.

public interface ITransactionListener {
    void onTransactionComplete (TransactionDetails details);
    void onTransactionError (TransactionError error, String message);
}

onTransactionComplete

Your custom game logic for handling a successful transaction. The function takes a TransactionDetails object, which details the specifics of a transaction.

onTransactionError

Your custom game logic for handling a failed transaction. The function takes a TransactionError object, which identifies the source of transaction failure.

Example onPurchase implementation
@Override
public void onPurchase (String productID, ITransactionListener listener, Map<String, Object> extras) {
    thirdPartyPurchasing.purchase (productId); // Generic developer purchasing function

    // If purchase succeeds:
    listener.onTransactionComplete (TransactionDetails.newBuilder ()
        .withProductId ("100BronzeCoins")

        .withTransactionId ("ABCDEFG")
        .withReceipt ("receipt":"{\"data\": \"{\"Store\": \"fake\", \"TransactionID\": \"ce7bb1ca-bd34-4ffb-bdee-83d2784336d8\", \"Payload\": \"{ \\\"this\\\": \\\"is a fake receipt\\\"}\"}\"}")
        .withPrice (1.99)

        .withIsoCurrency ("USD")

        .build());

    // If purchase fails:
    listener.onTransactionError (TransactionError.NETWORK_ERROR, "No Network Connection");
}
TransactionDetails

An IAP transaction receipt converted into an object that the SDK can use for optimizing monetization.

Set the following fields on the builder using the public static Builder newBuilder () method, then the public TransactionDetails build () method to construct the final Product object.

Builder method Param type Description
withProductId String An internal reference ID for the Product.
withTransactionId String An internal reference ID for the transaction.
withReceipt String The JSON fields from the INAPP_PURCHASE_DATA detailing the transaction. Encode the receipt as a JSON object containing Store, TransactionID, and Payload.
withPrice BigDecimal The internal system value for the Product’s price.
withIsoCurrency String The ISO code for the Product’s localized currency.

Use the following functions to retrieve Product properties:

public String getProductId ();
public String getTransactionId ();
public String getReceipt ();
public BigDecimal getPrice ();
public String getCurrency ();
TransactionError

An enum indicating the reason a transaction failed.

public enum TransactionError {
    ITEM_UNAVAILABLE
    NETWORK_ERROR
    NOT_SUPPORTED
    SERVER_ERROR
    UNKNOWN_ERROR
    USER_CANCELLED
}

UnityAnalytics

The SDK provides Unity Analytics APIs to non-Unity developers, to help optimize monetization. Implement the following analytic events and pass them back to the SDK in order to better analyze your game’s economy. The more information the SDK has about your players’ behavior, the better it manages your monetization strategy.

public class UnityAnalytics { }

onItemAcquired

Call this event when players acquire a resource in-game.

public static void onItemAcquired (String transactionContext, Float amount, String itemId, Float balance, String itemType, String level, String transactionId, AcquisitionType acquisitionType);

onItemSpent

Call this event when players consume a resource in-game.

public static void onItemSpent (String transactionContext, Float amount, String itemId, Float balance, String itemType, String level, String transactionId, AcquisitionType acquisitionType);
Property Type Description
transactionContext String A description of the in-game context for the transaction (for example, "Loot box").
amount Float The quantity of the resource acquired.
itemId String An internal reference ID for the acquired resource.
balance Float The player’s new (post-transaction) quantity of the acquired resource.
itemType String The category of the resource required (for example, “Premium currency”).
level String The name or ID of the level/area where the player acquired the resource (for example, “Level 1 store”).
transactionId String An internal reference ID for the transaction. You can optionally use this identifier to group multiple events into a single transaction.
acquisitionType AcquisitionType Indicates soft or premium currency (see section below).

These events help train the SDK to know when it’s best to show a Promo. Consider the following examples:

If a player has purchased 300 Gold Coins and spent 250, the data model can determine that they are getting low on Gold Coins, and that it might be worthwhile to show a Promo for acquiring more.

UnityAnalytics.onItemAcquired ("3rd level store", 300.0f, "300goldCoins", 300.0f, "in-game-currency", "3", "ABCD", AcquisitionType.PREMIUM);

UnityAnalytics.onItemSpent ("4th level store", 250.0f, "250goldCoins", 50.0f, "in-game-currency", "4", "EFGH", AcquisitionType.PREMIUM);

If a player trades 100 Cows for 400 Pigs, the data model can determine that it might be worthwhile to show a Promo for replenishing the Cows they depleted.

UnityAnalytics.onItemAcquired ("Newbie Bazaar", 400.0f, "400pigs", 400.0f, "in-game-currency", "newbieBazaar", "ABCD", AcquisitionType.SOFT);

UnityAnalytics.onItemSpent ("Newbie Bazaar", 100.0f, "100cows", 0.0f, "in-game-currency", "newbieBazaar", "EFGH", AcquisitionType.SOFT);

onLevelFail

Call this when players fail a level in-game. The data model can use this to show a Promo for a product that will help them pass the level on the next playthrough.

public static void onLevelFail (Integer levelIndex);

onLevelUp

Call this when players complete a level. When used in conjunction with onLevelFail, the data model gains insight into which levels users are struggling with, and which Promos make effective offers for each level.

public static void onLevelUp (Integer newLevelIndex);
AcquisitionType

An enum that indicates whether an item is SOFT (in-game currency) or PREMIUM (exchanged for real world money).

public enum AcquisitionType {
    SOFT,
    PREMIUM;

    public String toString ();
}

Back to top

Still need help? Get in touch!
Last updated on 16th Nov 2018