Adding In-App Store to Cocos2D
There's been a few good tutorials about setting up items for purchase on In-App Stores (http://blog.mugunthkumar.com/coding/iphone-tutorial-–-in-app-purchases/ and http://troybrant.net/blog/2010/01/in-app-purchases-a-full-walkthrough/ were helpful) but there were some missing pieces about how to create a singleton to manage the store and how to display the results. The design pattern we use follows some of the singleton conventions in Cocos2D, and we've used it to create an in-app store to allow users to purchase level upgrades and multiple character upgrades and display the store using either UIKit or Cocos2D.
As a first step, you need to enable your products for sale with In-App Purchasing, including creating a unique App ID and provisioning profile. Then you'll need to create your products.
To manage the display and purchase of the in-app purchases, we created the following singleton class using the Cocos2D design pattern:
InAppPurchaseManager.h
InAppPurchaseManager.m
The usage of this singleton is pretty simple. First, before calling your product display view/scene initialize the store with this call:
[[InAppPurchaseManager sharedInAppManager] loadStore];
This will asynchronously load the store data for later display. We use plists to store the in-app store products names and titles, and then use this information to display a simple summary via a UITableView. The tricky part is knowing when the product data has loaded. We could have used an NSNotificationCenter callback but instead decided to have a simple function to poll whether the store loaded. We poll this function with an NSTimer, repeating every 5 seconds:
if ([[InAppPurchaseManager sharedInAppManager] storeLoaded])
{
// Update the UI to show that the store has loaded, ie. the user can make a purchase
}
After the user selects an item they'd like to buy, we display a more detailed view/scene that loads descriptions from the in-app store and stores them in SKProduct records. We do this with calls to product specific methods within the singleton:
SKProuct *prod = [[InAppPurchaseManager sharedInAppManager] getLevelUpgradeProduct];
We've written methods for each of our products and then keep track of the product index (ie., the displayed list of products) using a plist so we can change the display order if we'd like to promote one product higher than another for example. Once the user is satisfied with the details of the product and decides to make a purchase, we call the
And during initialization of our scene/view, we register for NSNotificationCenter callbacks for the purchase success or failure:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(purchaseSuccess:) name:kInAppPurchaseManagerTransactionSucceededNotification object: nil];
Where the purchaseSuccess: method displays a simple thank you message. Last but not least, we need to provide a way for the user to restore previous purchases if they upgrade devices, etc. We needed to support this because our products are consumable. This simply means you need to eventually place a button in your in-app store scene/view which makes a call to this method:
[[InAppPurchaseManager sharedInAppManager] restoreCompletedTransactions];
With that, you're up & running. Good selling!
--yarri
Reader Comments (12)
Great thanks!
This is a bookmark :)
Great post, and source code. Thank you!
I added the singleton to my project, and it all seems to work well, but it attempts to purchase the product twice, as if finishTransaction isn't being called. You say in the post that you add an observer called purchaseSuccess. Is this method supposed to call your completeTransaction function so that finishTransaction is called? If so, how do you get the transaction details?
Cheers,
Andrew.
I'd actually love to review these boxes on my shopping/lifestyle blog. i wonder if they'd send me a sample box to talk about? nzolta nzolta - Moncler Daunenjacke.
I Really enjoyed your blog. I just bookmarked it. I am a regular visitor of your website I will share It with my friends .Thanks.......
Thanks for this post. It's proving to be very useful. Putting In-App purchase in cocos2d was a PITA until I came across your post. I'm not done implementing it yet but i got further with your example than with any other I could find.
I am creating grenades that the user can buy in packs of five in the game. How can you keep track of how many grenades the user has bought so far, then subtract one each time he uses a grenade?
Can get full complete code ?
Great post, thanks. I was thinking about trying out in-app, so you have the perfect timing :)
(It is sad to see so much spam in the comments though.)
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(purchaseSuccess:) name:k this is line is missing some code... what is the k for?
kInAppPurchaseManagerTransactionSucceededNotification
Hi, I am new to iOS development and I'm trying to implement IAP but I'm having a little bit of trouble getting my head around how to actually make the purchase. I've got a buy button which i want to start the transaction. This button is in a class which imports InAppPurchaseManager.h and StoreKit. I've implemented and tested the code provided and the product is being fetched correctly.
-(void) buy: (id) sender {
/*In-App Code*/
if ([[InAppPurchaseManager sharedInAppManager] storeLoaded])
{
NSLog(@"The Store has loaded");
// Update the UI to show that the store has loaded, ie. the user can make a purchase
SKProduct *prod = [[InAppPurchaseManager sharedInAppManager] getLevelUpgradeProduct];
NSString *desc = prod.localizedDescription;
NSString *title = prod.localizedTitle;
NSDecimalNumber *price = prod.price;
NSLog (@"Title %@", title);
NSLog (@"Description %@", desc);
NSLog (@"Price %@", price);
if( [[InAppPurchaseManager sharedInAppManager] canMakePurchases]){
[[InAppPurchaseManager sharedInAppManager] purchaseLevelUpgrade];
}
// [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(purchaseSuccess:) name:kInAppPurchaseManagerTransactionSucceededNotification];
}else{
NSLog(@"The Store has not loaded");
}
}
I'm not really sure what I'm doing, can anyone help?
I am totally impressed with your work because your work is very grateful. I really like it very much. Your post and article is really informative.
It's very useful and helpful for me and everyone. Thanks for this informative post. Please give us more information. Keep it up