Requirements
Prerequisite knowledge
Experience building games for iOS with Flash Builder or Flash Professional and Adobe AIR will help you make the most of this article.
Required products
Flash Builder (Download trial)
Adobe Animate CC
Adobe AIR SDK
User level
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:
 
  • Offer your app for free and earn revenue with In-App Purchases
  • Tap into the revenue potential of impulse buys for free and paid users
  • Add support for In-App Purchases with just a few lines of code
  • Jumpstart development with a complete sample application, ActionScript 3 documentation, and a getting started guide
  • Verify your app's In-App Purchases with a test user before your app is live

 
Setting up In-App Purchases in iTunes Connect

Before you can use the iOS In-App Purchase extension, you'll need to set up your app on Apple's developer website.
 
 
Create an App ID and provisioning profiles
  1. Log into http://developer.apple.com and go to the iOS Dev Center.
  2. Click iOS Provisioning Portal.
  3. You need to create a custom App ID for your purchase-enabled application. Begin by clicking the App IDs category on the left, and then click New App ID (see Figure 1).
Figure 1. Click New App ID.
Figure 1. Click New App ID.
 
  1. Type a description and a bundle identifier for the App ID. For description, type the common name or description of the App ID. For the Bundle Seed ID, you may choose Use Team ID, unless you are planning to share data between applications. Consult Apple's documentation for more information on this selection. For Bundle Identifier, type the unique bundle ID suffix for your application, following Apple's recommended standard of reverse DNS naming; for example, type com.yourcompanysite.yourappname.
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.
 
  1. Click Submit.
  2. Back at the Provisioning Portal click the Provisioning category on the left. You should create at least two custom provisioning profiles for the application that you will be enabling for in-app purchases. One profile will be used for development and testing, and the other for distribution to the App Store.
  3. Click the Development tab and then click New Profile. For the Profile Name, type a descriptive name, such as yourappname dev provision. For Certificates, be sure your own certificate is selected. For App ID, select the App ID you just created. For Devices, select all the devices on which you want to test.
  4. Click Submit. When the Provisioning Portal finishes creating the profile (you may have to refresh the page if it says pending), download the provisioning file and save it to your disk. You'll need it later to test your application.
  5. Repeat the previous two steps, but this time start by clicking the Distribution tab to create a Distribution provisioning file. Download the resulting file and save it to your disk as well; you'll need to use it to publish your app to the App Store in the future.
 
Set up the contract and add the app in iTunes Connect
  1. Return to the main iOS Dev Center page, and click iTunes Connect.
  2. If you haven't already accepted the terms of the iOS Paid Applications contract under Contracts, Tax, and Banking, do so now.
  3. Now you need to register your app with Apple. From iTunes Connect, select Manage Your Applications.
  4. If you've already added your app in iTunes Connect, skip to the next section, Add An In-App Purchase.
  5. Click Add New App.
  6. On the App Information screen, select a Default Language and type the App Name and SKU Number for your app. For Bundle ID, select the Bundle ID you created earlier (see Figure 2).
  7. Click Continue. Finish setting up the rest of the basic information for your new app, including the release date, pricing tier, version information, rating information, metadata, icons, screenshots, and other required data. If you're just creating a test app, you can set the release date far in the future. At least one screenshot and icon are required to register an application. If you need placeholder graphics for screenshots and icons, some are provided in the /tutorial folder of the iOS In-App Purchase extension package.
Figure 2. Entering basic information about your app.
Figure 2. Entering basic information about your app.
 
  1. Click Save.
 
Add an In-App Purchase
  1. On the Manage Your Apps screen, click your app, and then click Manage In-App Purchases (see Figure 3).
Figure 3. Setting up In-App Purchases.
Figure 3. Setting up In-App Purchases.
 
  1. On the next screen, click Create New (see Figure 4).
Figure 4. Creating a new In-App Purchase.
Figure 4. Creating a new In-App Purchase.
 
  1. Select the type of In-App Purchase you are creating from Consumable, Non-Consumable, Auto-Renewable Subscription, Free Subscription, and Non-Renewing Subscription. Read the descriptions on this page for more information. Essentially, consumable items are things like magic spells that can be used up. Non-consumable items are permanent features, like level packs.
  2. On the next screen, type a Reference name and a product ID for the In-App Purchase. For Product ID, use Apple's recommended scheme of BundleID.productID; for example, if your bundle ID is com.yourcompanysite.yourappname, you might type com.yourcompanyname.yourappname.LevelPack as the Product ID of your level pack product.
  3. Click Add Language and add at least one language definition. Type in a Display Name (the name of the In-App Purchase that users will see) and a description (this will be used by Apple during the review process and visible to end users when your app is published).
  4. Click Save (see Figure 5).
Figure 5. Adding a name and description for the In-App Purchase
Figure 5. Adding a name and description for the In-App Purchase
 
  1. For Pricing and Availability, set Cleared for Sale to Yes. For Price Tier, select the cost of the item. (Click View Pricing Matrix for details.)
  2. For the screenshot, upload an image of your product in action. This is not shown to users, but is meant for Apple's review team to get an idea of what the product is supposed to do. You can upload a placeholder image for now from the /tutorial folder if you wish.
  3. Repeat the process for each In-App Purchase you want to add. When you're finished, click Save. Make a note of the Product IDs of all your In-App Purchases; you will need them in your application.
  4. Click Done.
 
Add a test user
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.
 
  1. Return to the iTunes Connect screen, and click Manage Users (see Figure 6).
Figure 6. Click Manage Users.
Figure 6. Click Manage Users.
 
  1. Click Test User.
  2. Click Add New User on the Manage Test Users screen (see Figure 7).
Figure 7. Adding a new test user.
Figure 7. Adding a new test user.
 
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.
 
  1. For First Name and Last Name, type whatever you wish. For Email Address, type a real address; make it unique. You should choose an email address at your own domain and remember it (even if the address doesn't actually exist). For example, type tester1@yourcompany.com. Specify a password and make note of it. Fill in the rest of the required information and click Save (see Figure 8).
Figure 8. Setting up the test user.
Figure 8. Setting up the test user.
 
  1. Click Done.
You're now ready to begin using the iOS In-App Purchase extension in your app.
 

 
Including the StoreKit API library

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:
 
  1. Create a new project of the type AIR for iOS.
  2. Choose File > Publish Settings.
  3. Click the wrench icon next to Script for ActionScript Settings.
  4. Select the Library Path tab.
  5. Click Browse For Native Extension (ANE) File and select the com.milkmangames.nativeextensions.StoreKit.ane file.
In Flash Builder 4.6:
 
  1. Go to Project Properties (right-click your project in Package Explorer and select Properties).
  2. Select ActionScript Build Path and click the Native Extensions tab.
  3. Click Add ANE and navigate to the com.milkmangames.nativeextensions.StoreKit.ane file.
In FlashDevelop:
 
  1. Copy the StoreKitAPI.swc file to your project folder.
  2. In the explorer panel, right-click the SWC and select Add To Library.
  3. Right-click the SWC file in the explorer panel again, select Options, and then select External Library.

 
Getting started with the API

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:
 
  1. Import the API Classes:
import com.milkmangames.nativeextensions.ios.*; import com.milkmangames.nativeextensions.ios.events.*;
  1. Initialize the API and create an instance of the StoreKit object. Make sure the current platform supports iOS purchases (PC, Android, and other platforms do not):
var storeKit:StoreKit; if(StoreKit.isSupported()) { storeKit=StoreKit.create(); } else { trace(“StoreKit only works on iOS!”); }
  1. Check if the specific device is set up for In-App Purchases. It is possible for parental controls or other settings to prevent purchases from being made at all, so you need to check this before using the other methods.
if(!StoreKit.storeKit.isStoreKitAvailable()) { trace(“this device has purchases disabled.”); return; }
  1. Set up all the necessary event handlers for StoreKit. It's a good practice to listen for all the possible events, including ErrorEvent events to avoid unexpected errors in your app:
// 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);
  1. Query the iTunes Connect server for a list of product details using the
  2. 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);
  1. When your user wants to purchase a product, you can use the 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); }
  1. Apple recommends that you add support in your app for situations in which a user downloads your app, makes In-App Purchases, uninstalls the app, and then re-installs it. In these cases, you'll want to include a button in your UI that restores the earlier In-App Purchase transactions (you should not perform this action automatically.) You can use 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.
 

 
Updating your application descriptor file

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.
 
  1. If it is not already set, set your AIR SDK version in the application descriptor file (use 3.2 below if you are using that version of the SDK):
<application xmlns="http://ns.adobe.com/air/application/3.1">
  1. Include a link to the extension in the descriptor:
<extensions> <extensionID>com.milkmangames.extensions.StoreKit</extensionID> </extensions>
  1. Make sure that your <id> property exactly matches the App ID you created in iTunes Connect.

 
Building the application

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.
 

 
Testing purchases with your test user account

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:
 
  1. Make sure your application descriptor file is set up with the App ID you created for your app.
  2. Make sure that you built your application with the ipa-debug or ipa-debug-interpreter target.
  3. Make sure that you built your application with the development version of the .mobileprovision file you created.
  4. Before starting your app on the device, go to Settings > Store, select your Apple ID, and tap Sign Out.
  5. Start your test app. When you try to make a purchase, it will prompt you to sign in, and the dialog box should be labeled with "Sandbox". Use the test user email and password you created in iTunes Connect.

 
Troubleshooting

If you're encountering errors or receiving notifications about invalid products, follow these troubleshooting tips:
 
  • Make sure you've agreed to the Paid Applications contract with Apple in the Contracts section of iTunes Connect.
  • Make sure that the App ID in your application descriptor file matches the App ID you created for the provisioning profiles exactly.
  • Make sure you are using the custom .mobileprovision files associated with your App ID to build your app.
  • Make sure the product IDs you pass to loadProductDetails() match exactly the ones you created in iTunes Connect.
  • Make sure you are using the test user account as you configured it.
  • You may need to wait 24 hours after creating products in iTunes Connect before they are available on the Apple test servers.

 
Where to go from here

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.