How to integrate In App Purchases

Monkey Archive Forums/Monkey Tutorials/How to integrate In App Purchases

Xaron(Posted 2013) [#1]
Ok, this tutorial will handle the IAP part of your app. It will have a generic part (which is the test app itself) and 3 specific parts for Android, iOS and (later) WP8.

Here we go!

This the code I use, it's mainly the same as Mark's example:

Xaron(Posted 2013) [#2]

So far so good, that was the easy part. Compile it to Android and sign it with your release key as you have to upload it to the store. YES, there is no other way to test it with real product ids, but don't worry, you won't have to publish it!

Ok, so go to your developer console and go to "InApp Products"

Ahhh you see, we have to upload the apk first! I select beta testing for that purpose.


Now go to InApp Products again:

Let's add our product IDs as managed products. As far as I understand starting with API V3 everything is managed which means that you can only buy consumables ONCE and you must consume it before you can buy the next consumable of the same type. Luckily Mark already handles this for us!
The product IDs MUST be the same as in your app defined. In our example:
Global CONSUMABLES:String[] = [ "bulletboost", "speedboost" ]
Global NON_CONSUMABLES:String[] = [ "shipupgrade" ]

Add title, description, price and set it to ACTIVE:

Alright, now your list should look like this:

Finally, to enable TESTING of your purchases you have to add beta testers to your account details. All Google accounts listed there will be able to purchase your items WITHOUT being charged for it. So the buy process will look exactly like the real one with the exception that your credit card isn't debited.

That's it! Actually you have to wait an hour or two till the product list is really available.

Xaron(Posted 2013) [#3]

Alright. Now to iOS. I was surprised how straight forward it is for this platform!

First, enter iTunes Connect and go to the app which you want to use InApp purchases with. Click on "Manage In-App Purchases":

Right, you see, no IAPs yet, so let's create a new one!

Ok, the type. Basically I've only tried consumables and non-consumables.
Consumables are things like fuel for a car.
Non-Consumables are things like a full version purchase or ad removal.

I select a non-consumable here in this real example. The reference name is just for you, nothing the customer will ever see. The product ID should be the string you use in your app as id!

Add languages (the display name is what the user sees) and (funny enough) a screenshot. I just used a screenshot where the "Buy" button is visible:

Click done. So far so good. That's it basically. We need a binary now to complete it!

Now go to your member center ( ) and ensure that your bundle list has InApp purchases enabled:

Finally enable IAPs in XCode in your app as well:

That's it. Build and submit it for review. Peace of cake! ;)

BE AWARE: It is important to add a "Restore Purchases" button to your app. Otherwise Apple will reject it!

Xaron(Posted 2013) [#4]

coming soon...

Xaron(Posted 2013) [#5]
Other Stores

(maybe) coming soon...

Nobuyuki(Posted 2013) [#6]
very nice. Here's the tutorial a bunch of people have been waiting for! They should be thankful for all your help, considering how hard it used to be before the IAP module existed :)

Paul - Taiphoz(Posted 2013) [#7]
You Sir can have some Stars :)

Xaron(Posted 2013) [#8]
Thanks guys! :) I still hope, Mark adds IAP for WP8 soon!

Supertino(Posted 2013) [#9]
Thanks Xaron - If you already know an Amazon store one would be good too.

dragon(Posted 2013) [#10]
XARON!!! This is great!
I never know how to integrate IAP & Ads

Gerry Quinn(Posted 2013) [#11]
Very nice tutorial, thanks! You make it look almost easy!

Do people feel that a single version with a single in-app purchase would get more traction these days than a shareware-style pro and lite version of a game or app?

Supertino(Posted 2013) [#12]
@ Gerry Quinn - almost certainly, it's easier for all concerned, easier for the dev as they don't need to manage different version and more importantly easier for the would be buyer, no additional downloads, no worry about losing progress they made in the lite version. And if they don'y upgrade you can still have the ads enabled.

SLotman(Posted 2014) [#13]
Wow! Thank you very much for this :)

rIKmAN(Posted 2014) [#14]
Great start Xaron, this will help a lot of people so thanks for taking the time to do it.

Looking forward to the iOS guide. :)

sionco(Posted 2014) [#15]
Yep, fantastic!

Xaron(Posted 2014) [#16]
You're welcome. iOS comes within the next days...

Dunno about WP8 yet, There is no official module yet.

silentshark(Posted 2014) [#17]
Many thanks for putting this together, Xaron. You are a star :-)

Xaron(Posted 2014) [#18]
Just dig through the Apple stuff and as far as I read you MUST have a Restore Button in your app as soon as you include non-consumable IAPs (like a button to buy the full version which would be a non-consumable item). Otherwise Apple will reject the app. Oh well... iOS IAP tutorial is coming along nicely... Stay tuned!

"...if your application supports product types that must be restorable, you must include an interface that allows users to restore these purchases. This interface allows a user to add the product to other devices or, if the original device was wiped, to restore the transaction on the original device."

dragon(Posted 2014) [#19]

hey xaron, what about new topic for each platform?
it is also better for user comments...

Xaron(Posted 2014) [#20]
Hmm well, might do this. thought to use the first 4 postings for all platforms. Because the code is always the same...

Xaron(Posted 2014) [#21]
Added the iOS guide. :)

rIKmAN(Posted 2014) [#22]
Great stuff Xaron - suprised how easy it is but thanks for taking the time to do the guide, much appreciated :)

dragon(Posted 2014) [#23]
yea - and where is that magic button code for Restore Purchases?

ordigdug(Posted 2014) [#24]
@Xaron - You should turn these guides into an e-book.

Wylaryzel(Posted 2014) [#25]
Thanks for the guide - it seems very usable :-)

As I was reading through the different options and documentations... are subscription already implemented? And if yes, what would be the difference to the managed consumables?


Alex(Posted 2014) [#26]
I always get result -1 when try to buy a product

Global NON_CONSUMABLES:String[] = [ "com.whitezebra.turtling.doubler", 
									"com.whitezebra.turtling.megapack" ]

Global IAPStore := New IAPStoreClass

Class IAPStoreClass Implements IOnOpenStoreComplete, IOnBuyProductComplete, IOnGetOwnedProductsComplete

	Field _store:MonkeyStore

	Method Init:Void()

		_store = New MonkeyStore()
		_store.AddProducts( NON_CONSUMABLES, 2 )

		_store.OpenStoreAsync( Self )

		Print "IAP Store Opened"

	End Method

	Method Update:Void()

		UpdateAsyncEvents() 'IMPORTANT!!!
		If MouseHit(0)

			Local iap:Product = _store.GetProduct("com.whitezebra.turtling.doubler")

			Print iap.Identifier()
			Print iap.Price()
			Print iap.Title()

			_store.BuyProductAsync( iap, Self )


	End Method

other standard methods

End Class

Debug Log:
IAP Store Opened
OpenStoreComplete, result = 0
<-- *** tap on the screen ***
Double Coins
BuyProductComplete, result = -1

Xaron(Posted 2014) [#27]
Is that with the emulator? If so, it won't work. You need a real device. Plus the InApp product has to be reviewed.

Alex(Posted 2014) [#28]
It's a device.

Will try with reviewed IAPs, however, on Unity there's no need to get them reviewed.

Thank you!

Xaron(Posted 2014) [#29]
Well technically yes, there is a test mode. I've never tried this but in my case the real ones actually work in my apps.

Alex(Posted 2014) [#30]
I got this working!

Small notes for people who has the same issue.
It seems that IAP registered through iTunes Connect only works in 2 cases:

1. The app has never been in "Waiting for review/upload". Your app status should be "Prepare for upload".
In this case you may simply create IAPs without having them reviewed or added to your binary.

2. If you pressed the button "Ready to upload binary" before IAPs was created (for that time status of your app should be "Waiting for upload"), you have to:
- create IAPs
- upload a binary
- reject it by yourself
- add IAPs to binary
- press "Ready to upload binary".
Then they will work.

Hope this will be helpful!

Xaron(Posted 2014) [#31]
Yes. I went through this as well and should update my tutorial. Thanks for pointing that out! :)

Erik(Posted 2014) [#32]
Thanks for the guide, works great on ios! I can't get the android store to work though. I always get "OpenStoreComplete, result = -1". I've followed the guide, signed the app, removed debug code etc etc.

Should I be transferring the signed apk to the test device and running that somehow? Currently I just compile it to the device from within monkey...

EDIT: I've tried uploading it to Google Play and downloading it from there using a valid test account. It downloads and runs fine on the device but still no IAP.

Raul(Posted 2014) [#33]
My app status is: Prepare for Upload
I created one IAP - consumables

I receive the BuyProductComplete, result = -1

Tested on a real device. Any thoughts?

Alex(Posted 2014) [#34]
Can you, please, post here your code?

Do you use the full ID for a proguct? i.e. "com.companyname..."
Do you see the name and price for a product in log?

What is your OpenStoreComplete result?

(just the guess)
Also, try to upload binary and then reject it.
First time do NOT do this ---> (- press "Ready to upload binary".)
And try to compile to see the BuyProduct result.
If it will not work then press "Ready to upload binary". And again try to compile.

erebel55(Posted 2014) [#35]
I know most games let you pay real money for in-game currency and then you use the in-game currency to buy items.

So, how would this model work?

I assume I would create consumable items for the virtual currency, such as "bag of coins", "box of coins" etc.

However, does that mean I wouldn't create the other items that are bought with the virtual currency through the google play developer console?
If not, how would I support something like Restore Purchases, consumables, etc?

Thank you for the great tutorial :)

Raul(Posted 2014) [#36]
Yes, I use the full ID for the product. In fact, in the Debug area I receive the product name, price and id.
Also the 'store' is opened correctly.

I will try your tricks with rejecting the app this evening. I do not have the code near me, right now.

Alex(Posted 2014) [#37]
Raul, I had the same issue, I mean, I see all the parameters of the product in debug, and still get result=-1. It was fixed by the rejecting thing.

erebel55, only non-consumables can be restored. If I understood you right. If you want to remove ads or something after the consumable has been bought, you have to store the "purchase is bought" var on the device. It will not work on the other device or if the app will be deleted.

erebel55(Posted 2014) [#38]
Thanks Alex. Basically, I am trying to do something like you do in your Tinny Flippers game. I want to offer in-game currency that the user can collect during the game. I also want to allow them to purchase this currency as iap. They can then use it to buy items in the game. I guess with this model the only thing that could be restored with a "Restore Purchases" option is the in-game currency and not the items bought with it.

therevills(Posted 2014) [#39]
I guess with this model the only thing that could be restored with a "Restore Purchases" option is the in-game currency and not the items bought with it.

I would have thought it would be the other way around. The in-game currency is consumable and depending on the item it would be non-consumable.

For example, in your game you have in-game currency stored as "money", and you need to save this about via SaveState (or something), when a player "buys" more in-game currency from an IAP the money value increases:
Method OnBuyProductComplete:Void(result:Int, product:Product)
  money += 10

Alex(Posted 2014) [#40]
erebel55, "Restore Purchases" is used in case of the player has deleted the game from his device and installed again. If the game wasn't deleted you don't need to use "Restore Purchases".
Only NON-CONSUMABLE products can be restored. Because their purchase is stored on Apple/Google server and can be downloaded again. Non-consumables can be purchased only once. Example - Remove Ads, Permanent doubler. Once you purchase them, you cannot do it again.
You CANNOT restore consumable products. Such as "Coin Pack", because you can buy them many times. There's no way Apple/Google can store the purchase that you can buy many times. So, you have to save it on the device only while the app is installed, like therevills says. Once you uninstall it, all data will be lost. You cannot restore it, unless you, maybe, use any cloud service (I don't know for sure).

erebel55(Posted 2014) [#41]
So, with my model it looks like nothing can be restored after reinstall? Doesn't ios require a restore purchases button?

The model I was thinking is to have the player purchase in-game currency with real money.
Player uses in-game currency to purchase all other items.

Alex(Posted 2014) [#42]
Yes, not only your, but all the apps cannot restore consumable IAPs. Apple doesn't require consumables to be able to restore (Don't know for sure, but think, Google too. They can't require this, as they do not support this).
So, dont worry, you don't have to restore your consumable IAPs at all.

Xaron(Posted 2014) [#43]
Yep. That's the reason why games like Clash of Clans don't have a restore button. They simply only offer consumables which are not required to be restored via Apple.

For Google Play you don't need a restore button at all.

erebel55(Posted 2014) [#44]
I was planning on having both consumable and non-consumable items that can be purchases with the in-game currency. And the only thing bought with real money is the in-game currency packs.
Some examples of non-consumables items in my game are different outfits and remove ads.

Xaron(Posted 2014) [#45]
Well in that case your ingame currency is a consumable item obviously no matter what you do with it internally. So there's no need for a restore button then.

erebel55(Posted 2014) [#46]
Okay, thanks guys. I was just hoping there was a way to restore the non-consumable items that the user has purchased. I guess there isn't since they are managed internally. It looks like the only way to support that is to have non-consumable items be purchased with real money (and managed by google) instead of in-game currency. (Without getting into cloud storage)

Xaron(Posted 2014) [#47]
But keep in mind that non-consumables can only be bought once.

erebel55(Posted 2014) [#48]
Right, I understand that. How would you recommend dealing with consumables/non-consumables and in-game currency? I thought in-game currency would be better because it seems to be the model everyone has gone to.

Xaron(Posted 2014) [#49]
Yes, I'm going to use ingame currencies as well in one of my next apps. I always would do it as consumable. But of course it would be good to have it stored serverside which I will integrate as well (either via Google Gameservices, own server, etc...)

Raul(Posted 2014) [#50]
me again.

I rejected my binary, but I still receive result = -1 when trying to buy a product.

I made the following steps:
1. Created IAPs
2. Upload binary
3. Reject it.
4. Add IAPs to binary
5. Press "Ready for Upload"

It doesnt work :(

Raul(Posted 2014) [#51]
Hey guys.

I found my problem. I forgot to switch to a Test Account on my device.

Please edit the initial Post and mention this :D

Thank you Alex once again for helping me.

erebel55(Posted 2014) [#52]
But keep in mind that non-consumables can only be bought once.

But if the user uninstalls the app they will still lose these non-consumables and have to purchases them again, correct?

What I'm getting at is, if the player uses in-game currency to purchase an item (consumable/non-consumable) it can't be restored since it isn't managed by google?
Only non-consumables managed by google (meaning bought with real money) can be restored.

So I can either forget about restoring any products OR I can have non-consumables managed by google and purchased with real money.

erebel55(Posted 2014) [#53]
I am getting "OpenStoreComplete, result = -1" in my android app now as well.
This was working yesterday and I purchased a few items and tested that all out. However, it stopped working sometime this morning. I didn't change anything..

The device has an internet connection. I've tried uninstalling the app and restarting my device. The device is also setup as a test account.

This is what it is telling me
E/Volley ( 685): [14] BasicNetwork.performRequest: Unexpected response code 500 for
I/[Monkey]( 8758): OpenStoreComplete, result = -1

Any ideas? Anywhere that I can find a more verbose log for this?

Edit: Nevermind I figured it out. I was calling AddProducts on some products that weren't defined on the google play developer dashboard.

Kslam(Posted 2014) [#54]
I got problem in iOS IAP.
In iOS 6, I can see the "Buy" screen, open store successful (OpenStoreComplete, result = 0). But, if I clicked buy, no error in Xcode debug log screen.
Then I click buy again, show error "OnBuyProductComplete, result = -1". I restart it, then I click "Cancel" instead of "Buy". The error is "OnBuyProductComplete, result = 1".
After that I upgraded my iPhone device to 7.1.1, open store successful (OpenStoreComplete, result = 0). Then no more "Buy" screen show up. It crashed (libc++abi.dylib: terminating with uncaught exception of type char const*).

My app is in Prepare for Upload status.
Monkey-x ver is 78h.
Xcode is Version 5.1.1 (5B1008)
iPhone device is 4s and iOS 6 and 7.1.1

Are there many Monkey-x developer successful develop their IAP game by using Monkey-x ?
If the IAP problem can't be solved, I consider remove IAP from my game.

Kslam(Posted 2014) [#55]
Solved the by adding Test account in itunesconnect.

Second problem come out.
Normally, if buy an item, we just click shopthisItem method, then click the buy button on the "Buy Screen". Consider 1 transaction.

The problem is,
I have to click shopthisItem method, then click Buy in "Buy Screen". After that, click shopthisItem method again. Then OnBuyProductComplete, result = 0.
Consider 1 transaction.

The shopthisItem method below:
Method shopthisItem:Void()
Local iap:Product = _store.GetProduct("")
Print iap.Identifier()
Print iap.Price()
Print iap.Title()
_store.BuyProductAsync( iap, Self )
End Method

Is there anyone got solution ?

Thank you.

erebel55(Posted 2014) [#56]
I think something may have changed on the google play side yesterday. Can someone please test the example given in this tutorial on android? It no longer works for me and the iap I added to my game that has been working for weeks has also stopped.

The store opens correctly however GetProducts() is no longer returning any results. I have tested on multiple devices with the same results.

I have tried clearing data for download manager, google play store, google services, and restarting device but it didn't help.

Hope someone can help! Thanks

erebel55(Posted 2014) [#57]
I was able to chat with google play support today and this was their reply

Ah, I see the issue. Unfortunately we're to blame for this problem.
We made some changes to how IAP, OBB, and license testing works about a week ago.
We now require apps to be published in order to test these features.
Currently we recommend publishing to Alpha or Beta to test.
I apologize for the lack of communication, and we're currently working to update our documentation to reflect this change.

Basically, you can no longer test in "Draft" mode and instead need to be published to Alpha/Beta/Prod.

So I am in the process of publishing my app so I can test to see if this fixes my issue. Will report back when I am done :)

therevills(Posted 2014) [#58]
In Xaron's tutorial he tells us that you need to release it to the store and his example is publishing it to the Beta section:

So far so good, that was the easy part. Compile it to Android and sign it with your release key as you have to upload it to the store. YES, there is no other way to test it with real product ids, but don't worry, you won't have to publish it!

So what is different now?

erebel55(Posted 2014) [#59]
The "you won't have to publish it!" part is different now.

Xaron's example showed to "upload" to the Beta section (not publish).

I already had my signed game uploaded to the Beta section of google play. However, it was in "Draft" mode. Everything was working just fine for weeks and then google changed this.
So now you can't test IAP in draft mode. You have to publish it. (You can publish to Alpha, Beta, or Prod)

To sum it up in an image, this was the issue

therevills(Posted 2014) [#60]
Ah, that makes more sense - thanks Ethan.

Hate it when Google changes things like this.

erebel55(Posted 2014) [#61]
Sure no problem, I hope it helps someone in the future.

Also, just to confirm, I published my app and waited around 4 hours and the iap is all working again :D

Raul(Posted 2014) [#62]
Strange issue appeared now:

I have a new problem on this second app I am making for a client. I am trying to implement IAP as I already done in my game for an iOS game.
The issue is that I am not event able to access my iap data from the code.

So I:
- created the iaps
- uploaded the application
- rejected it
- added the iap to the binary
- App status is: Waiting for Upload

The problem is that in my code:
- I open the store (result = 0)

app is crashing at the first Print:
Field iap1:Product
Field iap2:Product

		iap1 = _store.GetProduct("com.appbundle.10000credits")
		iap2 = _store.GetProduct("com.appbundle.20000credits")		
		Print "Price: " + iap1.Price()
		Print "Price: " + iap2.Price()

I receive no errors in the line: iap1 = _store.GetProduct("com.appbundle.10000credits")
but when I try to access: price, description, etc. the app is crashing.

Also the buy does not work. In xCode is telling me the iap1 is null.

Raul(Posted 2014) [#63]
I made a separately project using ONLY the Xaron code sample from the 1st post, to be sure is nothing wrong in my code.

No products are loaded. the product is NULL

The app is in Waiting for Upload. The iaps are also in waiting for review and are attached to the app version.

WHY IS NOT WORKING.... I am trying to do this shit for 4 days...

therevills(Posted 2016) [#64]
Using a new version MonkeyX requires the new OnOpenStoreComplete method:

	Method OnOpenStoreComplete:Void(result:Int, interrupted:Product[])
		Print "OpenStoreComplete, result=" + result
		storeUnavailable = False
		If result<>0
			Print "Failed to open Monkey Store"
			storeUnavailable = True
		If interrupted.Length
			Print "Interrupted purchases:"
			For Local p:=Eachin interrupted
				Print p.Identifier
				MakePurchase p
			Print "No interrupted purchases."

Also it seems for testing you need to download the version from the app store... cant remember if this was a requirement before....

And I always forget about the UpdateAsyncEvents() method!