Sponsored By

New Unity IAP system. Pros, Cons, Rocks

My name is Pavlo and I want to tell you how I’ve implemented new Unity IAP (from here and after - UIAP) which was released with Unity 5.3, what to expect when working with it, and what pitfalls you can fall into and how you can overcome them.

Pavlo Alieinikov, Blogger

May 26, 2016

6 Min Read
Game Developer logo in a gray background | Game Developer

Who am I and what I do?

Hi everyone! My name is Pavlo and I want to tell you how I’ve implemented new Unity IAP (from here and after - UIAP) which was released with Unity 5.3, what to expect when working with it, and what pitfalls you can fall into and how you can overcome them. So, without any further ado lets get to it!

Why I do it?

Why I choose UIAP? Mainly because this service is integrated into Unity ecosystem, thus, it will be expanded in future, and I am making platform that I will use in most of my future games.

Here is a list of what I will cover here for those who hesitate if he really needs this article:

  • How Unity IAP works, in a nutshell.

  • How I work with consumable purchases.

  • How I verify purchases (with Apple Store atm)

Overall structure of purchases

UIAP covers everything from loading data from store (including price and description), to communicating with the store and getting receipts for purchased products. Therefore, buy using UIAP developers can focus on making game magic happen… in theory. In practice - there are couple points you should be aware of, which we will talk about a bit later.

This Unity tutorial covers big chunk of info on how to use UIAP https://unity3d.com/ru/learn/tutorials/topics/analytics/integrating-unity-iap-your-game

Let’s go over some chunks of script that will show how to use it.

Initialization


//You need to init your IAP Configuration and fill it with data.
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());

// I’ve made pool of products that holds ID of products for different stores, its type, etc and named it InAppProduct, so that I won’t need to change code to add new products.

// Note that you should use actual store IDs for products in AppleStoreID and GoogleStoreID fields.
foreach (InAppProduct prod in products)
{
     builder.AddProduct (prod.UnityIAPID, prod.Type, new IDs () {{ prod.AppleStoreID, AppleAppStore.Name },{ prod.GoogleStoreID, GooglePlay.Name },});
}

// Here we are initializing our Purchasing module. Take look on this “this”, it means that this class instance will receive all messages for UIAP.
UnityPurchasing.Initialize(this, builder);



Purchasing products

Now we start our purchase by using BuyProductID(string productId) method. We invoke this method somewhere in code where we supply it UnityIAPID of the specific product (i.e. get100gems, getBigFGun, buySwordOfThousandTruths, etc.) and try to purchase something.


// Most crucial part is this - we get actual product saved in Product on initialize.
Product product = controller.products.WithID(productId);

// This is actual call to Store, be it Apple of Google or Windows. UIAP magic happens after this function (Store is called, popup is displayed, user confirms purchase, we get money, we get callback from store that purchase is done).
controller.InitiatePurchase(product);

Responding to purchase

We can get two responses from previous step:

  1. Purchase failed, for example, because user hasn’t got enough money.

Then we call


public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)

where we will write our logic of handling it.

  1. Purchase succeeded!

In this situation


public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args) 

method is called.

PurchaseEventArgs - it is, essentially, Product with filled receipt fields. This method can return two values - Complete and Pending. Why it is important? In a nutshell - it can freeze you from making future purchases. Let me get into bit more details on this one: On Complete value FinishTransaction event is called in Store (i.e. finishTransaction of SKPaymentTransaction class on Apple devices) for this purchase. On Pending value - this function will not be called. If you have pending purchase - you can’t buy anymore items of that type until you finish this purchase.

And now we get to the interesting part - if you have subscription or non-consumable IAP type - you will get a callback next time application starts that will call ProcessPurchase method… BUT, if you have consumable IAP - you will not get this callback, there is none for consumable purchases, thus, you will probably want to return Complete flag from this method and make your own receipt verification (i.e. on dedicated server) afterwards.

Essentially - this is how UIAP system works (I’ve omitted methods like void RestoreTransactions() as they are a bit out of scope of purchases). Now. On to the verification!

Verification

Why we need it?

To reduce amount of cheaters in the game:)

How is it done?

We send receipt to Apple Store in specific format and get response that contains all info we can possibly get for this purchase.

Sounds simple, but problem here is that we can’t control what is happening on user device - user can just forward message to fake Apple Store and return “correct” response each time, thus we need dedicated place that won’t be compromised (at least 99% of the time :) ). Thus we made our own dedicated server where we send receipts from client (encrypted, ofc). This server does all the checks and user app gives user gems (or whatever) on correct code return.

Next issue that I’ve faced - what if network will fail? Or any other issue will arise (crash, bug, dumb user)? We need to have bulletproof way to guarantee that user will get what he payed for. And here how ProductStash system was born:)

ProductStash is… well… a stash of products that await for confirmation from our server. This systems stashes purchases that are successful (from Apple Store point of view) till they are confirmed by our server and gems (coins, diamonds, etc.) are given to the user. Usually there is only one purchase there that will be removed by server confirmation, but even in an unlikely situation when user purchases couple items, but they all fail to get confirmed by server - I save those receipts in PlayerPrefs for later retry.

And this is how I’ve implemented UIAP into the game I’m working on.

Small tip on displaying product data

By using product.metadata property of Product (like when you get by using Product product = controller.products.WithID(productId); ) you can access local price, name and currency type of purchase. By local - it means local for country and store (i.e. values in Google Play and App Store can be different, depending on what conversion rate is set in stores).

Conclusion

So, to sum up, what pros of UIAP system:

  • Integrated into Unity ecosystem

  • Does all the communication with Store, you only need to do relatively minor stuff

What about cons?

  • Documentation. Unity wasn’t been able to finish and flesh it out, and describe all the features.

  • A lot of features work not what intuitively they should. Thus - a lot of frustration and misunderstanding.

  • A lot of features are missing. Like verification, or how to work with Pending consumables.

Would I recommend it? Yep, especially in a year or more, I think has potential to be great tool:)

Hope this article was at least a bit more helpful than boring, and please share your thoughts in comments! :)

Read more about:

Blogs
Daily news, dev blogs, and stories from Game Developer straight to your inbox

You May Also Like