Currency (IAP)

Integration Guide

Every project may have multiple custom currencies. For example "diamonds" and/or "cash". Aside from these typical game currencies, projects wishing to sell NFTs must integrate a specific currency. The internal name for this currency is "rgn-coin". When the "rgn-coin" is presented in the UI it can have any currency name, for example, "gems".

The "rgn-coin" may only be sold using in-app purchases. For more information on why this approach is used, please refer to the Currency GDG.

Other typical currencies can be added and used in an expected manner - as rewards to the user's account, or sold for in-app purchases.

We suggest utilizing Unity's IAP Package to handle the in-app purchase process on Android and iOS.

To sell "rgn-coin" or other custom currency via in-app purchases you need to follow the below process:

  1. Get the products list from AppStore (iOS) or PlayMarket (Android)

  2. Get the registered products list from RGN SDK:

    1. RGN.Modules.Currency.CurrencyModule.GetInAppPurchaseCurrencyDataAsync for custom coin currency packs

    2. RGN.Modules.Currency.CurrencyModule.GetRGNCoinEconomyAsync for "rgn-coin" packs. Important: you need to sell the "rgn-coin" for exact same tiers as it is specified in the response from this method.

  3. When the user tries to purchase the coins start the in-app purchase process by using one of the available Unity plugins.

  4. When the user purchases the coins and the callback for a successful purchase is triggered, you need to verify the receipt locally.

  5. After successful receipt verification, you need to trigger the RGNCurrency API:

    1. For custom currencies call the RGN.Modules.Currency.CurrencyModule.PurchaseCurrencyProductAsync method.

    2. For "rgn-coin" purchases call the RGN.Modules.Currency.CurrencyModule.PurchaseRGNCoinAsync mehtod.

  6. In case the operation is successfully updated coin currencies balance will be returned in the response.

Add in-app products information using the READYgg Dev Dashboard

In the READYgg Dev Dashboard, you can add your in-app purchases with the following details:

string id; //IAP identifier
string currencyName; //reward currency name i.e. coin
float price; //price of IAP
int quantity; //reward currency ammount
string type;  
string promotionalSticker;

API call:

The GetInAppPurchaseCurrencyDataAsync() needs to be called only once. You can cache the value CurrencyProductsData for later use in the PurchaseCurrencyProductAsync method:

using RGN.Modules.Currency;

namespace SomeNamespace
{
    internal sealed class RetrieveCurrencyData
    {
        internal CurrencyProductsData ProductsData { get; private set; }
        public async void RetrieveCurrencyDataOnceAsync()
        {
            ProductsData = 
                await CurrencyModule.I.GetInAppPurchaseCurrencyDataAsync();
        }
    }
}

The CurrencyProductsData contains two fields: products and offers

The products is a list of RGNStoreProduct classes:

public class CurrencyProduct
{
    public string id;
    public string currencyName;
    public float price;
    public int quantity;
    public string type;
    public string promotionalSticker;
}

The offers is a list of CurrencyOffer classes:

public class CurrencyOffer
{
    public string productId;
    public string offeredProductId;
    public double remainingTime;
    public float offeringPrice;
    public string promotionalMessage;
}

Buy IAP custom coin currency product

  1. Call Unity IAP package purchase API and let the user buy the IAP (it is handled by native UI)

  2. Validate the purchase receipt locally

  3. On OnSuccessfullPurchase event call RGN's PurchaseCurrencyProductAsync(productId):

using System.Collections.Generic;
using RGN.Modules.Currency;

namespace SomeNamespace
{
    internal sealed class PurchaseCustomCoin
    {
        // This is a callback method for IAP plugin after successful
        // receipt validation:
        public async void HandleSuccessfulPurchaseAsync(string productId)
        {
            List<Currency> userCurrencyData =
                await CurrencyModule.I.PurchaseCurrencyProductAsync(productId);
        }
    }
}

Here the productId is the id that you received in the CurrencyProduct data.

Purchase rgn-coin IAP

Purchasing rgn-coin works a bit differently, it has its own API called PurchaseRGNCoinAsync(string iapUUID)

To process in-app purchases you can use the Unity Purchasing plugin by adding "com.unity.purchasing": "4.9.3", to projects manifest.json file.

using RGN.Modules.Currency;
using UnityEngine;
using UnityEngine.Purchasing;
using UnityEngine.Purchasing.Security;

namespace SomeNamespace
{
    internal sealed class PurchaseRGNCoin
    {
        public async void HandleSuccessfulPurchaseAsync()
        {
            // You can also retrieve the ecomony data
            // once the app starts and cache it
            RGNCoinEconomy rgnCoinEconomy =
                await CurrencyModule.I.GetRGNCoinEconomyAsync();

            // TODO: select the right product from the list:
            // The list contains multiple 'rgn-coin' product packs
            // Every pack has different amount of 'rgn-coin's and
            // is sold using different price tier from the store
            string iapUUID = rgnCoinEconomy.products[0].uid;

            // TODO: before you call this method, you need
            // to go to the in-app purchase process
            //
            // After the in-app purchase successfully finishes
            // you need to validate the receipt locally
            // in the ProcessPurchase() callback and then
            // you can call following method:
            // TODO: get it from the iap plugin callback
            string iapTransactionId = string.Empty;
            // TODO: get it from the iap plugin callback
            string iapReceipt = string.Empty;

            System.Collections.Generic.List<Currency> purchaseResponse =
                await CurrencyModule.I.PurchaseRGNCoinAsync(
                    iapUUID,
                    iapTransactionId,
                    iapReceipt);
        }
        private PurchaseProcessingResult ProcessPurchase(
            PurchaseEventArgs purchaseEvent)
        {
            bool validPurchase = true; // Presume valid for platforms with no R.V.
            // Unity IAP's validation logic is only included on these platforms.
            // Prepare the validator with the secrets we prepared in the Editor
            // obfuscation window.
            var validator =
                new UnityEngine.Purchasing.Security.CrossPlatformValidator(
                    GooglePlayTangle.Data(),
                    AppleTangle.Data(),
                    Application.identifier);
            try
            {
                // On Google Play, result has a single product ID.
                // On Apple stores, receipts contain multiple products.
                var result = validator.Validate(
                    purchaseEvent.purchasedProduct.receipt);
                // For informational purposes, we list the receipt(s)
                Debug.Log("Receipt is valid. Contents:");
                foreach (IPurchaseReceipt productReceipt in result)
                {
                    Debug.Log(productReceipt.productID);
                    Debug.Log(productReceipt.purchaseDate);
                    Debug.Log(productReceipt.transactionID);
                }
            }
            catch (IAPSecurityException)
            {

                Debug.Log("Invalid receipt, not unlocking content");
                validPurchase = false;
            }
            if (validPurchase)
            {
                Debug.Log(
                    $"Product {purchaseEvent.purchasedProduct.definition.id} " +
                    "purchased");
                string transactionId = purchaseEvent.purchasedProduct.transactionID;
                string receipt = purchaseEvent.purchasedProduct.receipt;
                // TODO: call here the
                // await CurrencyModule.I.PurchaseRGNCoinAsync() method
            }
            else
            {
                Debug.Log("Something happened when trying to purchase product " +
                    purchaseEvent.purchasedProduct.definition.id);
            }

            return PurchaseProcessingResult.Complete;
        }
        public class GooglePlayTangle
        {
            private static byte[] data = System.Convert.FromBase64String("abc");
            private static int[] order = new int[] { 10, 11 };
            private static int key = 12;

            public static readonly bool IsPopulated = true;

            public static byte[] Data()
            {
                if (IsPopulated == false)
                    return null;
                return Obfuscator.DeObfuscate(data, order, key);
            }
        }
        public class AppleTangle
        {
            private static byte[] data = System.Convert.FromBase64String("abc");
            private static int[] order = new int[] { 10, 11 };
            private static int key = 12;

            public static readonly bool IsPopulated = true;

            public static byte[] Data()
            {
                if (IsPopulated == false)
                    return null;
                return Obfuscator.DeObfuscate(data, order, key);
            }
        }
    }
}

You can get isoCurrenyCode and localizedPrice from Unity IAP product's metadata. More details for Browsing Product Metadata.

For now, you'll have to set isoCurrenyCode & localizedPrice in USD and 0.99, 1.99 or 2.99