Pages

Monday, August 8, 2011

In App Purchase Made Easy

In App Purchase with MKKit

The MKKit includes several specialty view controllers. In this blog I'm going to show you to the MKIAPViewController. This drop-in controller provides an interface and methods for processing inApp Purchases.

The goal of the inApp Purchase Controller is to provide an intuitive store front to the user, and an easy purchase delivery to the developer.

The end result looks like this:



All of the information for this table is pulled from the appStore. The buttons are designed to mimic the buttons on the appStore. When the user taps on one of the buttons it will turn green and say "Installing". When the purchase is complete it will revert to blue and say "Installed". If the purchase is not completed the button will say "Retry".  When the info button is tapped it will display an alert view giving the description that is listed in the appStore.  This button is replaced with an round activity indicator as the purchase is being processed.

Initializing 

How do you add this controller into your app? It is really quite simple.


NSSet *items = [NSSet setWithObjects:BACKUP_TOOL_ID, IN_APP_WEB_ID, nil];
MKIAPViewController *viewController = [[MKIAPViewController alloc] initWithIdentifiers:items observer:self];

From here the controller can be presented as a model view or added to navigation stack. The NSSet passed to the initWithIdentifiers:observer: method must contain the identifiers of you inApp Purchases. These are need to fill the data of the view and to complete transactions. The object passed as the observer needs to implement the MKIAPObserver protocol.

The only thing that this controller does not do is provide the content for your inApp Purchase. That is done through the MKIAPObserver protocol. This protocol only has one method.

- (void)didCompleteEvent:(MKIAPEvent)event forIdentifiers:(NSSet *)identifiers;

This method is called at different stages of inApp transaction processing. Each stage can be identified using the MKIAPEvent that is passed.  There are four types of defined events that will be passed to this method they are defined as:

typedef enum {
    MKIAPEventRequestComplete,
    MKIAPEventRequestFailed,
    MKIAPEventPurchaseComplete,
    MKIAPEventRestoreComplete,
} MKIAPEvent;

The NSSet that is passed through this method contains the identifiers of all the items that the event applies to.  If you are using the storefront provide by MKIAPViewController the only event you need to worry about is MKIAPEventPurchaseComplete.  When this event is posted, you need to provide the content of you inApp Purchase. Here is the what observer method may look:

- (void)didCompleteEvent:(MKIAPEvent)event forIdentifiers:(NSSet *)identifiers {
    if (event == MKIAPEventPurchaseComplete) {
        for (NSString *identifier in identifiers) {
            if ([identifier isEqualToString:BACKUP_TOOL_ID]) {
                [[NSUserDefaults standardUserDefaults] setBool:YES forKey:BACKUP_TOOL_PURCHASED];
            }
            if ([identifier isEqualToString:IN_APP_WEB_ID]) {
                [[NSUserDefaults standardUserDefaults] setBool:YES forKey:IN_APP_WEB_TOOL_PURCHASED];
                [[NSUserDefaults standardUserDefaults] setBool:YES forKey:OPTION_WEB_ACCESS_ON];
            }
        }
    }
}

Under the Hood

This controller is powered by the MKIAPController class. This class handles all the communication with the appStore and processes inApp Purchase transactions and requests.  This class was built as stand-alone class, so if you want to design your own storefront you can still use its methods for your transactions. 

MKIAPController was also designed with easy implementation in mind. It takes advantage of iOS's Grand Central Dispatch to provide quick and powerful implementation. 

For an example of this I will use the restorePurchase: method. Even if you are using provided store front, this method needs to be called directly. Here is how that would look using the implementation blocks:

[MKIAPController restorePurchase: ^ (SKPaymentTransaction *transaction, NSError *error) {
        if (error != nil) {
            //Process Transaction
        }
    }];
 
Simular methods are provided for data and purchase requests as well. You can also create and instance of MKIAPController and observer actions through the MKIAPDelegate protocol. 

This controller is part of the MKKit available on github @ https://github.com/matt62king/MKKit.