Tutorial – Swift In App Purchases
Today we will look at adding in app purchases in a swift app. This can also be viewed on youtube here.
Before we start if you haven’t already I highly recommend getting a developer account here. Without one you can’t fully setup your In App Purchases (IAP for short), you cannot test it properly to ensure it works correctly.
Once this is setup first of all we need to setup the app identifier and the in app purchases in iTunes connect. Head on over to the Apple developer centre and select member centre up the top. Then go on over to certificates, identifiers and profiles.
Go to identifiers, up the top click on the plus button, enter in seems.iap.
Make sure that Excplicit App ID is selected as for IAPs to work it needs to be explicit. Click next and go on through the steps to create the App ID.
Now is the time to create our app in iTunes connect. Create a new iOS App in my apps and select the App ID as the one we just created. Fill in the other fields as you wish.
Go into the App once created and select In App Purchases. Create a new In App Purchase and you will see several areas to fill out.
The two items we will be focusing on is consumable and non-consumable.
A consumable is something like buying coins in app – you can buy it only once or many times.
A non-consuable can only be purchased once. An example is something to remove ads in an app, or to unlock more features within an app.
We will setup one of each. The first item we will setup is a adding coins IAP. Select consumable There are several options to fill out as follows:
Reference Name: This will only show up in your iTunes financial reports. We will just add “additions”
Product ID: This is a unique identifier that is used to reference the in app purchase. We will need to remember this as we need to use it in Xcode later in setting up the in app purchases. We will use “seems.iap.addcoins”
Pricing & Availability: You select the price of the IAP here, it can be free or you can select from a large range of tiers. We will select Tier 1, the cheapest tier.
Language: You need to add at least one language which will be used to show the IAP name and description. Add your native language and add the name “Add Coins” and description “Add coins to your account”
Review Notes: If you want to clarify and details when submitting the app, you can do so here.
Screenshot for review: You must provide a screenshot when the app is submitted for each IAP. For example if your IAP removes adds I would place a screenshot of the App with ads removed.
Once you have setup these details select submit. We will repeat this process except making a non-consumable. This one will be remove ads. So in any names place “Remove Ads” and for the product id we will use “seemu.iap.removeads”.
Now that this is done open up XCode, it is time to setup our app and code the In App Purchases. Create a new single view application project and name it what ever you want – in our case we set it as “SeemuIAPTute”
The first order order of business is to set the bundle ID. To do this select the project and select it under targets. Select the “Info” menu and set the bundle identifier to “seems.iap”
Once this is done go over to the storyboard and add buttons and labels as follows:
Select he assistant editor from the top right , this will split the view into the storyboard on the left and the view controller.swift on the right. For each button label control click and drag to create the outlet and actions as follows:
@IBOutlet var lblAd: UILabel! @IBOutlet var lblCoinAmount: UILabel! @IBOutlet var outRemoveAds: UIButton! // Outlet for button remove ads @IBOutlet var outAddCoins: UIButton! // Outlet for add coins remove ads var coins = 50 // Also add this in for the coin amount - we use it later.
As above also create a variable to store the coin amount as we will need to use this later.
Along with these we need to create two IBActions for the buttons to run the code for the in app purchases.
@IBAction func btnRemoveAds(sender: UIButton) { } @IBAction func btnAddCoins(sender: UIButton) { } @IBAction func RestorePurchases(sender: UIButton) { }
Now that this is done close the split view, and open up the ViewController.swift so we can add the code for IAP’s! First of all you need to import store kit and add SKProductsRequestDelegate and SKPaymentTransactionObserver. It should end up looking something like this:
import UIKit import StoreKit class ViewController: UIViewController, SKProductsRequestDelegate, SKPaymentTransactionObserver{
Add the following code in so we can setup the buttons after to make a in app purchase. Each section is labeled with a number which will be explained below:
// 1 var list = [SKProduct]() var p = SKProduct() // 2 func buyProduct() { print("buy " + p.productIdentifier) let pay = SKPayment(product: p) SKPaymentQueue.default().add(self) SKPaymentQueue.default().add(pay as SKPayment) } //3 func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { print("product request") let myProduct = response.products for product in myProduct { print("product added") print(product.productIdentifier) print(product.localizedTitle) print(product.localizedDescription) print(product.price) list.append(product) } outRemoveAds.isEnabled = true outAddCoins.isEnabled = true outRestorePurchases.isEnabled = true } // 4 func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) { print("transactions restored") for transaction in queue.transactions { let t: SKPaymentTransaction = transaction let prodID = t.payment.productIdentifier as String switch prodID { case "seemu.iap.removeads": print("remove ads") removeAds() case "seemu.iap.addcoins": print("add coins to account") addCoins() default: print("IAP not found") } } } // 5 func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { print("add payment") for transaction: AnyObject in transactions { let trans = transaction as! SKPaymentTransaction print(trans.error) switch trans.transactionState { case .purchased: print("buy ok, unlock IAP HERE") print(p.productIdentifier) let prodID = p.productIdentifier switch prodID { case "seemu.iap.removeads": print("remove ads") removeAds() case "seemu.iap.addcoins": print("add coins to account") addCoins() default: print("IAP not found") } queue.finishTransaction(trans) case .failed: print("buy error") queue.finishTransaction(trans) break default: print("Default") break } } }
//1
The list will hold in all the Product ID’s of our in app purchases. In our case it is seems.aip.removeads and seem.iap.addcoins. The p variable is a temporary variable that stores the current IAP that is being processed.
//2
When a IAP is shown for purchase this code is automatically run to add it to a payment que.
//3
Later on in the viewDidLoad we will be adding code to load the IAP details from the iTunes connect servers. This will run this code which downloads all the details such as the title, price and description of it that was set earlier. Once they have all been downloaded we enable the buttons so the user can make a IAP, otherwise if they attempt to purchase anything before this is run, nothing will happen.
//4
Apple requires you to have a “Restore Purchases” somewhere in your app, to restore any existing in app purchases if the user reinstall’s the app. This will loop through every IAP, and check the product ID of it. For each product ID it find’s it will run the code to restore the purchase. E.g removeads() will remove the ads for the app if Remove Ad’s has been purchases – whose product ID is seems.iap.removeads. Note that this only applies to one off purchases.
//5
This is run once the user has paid for the in app purchase and the payment has been done. The product ID of the purchase is stored in p. The case statement checks if the purchase was successful (.Purchased) or Failed (.Failed). In the case of .Purchase it will check which product ID was purchased. Based on ours it will either remove the ads (removeAds()) or Add Coins to the users account (AddCoins()) In case of failure it will simply print a message to the console.
You may have noticed I included a lot of print statements in my code. I like to do this with the IAP code so I can’t keep a track of what’s going on as I’m testing it. Also if your still new to implementing IAPs it will help you understand what exactly is going on as you can see what methods are run and an in what order.
Now we have done this it is time to add in the removeAds() and addCoins() methods for the IAP. Also we need to add some code to the buttons so the user can make a purchase.
Make the following additions & changes to look like the following, each item will be explained again by it’s number.
// 1 override func viewDidLoad() { super.viewDidLoad() outRemoveAds.isEnabled = false outAddCoins.isEnabled = false outRestorePurchases.isEnabled = false if(SKPaymentQueue.canMakePayments()) { print("IAP is enabled, loading") let productID: NSSet = NSSet(objects: "seemu.iap.addcoins", "seemu.iap.removeads") let request: SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>) request.delegate = self request.start() } else { print("please enable IAPS") } } // 2 @IBAction func btnRemoveAds(_ sender: Any) { print("rem ads") for product in list { let prodID = product.productIdentifier if(prodID == "seemu.iap.removeads") { p = product buyProduct() } } } // 3 @IBAction func btnAddCoins(_ sender: Any) { for product in list { let prodID = product.productIdentifier if(prodID == "seemu.iap.addcoins") { p = product buyProduct() } } } // 4 func removeAds() { lblAd.removeFromSuperview() } // 5 func addCoins() { coins += 50 lblCoinAmount.text = "\(coins)" } // 6 @IBAction func btnRestorePurchases(_ sender: Any) { SKPaymentQueue.default().add(self) SKPaymentQueue.default().restoreCompletedTransactions() }
// 1
We disable the buttons to purchase anything as they have to load up the details such as the name, price & description. In Set maps we need to set our IAP product id’s (seems.iap.removeads and seemu.iap.addcoins). If the user does not have in app purchases enabled it will print a message to the console.
// 2
This runs the remove ads purchase. Since all in app purchases are stored in list, we must loop through it until we find the one to remove ads. We know this from it’s product id which is seems.iap.remove ads. Once it finds it, it will start the process to purchase the product in buyproduct.
// 3
This is the same as #2 excepct it is finding the one for remove coins.
// 4
This will remove the ads, which in our case is the label to subscribe to my youtube later. To save this for the user we would use NSUserDefaults which is covered in this tutorial.
// 5
This add’s 50 coins to the coin balance and updates the label displaying the amount of coins. As with before you would save and load this setting from the NSUserDefaults which will be covered in a future tutorial.
Now that the code is run we can test the In App Purchases…. well almost. First we need to setup a test account and development provisioning profile. Also testing In App Purchases in the iOS simulator doesn’t work fully Whilst they load and you can put in your password details, they can’t go through as a purchase for testing. So you will need to test it on a real iOS device.
To setup the development revising profile, go back to the Apple developer page. Press the + button to add a new one. We will be selecting iOS App Development for the type. This allows us to test the IAP’s without actually spending any money as it connects to test server.
Click next, and select the App ID we created earlier (seems.iap). Continue selecting all users and devices. Generate the certificate and download it. To install it ensure XCode is closed and then double click on the certificate from the downloads folder. This will install it silently so you won’t see anything. After a few seconds you can open up XCode again and set it up.
Go to the project properties and select Build Settings. Under Code Signing, Provisioning Profile and select the one you just made.
Now if you plug in your iOS device you should be able to select and run this app on it from the top left menu. The final step is to create test account to test the In App Purchases. To do this go to iTunes connect. Go to user’s and groups and select sandbox users up the top. Create a user in here with whatever details you want, it can all be made up just to test your In App Purchases.
Once that is setup you can run the app on your iOS device. To test the in app purchases click on either remove ads or add coins, for the username and password put in the email and password for the sandbox user you just made.
That’s it your done!. It is quite tedious and involved the first few times you implement it, after doing this a few times you get used to it and it will become seined nature!
Free Download – See App Earnings!
See how much competitor apps earn on the app store! A must have before you go ahead with your latest idea.