In App Purchases – for Upgrading Free App

Just finished implementing in-app purchases for Russian Bingo. I implemented a button in the last version, to determine how many of our users actually wanted more vocabulary levels. Well, it is hovering around 10% for Russian and 30% for Mandarin. Note though that Russian has a much larger sample set- at 2K – than Mandarin (at 3, ha!).

The best resource I found out there was this site: In App Purchases- A Complete Walkthrough. Some additional comments I wanted to make:

1) In the iTunes Connect site, create a “test user.” The option is to create an iTunes Connect User, or Test User.

2) I did have problems initially with getting the product ID. The solution for me was to delete my build from my iPhone, clean it, and re-install and run before the product request worked. Troy has a great checklist on his subsequent blog post regarding troubleshooting the product query.

While his code is good almost straight from his blog, I wanted to know how people wired up the methods from the PurchaseManager into their app, so this is how I did it:

1) I have a button on a view controller that initializes the purchase action.

[FlurryAnalytics logEvent:@"buy levels"];
InAppPurchaseManager *appMgr = [[InAppPurchaseManager alloc] init];
BOOL can_buy = [appMgr canMakePurchases];
[appMgr purchaseProUpgrade];
} else {
NSLog(@"notify cannot buy");
[self cannotBuyAlert];

“Can Buy” is the check to see if the user is of age, I believe. It’s just recommended by Apple. The “purchaseProUpgrade” is the method you tested in the Product Query phase, and it starts the ball rolling. I’m doing analytics initially to see how many people were interested, and now I’ll keep it in there to see if the transaction deters folks.

4) You have to prep the app for the store and start the observer, so, in the app Delegate, “didFinishLaunching” method, I included these four lines:

InAppPurchaseManager *purchman = [[InAppPurchaseManager alloc] init];
[purchman loadStore];

/* I also check if the user has bought by grabbing the user default */
self.has_bought = [[NSUserDefaults standardUserDefaults] boolForKey:@"isProUpgradePurchased" ];
/* nice to blog while troubleshooting */
NSLog(@"has_bought: %@\n", (has_bought ? @"YES" : @"NO"));

“self.has_bought” is an instance property that I use throughout the game to check whether the user has completed a purchase. I set this variable to the UserDefaults (as per Troy’s recommendation) at the final step of the transaction, when you are about to deliver the content.

- (void)provideContent:(NSString *)productId
if ([productId isEqualToString:kInAppPurchaseProUpgradeProductId])
// enable the pro features
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"isProUpgradePurchased" ];
[[NSUserDefaults standardUserDefaults] synchronize]; /* writes to device the setting */
myDelegate *appDelegate = (myDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.has_bought = YES; /* instance prop that is checked throughout app */
[appDelegate loadMoreBoards]; /* my product initialization */


Note: Testing the Product Query
To test the Product phase, I did relatively the same, except instead of “LoadStore,” I ran the method “-(void)requestProUpgradeProductData;”. Also, done in the appDelegate’s “didFinishLaunching” method.

InAppPurchaseManager *purchman = [[InAppPurchaseManager alloc] init];
[purchman requestProUpgradeProductData];

I didn’t do any other bells and whistles to wire up the store, and I only have a single upgrade option so it’s simply one PropertyId. I do hide the purchase button once the boolean “has_bought” has been set, and instead I reveal a label that says “thanks for purchasing.”