Skip to content

agoodman/inventory-kit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

36 Commits
 
 
 
 
 
 

Repository files navigation

Overview

InventoryKit is a free open source library that provides a synchronous (blocking) wrapper around Apple’s StoreKit API for managing in-app purchases. It also supports programmatic activation of products, allowing you to offer unique and exciting features to your users. In games, for example, you can have an achievement that unlocks a feature the player would otherwise need to buy. It’s also easy to include easter eggs that activate products. IK also makes it easy to prompt the user to buy a product, providing a simple asynchronous helper method and delegate interface.

IK 1.0 only supports non-consumable purchases. Future releases aim to include support for consumables and subscriptions. 2.0 is in active development (master) and includes consumables (only stored on the device, not available on other platforms) and auto-renewable subscriptions (synced with EnrollMint™, stored locally for offline support).

History

IK was originally written as part of Scorched Earth (App Store link) to transition between the “lite/paid” split app paradigm to the “free + in-app purchase” single app paradigm. The problem was the folks who bought the paid app should be able to continue to use the features they bought, while also taking advantages of updates. The strategy was to remove the “lite” version from the App Store and set the price of the paid version to zero (free). Then, the features from the paid version were made available as in-app upgrades. Clearly, the folks who already paid for the app would not be happy to be forced to pay again for the same features.

IK solves this problem by providing a transition mechanism, whereby you issue an update to your paid app before you perform the conversion process described above. This update includes a plist describing all the products to be transitioned, as well as a single line of code to be included in your app delegate. Release an update with this change, then wait a month or two to allow your users to update before releasing a second update to enable the in-app purchases.

In light of the Apple press release from 15 Feb 2011, announcing auto-renewable subscriptions as in-app purchases, IK is being upgraded to include subscription support. This requires a server to manage the subscriptions in a central location that is accessible to all network-connected devices. EnrollMint™ (http://enrollmint.com) was created to provide subscription management as a service. The service is free to use and charges 10% of your subscription revenues, billed quarterly. InventoryKit uses EnrollMint™ to sync subscription data to your user’s mobile device, allowing developers to integrate subscriptions into their apps quickly, easily, and free.

Installation

You are recommended to use IK as a git submodule. From your project’s git root directory, type this:

git submodule add git@github.com:agoodman/inventory-kit.git

Then, in Xcode, add the InventoryKit directory to your project. Once you’ve done that, you can use any of the IK API features by simply adding the following line to your .m file or, alternatively, to your xxx_Prefix.pch file:

#import "InventoryKit.h"

Finally, add this in your ApplicationDelegate’s application:didFinishLaunchingWithOptions: method:

[InventoryKit registerWithPaymentQueue];

Configuration

Once you have configured your in-app purchase products in iTunes Connect, you can use the product IDs with IK right away.

Transitioning Your App

The transition process is simple. Create a file in your resource bundle called TransitionProducts.plist. See the example in the IKExample app for more details. Once you have this file in your resource bundle, you must add the following line of code to your app delegate:

[InventoryKit prepareTransitionProducts];

That’s it. The first time the user runs the app after updating with this code included, IK will populate their inventory with the product IDs listed in the plist. Then, they will be ready to transition to the new paradigm, and they will have uninterrupted access to the features they bought.

NOTE: You must remove this line of code before publishing the free version of the app. Otherwise, you will be guaranteeing that every user has full access to all the in-app upgrades without paying you.

Bundles

With Scorched Earth 1.2, bundles were introduced. This feature allows you to package multiple in-app purchase products together as a bundle. Bundles are treated exactly the same as products. They each must have a unique product ID configured in iTunes Connect. You trigger a bundle purchase exactly the same way you do a stand-alone product. The difference is that IK looks for a configuration file (another plist) in your resource bundle. Create a new file in your project called IKBundles.plist. See the example in the IKExample app for more details. When IK receives successful purchase callbacks from StoreKit, it automatically activates all the product IDs associated with the given bundle product ID.

Consumables/Subscriptions

All products are considered non-consumable unless they are explicitly listed in one of two plist configuration files – one for consumables IKConsumableProducts.plist and one for subscriptions IKSubscriptionProducts.plist. Consumables are NSStrings as elements of a NSArray. Subscriptions are NSString/NSNumber key-value pairs as objects in a NSDictionary, where the key is product ID and the value is subscription duration in seconds.

Usage

Using IK is a snap. There are a handful of synchronous methods for querying and manipulating product activation. There are also a handful of asynchronous methods and a corresponding callback system for guiding the user through the purchasing process and for restoring purchases the user made (potentially on a different device).

Product Activation

Non-Consumables

  • Activate/Deactivate a Product
[InventoryKit activateProduct:@"your.product.id"];
[InventoryKit deactivateProduct:@"your.product.id"];
  • Query Product Activation
BOOL isActivated = [InventoryKit productActivated:@"your.product.id"];

Consumables

  • Activate Quantity
[InventoryKit activateProduct:@"your.product.id" quantity:3];
  • Query Quantity Availability
int tQuantityAvailable = [InventoryKit quantityAvailableForProduct:@"your.product.id"];
BOOL tCanConsume = [InventoryKit canConsumeProduct:@"your.product.id" quantity:3];
  • Consume Quantity
[InventoryKit consumeProduct:@"your.product.id" quantity:3];

Subscriptions

  • Time-limited Product Activation
[InventoryKit activateProduct:@"your.product.id" expirationDate:yourDate];
  • Query Product Activation
BOOL isActivated = [InventoryKit productActivated:@"your.product.id"];

Product Purchase

Non-Consumables and Single Unit Consumables

Delegate-based

[InventoryKit purchaseProduct:@"your.product.id" delegate:yourDelegate];

Block-based

IKBasicBlock tStart = ^{ 
  // notify user of pending transaction using dispatch_async to schedule operations on the main thread
};
IKStringBlock tSuccess = ^(NSString* productKey) {
  // notify user of successful purchase using dispatch_async to schedule operations on the main thread
};
IKErrorBlock tFailure = ^(int code, NSString* description) {
  // notify user of failed purchase using dispatch_async to schedule operations on the main thread
};
[InventoryKit purchaseProduct:@"your.product.id" startBlock:tStart successBlock:tSuccess failureBlock:tFailure];

Multiple Unit Consumables

Delegate-based

[InventoryKit purchaseProduct:@"your.product.id" quantity:3 delegate:yourDelegate];

Block-based

IKBasicBlock tStart = ^{ 
  // notify user of pending transaction using dispatch_async to schedule operations on the main thread
};
IKStringBlock tSuccess = ^(NSString* productKey) {
  // notify user of successful purchase using dispatch_async to schedule operations on the main thread
};
IKErrorBlock tFailure = ^(int code, NSString* description) {
  // notify user of failed purchase using dispatch_async to schedule operations on the main thread
};
[InventoryKit purchaseProduct:@"your.product.id" quantity:3 startBlock:tStart successBlock:tSuccess failureBlock:tFailure];

Restore Purchases

Delegate-based

[InventoryKit restoreProducts:yourDelegate];

Block-based

IKBasicBlock tSuccess = ^{
  // notify user of successful purchase using dispatch_async to schedule operations on the main thread
};
IKErrorBlock tFailure = ^(int code, NSString* description) {
  // notify user of failed purchase using dispatch_async to schedule operations on the main thread
};
[InventoryKit restoreProductsWithSuccessBlock:tSuccess failureBlock:tFailure];

Profit

That’s it. You’re ready to make money. InventoryKit is free to use and improve, but I always accept donations. Please send them via PayPal to aubrey.goodman@gmail.com. Remember me when you make your millions.

If you’re using subscriptions with EnrollMint™, you’ll receive an invoice quarterly. EnrollMint™ tracks subscription prices in real-time, eliminating the need for developers to update pricing on both iTunes Connect (ITC) and EnrollMint™. Simply set your prices in ITC and they will automatically be updated.

© 2009-2011 Migrant Studios. All rights reserved.