29 May 2012
Experience building games for iOS with Flash Builder or Flash Professional and Adobe AIR will help you make the most of this article.
Intermediate
With the iOS In-App Purchase native extension for Adobe AIR from Milkman Games, you can rapidly integrate In-App Purchases via the App Store into your mobile AIR application using ActionScript 3.
The iOS In-App Purchase extension is a completely native iOS solution that enables you to:
Before you can use the iOS In-App Purchase extension, you'll need to set up your app on Apple's developer website.
Note: Take note of your bundle ID, as it will need to be matched exactly by the <id> property in your AIR application descriptor file later.
The final step is to add a Test User to the Sandbox. A Test User is a fake iTunes account that you can use for testing In-App Purchases. It will behave just like a real account, except no money will actually be deducted when the test purchases happen.
Now, set up the fake user that you will use for testing purposes. Later, you will be able to login to the store as this user when testing your application, and complete the purchase flow without actually having any money charged to your account.
You're now ready to begin using the iOS In-App Purchase extension in your app.
The next step is to add the com.milkmangames.nativeextensions.StoreKit.ane library to your project. (If you are not using Flash Builder 4.6 and later or Flash Professional CS6 and later you'll need to add the StoreKitAPI.swc library instead.)
In Flash Professional CS6:
In Flash Builder 4.6:
In FlashDevelop:
You can start using the iOS In-App Purchase extension with a few simple calls. See example/StoreKitExample.as for a full example that shows how to make purchases, restore transactions, saving state of purchased items, and more.
Follow these steps to get started:
import com.milkmangames.nativeextensions.ios.*;
import com.milkmangames.nativeextensions.ios.events.*;
var storeKit:StoreKit;
if(StoreKit.isSupported())
{
storeKit=StoreKit.create();
}
else {
trace(“StoreKit only works on iOS!”);
}
if(!StoreKit.storeKit.isStoreKitAvailable())
{
trace(“this device has purchases disabled.”);
return;
}
// Listen for events.
StoreKit.storeKit.addEventListener(StoreKitEvent.PRODUCT_DETAILS_LOADED,onProductsLoaded);
StoreKit.storeKit.addEventListener(StoreKitEvent.PURCHASE_SUCCEEDED,onPurchaseSuccess);
StoreKit.storeKit.addEventListener(StoreKitEvent.PURCHASE_CANCELLED,onPurchaseUserCancelled);
StoreKit.storeKit.addEventListener(StoreKitEvent.TRANSACTIONS_RESTORED,onTransactionsRestored);
// adding error events. always listen for these to avoid your program failing.
StoreKit.storeKit.addEventListener(StoreKitErrorEvent.PRODUCT_DETAILS_FAILED,onProductsFailed);
StoreKit.storeKit.addEventListener(StoreKitErrorEvent.PURCHASE_FAILED,onPurchaseFailed);
StoreKit.storeKit.addEventListener(StoreKitErrorEvent.TRANSACTION_RESTORE_FAILED,onTransactionRes
toreFailed);
StoreKit.storeKit.loadProductDetails() method. Before you can buy anything in your app, you need to pass a list of one or more product IDs (which you created in Add an In-App Purchase) to the server. You'll receive a response with detailed information about the In-App Purchases that is tailored to the particular user. For instance, the price in the response will match their region, and so on. If any of the IDs you pass in are not found on the server, you'll also get a response indicating this. You should wait for the product details response event before starting to make purchases.// the first thing to do is to supply a list of product ids you want to display,
// and Apple's server will respond with a list of their details (titles, price, etc)
// assuming the ids you pass in are valid. Even if you don't need to use this
// information, you must make the details request before doing a purchase.
// the list of ids is passed in as an as3 vector (typed Array.)
var productIdList:Vector.<String>=new Vector.<String>();
productIdList.push(“com.yourcompany.yourapp.LevelPack”);
productIdList.push(“com.yourcompany.yourapp.MagicSpell”);
// when this is done, we'll get a PRODUCT_DETAILS_LOADED or PRODUCT_DETAILS_FAILED event and go
on from there...
StoreKit.storeKit.loadProductDetails(productIdList);
StoreKit.storeKit.purchaseProduct() method. One of three events will fire when the transaction is complete: StoreKitEvent.PURCHASE_SUCCEEDED , StoreKitErrorEvent.PURCHASE_FAILED , or StoreKitEvent.PURCHASE_CANCELLED . The PURCHASE_CANCELLED event fires if the user taps the Cancel button or otherwise declines to make the purchase.// this call purchases a product. The second parameter is an optional quantity- if you want to
// purchase more than one item at a time.
StoreKit.storeKit.purchaseProduct(“com.yourcompany.yourapp.MagicSpell”,1);
// this event is fired when a purchase goes through ok
private function onPurchaseSuccess(e:StoreKitEvent):void
{
// your app is now responsible for 'giving' the user whatever they bought!
giveUserItem(e.productId);
}
// this event happens when something goes wrong with the purchase
private function onPurchaseFailed(e:StoreKitErrorEvent):void
{
trace(“there was an error buying the product:”+e.text);
}
// this event happens if the user pressed cancel instead of buying
private function onPurchaseUserCancelled(e:StoreKitEvent):void
{
trace(“the user decided not to buy “+e.productId);
}
StoreKit.storeKit.restoreTransactions() to implement this feature. The StoreKitEvent.PURCHASE_SUCCEEDED event will fire for every item previously purchased, so you can give each item to the user. When the process is complete, you'll receive the StoreKitEvent.TRANSACTIONS_RESTORED event. If something goes wrong, StoreKitErrorEvent.TRANSACTION_RESTORE_FAILED will be dispatched.// this will make a PURCHASE_SUCCEEDED event happen again for anything the user has bought
// previously for your app. When it's all done, the TRANSACTIONS_RESTORED event will occur.
StoreKit.storeKit.restoreTransactions();
// this event is fired when a restore is finished.
private function onTransactionsRestored(e:StoreKitEvent):void
{
// your app got PURCHASE_SUCCEEDED for each old purchase, and should've
// give the items to the user.
trace(“restore complete!”);
}
// this event happens when something goes wrong with the restore
private function onTransactionRestoreFailed(e:StoreKitErrorEvent):void
{
trace(“there was an error restoring transactions:”+e.text);
}
That covers the basics of the API. Note that you'll want to initialize the iOS In-App Purchase extension and start listening for its events as early as possible in your app. This way, if the user had initiated an In-App Purchase and then received a phone call or other interruption that closed your app, your app will be ready to finish the transaction events as soon as it restarts.
In your application descriptor file, you need to specify the version of the AIR SDK you are using (3.1 or later) as well as a link to the extension. For a working example, see example/app.xml.
<application xmlns="http://ns.adobe.com/air/application/3.1">
<extensions>
<extensionID>com.milkmangames.extensions.StoreKit</extensionID>
</extensions>
<id> property exactly matches the App ID you created in iTunes Connect.If you're using Flash Builder 4.6 or later (or Flash Professional CS6 or later) and have added the StoreKit extension library as described above, then you can compile as you usually do directly from your IDE. If not and you are building your app with the extension from the command line, then you'll need to specify the directory containing the com.milkmangames.nativeextensions.StoreKit.ane file.
Here is an example build command line:
[PATH_TO_AIR_SDK]\bin\adt -package -target ipa-test-interpreter -storetype pkcs12 -keystore [YOUR_KEYSTORE_FILE] -storepass [YOUR_PASSWORD] -provisioning-profile [YOUR_MOBILEPROVISION_FILE] myapplication.ipa app.xml myapp.swf -extdir [DIRECTORY_CONTAINING_ANE_FILE]
When you're building a version of your app for testing be sure you use the development version of the .mobileprovision file. You'll also need to make sure the file is installed on the test phone–just drag the file to iTunes and then sync.
You can and should use the distribution version of the .mobileprovision file when building the release version of your app to upload to the App Store.
In completing the steps in Setting up In-App Purchase in iTunes Connect, you created a test user in iTunes Connect for testing the purchase flow without actually spending money. Follow these steps to use the test user account to test your implementation:
ipa-debug or ipa-debug-interpreter target.If you're encountering errors or receiving notifications about invalid products, follow these troubleshooting tips:
loadProductDetails() match exactly the ones you created in iTunes Connect.The example application included with the iOS In-App Purchase download package shows how to track In-App Purchases with a simple client-based model. However, you can also use your own server to track, verify, and provide In-App Purchase content. For more information on how this is implemented, see Apple's most recent documentation. The iOS In-App Purchase extension provides the receipt data you need to pass to your server in this case, as the property receipt of the StoreKitEvent.PURCHASE_SUCCEEDED event, which is dispatched after a purchase.
Now that you have the iOS In-App Purchase extension for iOS up and running, you may want to explore the ActionScript 3 documentation or check out the other tools from available from Milkman Games.

This work is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License.