This feature allows you to support In-App Purchases. Currently, only the Apple iTunes Store is supported. In the future, other store fronts may be added.
In-App Purchases allow users to purchase additional content. However, the Apple iTunes Store manages transaction information only! Developers cannot use the Apple App Store to deliver content. So, either you bundle content with your app when you ship it waiting to be unlocked upon purchase, or you have to work out your own system to download the data if you wish to deliver content after the fact. To support downloadable content, you may use our new Network/AsynchHTTP APIs.
For your app to work with Apple's iTunes Store, you must follow Apple's instructions for setting up provisioning on Apple's Provisioning Portal and for setting up purchasing on iTunesConnect. This is a complex process. There are many helpful tutorials available elsewhere on the web; some suggestions are listed at the end of this article. Briefly, the key steps are as follows:
A sample project is available here: InAppDemo.zip
store moduleYou'll also need to create code in your Corona app to handle transactions with the App Store.
First, you should require the store module into your program
store = require("store")
Next, you need to call the store.init function specifying a listener to handle transaction callbacks (more on that below).
You should call store.init() soon after your program finishes launching. The reason is that the Apple App Store likes to aggressively make sure any incomplete transactions can be completed as soon as possible. If a transaction was interrupted the last time your program was run (say due to a phone call or network outage), the user should be able to continue the transaction. By calling store.init(), your app notifies the store that it is ready to handle transaction callbacks.
Corona provides store.loadProducts() to retrieve information about items available for sale. This includes the price of each item, a localized name, and a localized description. However, the Apple App Store does not provide a way to query for a list of all available products. Therefore, your code must include (or generate) product identifiers for all items.
Product IDs are what you entered in iTunes Connect. The typical convention is to use your bundle id with the item name appended on, e.g. (com.anscamobile.NewExampleInAppPurchase.MyNonConsumableItem).
The resulting event from the loadProductsCallback listener has the following properties:
Each entry in the event.products array supports the following fields
Here is a simple code example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | function loadProductsCallback( event ) print("showing products", #event.products) for i=1, #event.products do local currentItem = event.products[i] print(currentItem.title) print(currentItem.description) print(currentItem.price) print(currentItem.productIdentifier) end print("showing invalidProducts", #event.invalidProducts) for i=1, #event.invalidProducts do print(event.invalidProducts[i]) end end arrayOfProductIdentifiers = { "com.anscamobile.NewExampleInAppPurchase.MyConsumableItem", "com.anscamobile.NewExampleInAppPurchase.MyNonConsumableItem", "com.anscamobile.NewExampleInAppPurchase.MySubscriptionItem", } store.loadProducts( arrayOfProductIdentifiers, loadProductsCallback ) |
If you need your product list to be dynamic, Apple recommends you run your own server to provide a list of up-to-date products your app can retrieve.
Typically, you would use the callback as an opportunity to create and display a UI so a user may browse and buy items.
iOS devices have a setting that disables purchasing. A common case for this is to prevent children from accidentally purchasing things without parents' permission. Corona provides an API to check whether purchasing is possible. Use this preemptively to avoid having your users navigate through many purchase steps only to find out at the last step that purchasing is forbidden.
Returns true if purchases are allowed, false otherwise.
To initiate a purchase, Corona provides store.purchase().
This function will send out purchase requests to the store. The listener you specified in store.init() will be invoked when the store finishes processing the transaction.
Note: Currently, there is no explicit API to specify quantities for consumable items. However, as a backdoor, you may place the product in the array multiple times and Corona will set the quantity behind the scenes.
Calling store.init() enables your program to handle transaction callbacks from the App Store using the listener you provide. This listener should handle all of the following circumstances:
store.purchase())store.purchase() was called)store.purchase())store.restore(), explained below)The resulting event from the transaction callback listener has the following property:
The transaction object supports the following read-only properties
After you receive a transaction event, it is up to you to decide what to do. For example, if the user successfully purchased an item, you might record this information in a preference file that unlocks the user's ability to use the item. This file should be referenced in the future so you know that the item has been purchased in future runs. Similarly, if the content must be downloaded, you would initiate the download here.
After you finish handling the transaction, you must call store.finishTransaction() on the transaction object. If you don't do this, the App Store will think your transaction was interrupted and will attempt to resume it on the next application launch.
Users who wipe the information on a device or buy a new device, may wish to restore previously purchased items without paying for them again. The store.restore() API initiates this process. Transactions that can be restored will be invoked on your transactionCallback listener which you registered with store.init(). The transaction state will be "restored" in this case and your app may then make use of the originalReceipt, originalIdentifier, and originalDate fields of the transaction object.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | function transactionCallback( event ) local transaction = event.transaction if transaction.state == "purchased" then print("Transaction succuessful!") elseif transaction.state == "restored" then print("Transaction restored (from previous session)") print("productIdentifier", transaction.productIdentifier) print("receipt", transaction.receipt) print("transactionIdentifier", transaction.identifier) print("date", transaction.date) print("originalReceipt", transaction.originalReceipt) print("originalTransactionIdentifier", transaction.originalIdentifier) print("originalDate", transaction.originalDate) elseif transaction.state == "cancelled" then print("User cancelled transaction") elseif transaction.state == "failed" then print("Transaction failed, type:", transaction.errorType, transaction.errorString) else print("unknown event") end -- Once we are done with a transaction, call this to tell the store -- we are done with the transaction. -- If you are providing downloadable content, wait to call this until -- after the download completes. store.finishTransaction( transaction ) end store.init( transactionCallback ) -- Might try buying something here: -- store.puchase{ "com.anscamobile.NewExampleInAppPurchase.MyNonConsumableItem" } -- Or might try restoring here: -- store.restore() |
In App Purchases are not easy to set up. You may find that you spend more time setting things up in iTunes Connect and creating Provisioning Profiles than actually writing code. Here are some tips and links to help you along the way.
Apple Links
Other Links
How do you do step three on the walk through link?
EDIT: I was able to fetch valid product back from the sandbox, and the above documentation is correct. I am so sorry for posting something that wasn't fully tested properly.
1 2 3 4 5 6 7 | --what we see above and what we see in In-App Purchase demo code arrayOfProductIdentifiers = { "com.anscamobile.NewExampleInAppPurchase.MyConsumableItem", "com.anscamobile.NewExampleInAppPurchase.MyNonConsumableItem", "com.anscamobile.NewExampleInAppPurchase.MySubscriptionItem", } |
Please ignore this post (what it suggested does not seem to be true):
http://developer.anscamobile.com/forum/2011/06/28/loadproducts-problem
Also, remember to use Ad Hoc Distribution method to test on device. I read through the "Technical Note TN2259: Adding In App Purchase to your iOS Applications" just once before I started implementing In-App Purchase, but along the way, I found myself trying to test using dev distribution method, which absolutely failed and sent me trying to fix something that is not fixable (because what I thought was a problem was not a problem and need not and could not be fixed).
So what your saying is I need two list of iIdentifiers, one for the product id and one for what it is?
Also do I get the product identifier from itunes connect (manage in app) or the prov profile (it's probably itunes connect)?
Thanks.
@jeremyapplebaum12, let's resume this discussion on forum under In-App Purchase folder.
i am fresher to corona development i develop game it have 10 level .it is free game in that i will active first three level and we want play fourth level we want buy product. so implement in app purchase .its work but i have problem in .......
when i load app first time i will click product to buy it get error message itunes(could not connect itunes store)
and close app and open again it work prefect i.e i make purchase again its work correct purchase corectly
Does anyone know about the localization of prices? For example, when someone from Japan is playing my app, would the product[i].price return the value in US Dollar or in Japanese Yen?
Also, anyone knows how to display the price using the correct locale? The equivalent of the following code in native iOS?
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[numberFormatter setLocale:product.priceLocale];
NSString *stringPrice = [numberFormatter stringFromNumber:product.price];
[numberFormatter release];
Thanks!
"localizedPrice" will return the localized prize, i.e. the user's currency value and symbol, like "0,79€". (Note that when you use your own font, you should try test how it handles a symbol like "€", as you might be in for some font size surprise or so.)
I'm using below code in my games, use on your own risk :)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | function appLoadProductsCallback(event) if event ~= nil and event.products ~= nil then local price = nil for i = 1, #event.products do if event.products[i].productIdentifier == app.products[1].id then price = event.products[i].localizedPrice if price == nil or price == '' then price = event.products[i].price end break end end local priceText = appGetSpriteByType('buttonPart', 'price') if price ~= nil and priceText ~= nil then priceText.text = price app.diamondsPackPriceCached = price end end end |
Note things like "app.products" and "appGetSpriteByType" or "app.diamondsPackPriceCached" are specific to my framework, adapt as needed. Also I'm using a bit of a defensive code there which you may wanna throw out, depending (e.g. testing for nils of localizedPrice etc.)
I didn't see this stated explicitly anywhere, but store.restore() does not restore consumables.
page 19
i am fresher to corona development i develop game it have 10 level .it is free game in that i will active first three level and we want play fourth level we want buy product. so implement in app purchase .its work but i have problem in .......
when i load app first time i will click product to buy it get error message itunes(could not connect itunes store)
and close app and open again it work prefect i.e i make purchase again its work correct purchase corectly
I took 3 days trying to configure the In App Purchases, without success. Until I got to create a certificate Ad Hoc with the App ID that I have set in iTunes Connect for App.
My mistake was wearing a certificate for App Store with correct App ID, but the AD Hoc certificate test I was used for the App ID => *
:) :)
Hi everyone,
Is there any way to use In-app purchase in android in corona..?
Thanks,
-Vaibhav
i am fresher to corona development i develop game it have 10 level .it is free game in that i will active first three level and we want play fourth level we want buy product. so implement in app purchase .its work but i have problem in .......
when i load app first time i will click product to buy it get error message itunes(could not connect itunes store)
and close app and open again it work prefect i.e i make purchase again its work correct purchase corectly
Please tell more about downloadable content, how to organize everything, when you have 200-300 files in your in-app purchase pack.
The inAppDemo.zip uses
event.transaction.originalTransactionIdentifierbut the tutorial above usesevent.transaction.originalIdentifier, which one is correct, or am I misunderstanding this?