The best ways to get an in-app purchase working for iOS 7
(or iOS 8
) in XCode 5 or 6 is to do the following:
- go to itunes.connect.apple.com and log in
- click
manage your apps
then click the app you want do add the purchase into - click
manage your in-app purchases
- click
create new
in the top left hand corner - for this tutorial, were going to be adding a in-app purchase to remove ads, so choose
non-consumable
- for the reference name, put whatever you want (but make sure you know what it is)
- for product id put
com.companyname.appname.referencename
this will work the best, so for example, you could use com.brainademy.brainademy.removeads
- choose
cleared for sale
and then choose price tier as 1 (99¢). Tier 2 would be $1.99, and tier 3 would be $2.99. The full list is available if you click view pricing matrix
I recommend you use tier 1, because that's usually the most anyone will ever pay to remove ads. - Click the blue
add language
button, and input the information. This will ALL be shown to the customer, so don't put anything you don't want them seeing - for
hosting content with Apple
choose no - You can leave the review notes blank FOR NOW.
- skip the
screenshot for review
FOR NOW, everything we skip we will come back to. - press save
now that you've set up your in-app purchase information on iTunesConnect, go into your Xcode project, and go to the application manager (blue page-like icon at the top of where your methods and header files are) click on your app under targets (should be the first one) then go to general. At the bottom, you should see linked frameworks and libraries
click the little plus symbol and add the framework StoreKit.framework
If you don't do this, the in-app purchase will NOT work!
now we're going to get into the actual coding.
Add the following code into your .h
file:
BOOL areAdsRemoved;
- (IBAction)purchase;
- (IBAction)restore;
- (IBAction)tapsRemoveAdsButton;
and now add the following into your .m
file, this part gets complicated, so I sudgest you read the comments in the code:
#define kRemoveAdsProductIdentifier @"put your product id (the one that we just made in iTunesConnect) in here"
- (void)tapsRemoveAds{
NSLog(@"User requests to remove ads");
if([SKPaymentQueue canMakePayments]){
NSLog(@"User can make payments");
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:kRemoveAdsProductIdentifier]];
productsRequest.delegate = self;
[productsRequest start];
}
else{
NSLog(@"User cannot make payments due to parental controls");
//this is called the user cannot make payments, most likely due to parental controls
}
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
SKProduct *validProduct = nil;
int count = [response.products count];
if(count > 0){
validProduct = [response.products objectAtIndex:0];
NSLog(@"Products Available!");
[self purchase:validProduct];
}
else if(!validProduct){
NSLog(@"No products available");
//this is called if your product id is not valid, this shouldn't be called unless that happens.
}
}
- (IBAction)purchase:(SKProduct *)product{
SKPayment *payment = [SKPayment paymentWithProduct:product];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
- (IBAction) restore{
//this is called when the user restores purchases, you should hook this up to a button
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}
- (void) paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
{
NSLog(@"received restored transactions: %i", queue.transactions.count);
for (SKPaymentTransaction *transaction in queue.transactions)
{
if(SKPaymentTransactionStateRestored){
NSLog(@"Transaction state -> Restored");
//called when the user successfully restores a purchase
[self doRemoveAds];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
}
}
}
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{
for(SKPaymentTransaction *transaction in transactions){
switch (transaction.transactionState){
case SKPaymentTransactionStatePurchasing: NSLog(@"Transaction state -> Purchasing");
//called when the user is in the process of purchasing, do not add any of your own code here.
break;
case SKPaymentTransactionStatePurchased:
//this is called when the user has successfully purchased the package (Cha-Ching!)
[self doRemoveAds]; //you can add your code for what you want to happen when the user buys the purchase here, for this tutorial we use removing ads
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
NSLog(@"Transaction state -> Purchased");
break;
case SKPaymentTransactionStateRestored:
NSLog(@"Transaction state -> Restored");
//add the same code as you did from SKPaymentTransactionStatePurchased here
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
//called when the transaction does not finnish
if(transaction.error.code != SKErrorPaymentCancelled){
NSLog(@"Transaction state -> Cancelled");
//the user cancelled the payment ;(
}
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
}
}
}
Now you want to add your code for what will happen when the user finishes the transaction, for this tutorial, we use removing adds, you will have to add your own code for what happens when the banner view loads.
- (void)doRemoveAds{
ADBannerView *banner;
[banner setAlpha:0];
adsRemoved = YES;
removeAdsButton.hidden = YES;
removeAdsButton.enabled = NO;
[[NSUserDefaults standardUserDefaults] setBool:adsRemoved forKey:@"areAdsRemoved"];
//use NSUserDefaults so that you can load wether or not they bought it
[[NSUserDefaults standardUserDefaults] synchronize];
}
If you don't have ads in your application, you can use any other thing that you want, we could make the color of the background blue. To do this we would want to add
- (void)doRemoveAds{
[self.view setBackgroundColor:[UIColor blueColor]];
areAdsRemoved = YES
//set the bool for wether or not they purchased it to YES, you could use your own boolean here, but you would have to declare it in your .h file
[[NSUserDefaults standardUserDefaults] setBool:adsRemoved forKey:@"areAdsRemoved"];
//use NSUserDefaults so that you can load wether or not they bought it
[[NSUserDefaults standardUserDefaults] synchronize];
now somewhere in your ViewDidLoad method, your going to want to add the following code:
areAdsRemoved = [[NSUserDefaults standardUserDefaults] boolForKey:@"areAddsRemoved"];
[[NSUserDefaults standardUserDefaults] synchronize];
//this will load wether or not they bought the in-app purchase
if(areAdsRemoved){
[self.view setBackgroundColor:[UIColor blueColor]];
//if they did buy it, set the background to blue, if your using the code above to set the background to blue, if your removing ads, your going to have to make your own code here
}
Now that you have added all the code, go into your .xib
or storyboard
file, and add two buttons, one saying purchase, and the other saying restore. Hook up the tapsRemoveAds
IBAction
to the purchase button that you just made.
Next, go into iTunesConnect, and click manage users
then click test users
, and then click add new user
you can just put in random things for the name and last name, and the e-mail does not have to be real. You just have to be able to remember it. Put in a password (which you will have to remember) and fill in the rest of the info. iTunes store HAS to be in the correct country, though. Next, log out of your existing iTunes account. (you can log back in after this tutorial) and log in as the test user that you just created.
Now, run your application on your iOS device, if you try running it on the simulator, the purchase will alwayserror, you HAVE TO run it on your iOS device, once you've ran it on your device, click the purchase button, and when it asks you to confirm the purchase of 99¢ or whatever you set the price tier too, TAKE A SCREEN SNAPSHOT OF IT this is what your going to use for your screenshot for review
on iTunesConnect. Now cancel the payment
Now, go to iTunesConnect, then go to Manage your apps > the app you have the In-app purchase on > manage in-app purchases > click your in-app purchase, and click edit under in-app purchase details.
Once you've done that, import the photo that you just took on your iPhone into your computer, and upload that as the screenshot for review, then, in review notes, put your TEST USER e-mail and password. This will help apple in the review process.
After you have done this, go back onto the application on your iOS device, still logged in as the test user account, and click the purchase button. This time, confirm the payment Don't worry, this will NOT charge your account ANY money, test user accounts get all in-app purchases for free After you have confirmed the payment, make sure that what happens when the user buys your product actually happens. If it doesn't, then thats going to be an error with your doRemoveAds method. Again, I recommend using changing the background to blue for testing the in-app purchase, this should not be your actual in-app purchase though. If everything works and your good to go! Just make sure to include the in-app purchase in your new binary when you upload it to iTunesConnect! Below are some common errors:
Logged: No Products Available
this means that you didn't put in the correct in-app purchase ID, or, you didn't clear it for sale.
If it doesn't work the first time don't get frustrated and give up! It took me about 5 hours straight before I could get this working, and about 10 hours searching for the right code! If you use the code above exactly, it should work fine! Feel free to comment if you have any questions at all
Hope this helps to all of those hoping to add an in-app purchase to their XCode ios application! Cheers!