FAQ

Why InitializeStore call returns empty product list in the callback 💁‍♂️?

This usually happens for two reasons.

  • There are no billing products set up in the Essential Kit Settings (Refer Setup)

  • Platform specific issue

iOS

Android

Why InitializeStore returns products in out of order?

We always recommend to refer a product with its id rather than index. This is for one main reason

Products can be marked as inactive or delete in the future

If a product is deleted in the future versions, our plugin ordering the products will break older versions. For this reason we always recommend not to rely on the index, but instead on the product id to refer a product.

To get product details for a product id, you can make use of BillingServices.GetProductWithId method.

Why on Android, purchases bought with an account are restored even when logged in with a different account in google play?

This is usual behaviour on Android.

Purchases on Android aren't linked to the account which is logged into the google play app. They are "linked to the account which installs the app".

So, if you re-install the app with new account, thats when the restore purchases reflect the new account purchases and stops old purchases.

Are the testers charged for testing too?

On iOS, sandbox testers are not charged any time. For all test flight users, IAP are offered free by default (and they don't need to use sandbox tester accounts too)

On Android, normal testers(who opt-in through test track url) are charged and will be refunded in 14 days. Where as license testers won't be charged anytime.

How to do receipt verification with Appodeal?

IBillingTransaction transaction; //Get this value from the Transaction Change callback
//...
IDictionary rawData =  (IDictionary)ExternalServiceProvider.JsonServiceProvider.FromJson(transaction.RawData);
var originalTransaction = rawData != null ? rawData["transaction"] as string : null;
var signature = rawData != null ? rawData["signature"] as string : null;

#if UNITY_ANDROID
    var additionalParams = new Dictionary<string, string> { { "key1", "value1" }, { "key2", "value2" } };

    var purchase = new PlayStoreInAppPurchase.Builder(transaction.Product.Type == BillingProductType.Subscription ? PlayStorePurchaseType.Subs : PlayStorePurchaseType.InApp)
        .WithAdditionalParameters(additionalParams)
        .WithPurchaseTimestamp(new DateTimeOffset(transaction.DateUTC).ToUnixTimeSeconds())
        .WithDeveloperPayload("payload")
        .WithPurchaseToken(transaction.Receipt)
        .WithPurchaseData(originalTransaction)
        .WithPublicKey(BillingServices.UnitySettings.AndroidProperties.PublicKey)
        .WithSignature(signature)
        .WithCurrency(transaction.Product.Price.Code)
        .WithOrderId(transaction.Id)
        .WithPrice($"{transaction.Product.Price.Value}")
        .WithSku(transaction.Product.PlatformId)
        .Build();

    Appodeal.ValidatePlayStoreInAppPurchase(purchase, this);
#elif UNITY_IOS
    var additionalParams = new Dictionary<string, string> { { "key1", "value1" }, { "key2", "value2" } };

    var purchase = new AppStoreInAppPurchase.Builder(transaction.Product.Type == BillingProductType.Subscription ? AppStorePurchaseType.AutoRenewableSubscription : transaction.Product.Type == BillingProductType.Consumable ? AppStorePurchaseType.Consumable : AppStorePurchaseType.NonConsumable)
        .WithAdditionalParameters(additionalParams)
        .WithTransactionId(transaction.Id)
        .WithProductId(transaction.Product.PlatformId)
        .WithCurrency(transaction.Product.Price.Code)
        .WithPrice($"{transaction.Product.Price.Value}")
        .Build();

    Appodeal.ValidateAppStoreInAppPurchase(purchase, this);
#endif

Last updated