2009 • 31:57
With iPhone 3.0 SDK you can request payment for subscriptions, additional game levels, or other content from within your applications. This session covers the entire purchase life cycle for in-app payments, including use of the Store Kit APIs, the product submission process, proper product presentation, purchase authentication, and transaction validation.
Speaker: Mark Malone
Unlisted on Apple Developer site
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Hello, I'm Mark Malone, iPhone and Server Technologies Evangelist. In this video you'll learn the overall architecture and the steps required to successfully add in-app purchase to your app. More than an overview, this session is designed to highlight the most critical steps and best practices you'll use to ensure a stress-free implementation. So let's begin.
So here's our agenda, what we'll cover today. First, a bit of overview and some architecture, the development and production preparation steps you'll need to take, as well as some implementation details, the things that you'll need to do within your application, perhaps on your server as well. And then finally, we'll wrap it up with some debugging techniques.
Throughout this presentation you'll see these little stars next to the bullets. The goal is that you've read the documentation and this just isn't going to reiterate the things in the documentation, but these little gold stars are there to demarcate items where folks have been confused or gotchas, things that have tripped up people as part of their implementation. So keep mindful of these.
So, overview and architecture. Let's get into some details. At the top level, In-App Purchas is there to allow you, within your application, to leverage the App Store Catalog and Billing system. You're able to sell access to built-in features or perhaps remote content. You're able to provide localized price information as well as product descriptions. And the App Store collects the payment for you, and you, in turn, unlock the features within your app.
And implementing in-app purchase is easy. There's lots of functionality for very little code. You get localized pricing and product detail information. There's no credit card processing that you need to build into your application. The App Store manages the checkout with familiar screens that your customers are used to.
And of course, there is no server required as part of this. And there's plenty of great implementations of in-app purchase already up on the App Store. All sorts of things: buying content, driving directions, game levels, you name it. There's a way to use in-app purchase in order to add value to your application.
So let's look at the architecture. There's four moving parts that I'm going to talk about. Four of the main moving parts. First and foremost, there's your application. All that's required is iPhone OS 3.0 or better, an iPod Touch, or an iPhone, as well as a cellular plan or Wi-Fi connection so that we can talk to the back-end network in the App Store.
On the App Store side, well, you're going to access the App Store via the Store Kit frameworks. We provide localized product metadata descriptions and pricing, collect the payments, and we also provide transaction recovery for installation of an application on a new device for one of your customers and allowing you to recover the transactions they've already paid for.
There's also an optional server that you could provide where you could deliver purchase content. You can also validate the purchase receipts associated with the purchase transactions. And a cloud service that we provide through iTunes for receipt validation. Now keep in mind that both of these parts are optional. You don't need to validate the receipts. And delivering content that's sitting on a server is purely a design consideration for your application.
So let's look at the in-app purchase workflow. The first step that you're going to want to implement is requesting product IDs. These product IDs are the potential products you may sell within your application using in-app purchase. Now you might request those product IDs from your server using a web service call, bring them back into your application, or you might load them from your application bundle itself, or maybe you have them as a set of constants within your application.
Step one is that you want to get them into your application. Step two is you're going to take that set of potential product IDs and validate them. You're going to validate them using the Store Kit framework to talk to the App Store itself. So you pass those product IDs off to the App Store. The App Store is going to pass you back what is considered a valid set of product IDs.
Then within your application you're going to present the display of items for your users, and then your user is going to select an item for purchase, and you're going to pass that product, the one they selected, back to the App Store using the Store Kit framework to request payment for that particular product. As a result of the user walking through a series of dialogues, you will get passed back a receipt associated with a successful transaction.
Now if you're implementing purchase validation, you'll want to pass that receipt back up to your server, and then you'll call our iTunes URL, passing that receipt for validation. We'll look up that transaction in our back-end database, and then pass you back the result. We'll let you know if that was a successful transaction, a verified transaction. And then of course you'll pass that back to your application for unlocking the purchase for your user.
It's that simple. So let's get into some nitty-gritty details. Preparation and implementation. These are the steps that you're going to perform in order to get everything set up. And then finally, what you're going to do within your application to make sure that you adopt the right techniques. So there's four moving parts that I'm going to talk about here as part of preparation and implementation.
There's the program portal, a place you're used to interacting with when you go and register IDs or request certificates. There's iTunes Connect, where you've recently uploaded your applications or provided metadata for your applications. There's some things that you need to do, obviously, within your application, the implementation of Store Kit APIs. And then finally, if you're doing purchase validation, then you're going to take advantage of a couple of steps on the server as well. So let's take a look at each of these in some detail.
On the development preparation side, you're going to start at the Developer Program Portal. And the first step there is you need to enable your App ID for in-app purchase. This is required in order for you to go into iTunes Connect at a later step and enter the products associated with your application for sale. So do this first. Until you associate an App ID with in-app purchase, none of the iTunes Connect features are going to be turned on for you.
Another thing to keep in mind is that no wildcards are allowed for app IDs associated with in-app purchase, or push notification for that matter. So make sure that you have a non-wildcarded app ID associated with in-app purchase. If you've got an existing application and you're just merely updating it to add in-app purchase, it's as easy as creating a new app ID, the same as the previous one, and just leaving out the wildcard.
From the store's perspective, it'll look just like an update. The user will be notified that your new version is up there. There won't be any issue with access to the local documents directory, anything like that. It'll be just like an in-place update. So here's the UI that you'll see once you select the appropriate app ID. And you'll see over on the right hand side there's a configure button. So tap that configure button.
And you'll see some details associated with your app ID. All that's required for enabling in-app purchase is to check the checkbox saying "Enable in-app purchase." A little green light will go on and you're good to go. And you're all done in the Program Portal. That's it. That one step. Next step, let's go into iTunes Connect and do a few things there.
So within the iTunes Connect, we're going to first verify that you've got appropriate contracts in place. You're going to add your application. You don't need to upload your binary yet, but get some critical meta data information in there first. You're going to add your products. And then finally you're going to create a test user for testing in-app purchase within your application.
So let's begin with verifying your contracts. Tap on the Contracts, Tax, and Banking Information item within iTunes Connect, and it'll take you to a section where you can manage the contracts that you have in place. Make sure that you've got a paid applications contract in place in the Your Contracts in Effect section within this particular tab. This is especially critical for folks who have delivered free applications on the App Store and have never sold an application at a given price. So make sure that you've got this step taken out of the way in the beginning.
Now if you've already sold an application within the App Store, then you've got a contract in place. However, there might be an amendment waiting for your agreement there. So if you're having an issue adding your products, associating them with an application, then it might be that you have another contract waiting for you to agree to. So simply tap the Submit button and move on. You're good to go. Next step is we're going to add your application. So click on the "Manage your application" section in iTunes Connect.
Now, you don't have to load your entire app altogether. We don't request your binary is submitted as part of the testing process associated with in-app purchases. We just require that you add a certain amount of metadata so that we can track the application and associate the products with it.
Something to keep in mind is that changes for apps that are already on the store go live immediately. So don't go into the description of your application and start advertising about the in-app purchases that you've got coming, since those will be presented to your users right away, and you might not have uploaded the most recent version of your application that even contains the capabilities for in-app purchase. Next step is adding your products. So you're going to click on the Manage your in-app purchases section of iTunes Connect. And you should see, if everything went well, a Manage In-App Purchases button next to your application of choice. So go ahead and tap that.
So to collect your product information, we'll display a view that collects things like the reference name, a product ID type, price tier, as well as cleared for sale. One thing to keep in mind as you're filling in this information is that product IDs are unique across applications. Many folks use the reverse domain name naming function or perhaps a bundle identifier as a way of creating a unique product name, followed by the product itself.
And something to keep in mind is that the type that you choose here is very important because the type that you choose for this particular in-app purchase really drives a lot of the behavior of whether it's restored to a user's device, how the user buys it perhaps multiple times over time, whether it's a subscription. So let's talk a little about these in detail.
The first type of product that you might associate with your in-app purchase is a non-consumable. These are products that are purchased once, but available forever within your application. A good example is perhaps a game level. A user would buy that once and they would always have access to that particular level in a game.
Another product type is a consumable. Bullets is a good example for a game as well, where it's purchased each time that they are consumed. The user will use them up and then they'll need to buy more in order to get more bullets or whatever product it is that you're selling that's consumable.
The third and final type is a subscription. A subscription is purchased each time the subscription expires. Keep in mind that you're in charge of the dates associated with when a particular item is no longer valid for a given subscription that a user has purchased. So that's the product types. Another good thing to keep in mind is that the "Cleared for Sale" checkbox must be checked before you can test your in-app purchases within your application.
And finally, the Approve button you'll see next to your application listing all your products is there when it's time to go and submit your app and its products for approval. Make sure that you press that Approve button after you've tested all your products within your in-app purchase application.
And finally, let's create a test user that you'll use to test your implementation. Back into iTunes Connect. Click on the Manage User item within the menu. And it'll take you to an area where you can add an iTunes Connect user as well as an in-app purchase test user. Click on that.
And you'll see that we collect the same sort of information that you would enter for your app ID for production. However, we don't want you to enter your production Apple ID here. Make sure that this is a unique Apple ID that you're creating for testing in-app purchase. You don't want to use the same one that you would use for buying music, for example, or movies in iTunes. Don't enter that here. Make up something completely different.
You're going to want to make up one for each country that you wish to test, since the ID that you enter is going to be associated with an individual country that your product might be for sale within for a specific store. So use one for each one of the countries that you want to sell your products in.
And we're done. That's it in iTunes Connect. Let's take a look at what we need to do within your application now. Within your application, you're going to determine the sellable products, you're going to build the product display, request payment for the item that the user selected to purchase, you're going to perhaps verify the purchase receipt, remember the purchase, and then finally restore previous purchases that the user might have purchased with previous devices of your application.
So, as I said earlier in the beginning, the workflow. Whenever your application launches the first time, you're going to request a set of product IDs, either from your server or from within the file system, perhaps bundle of your application. You're going to pull those sellable products into your application. Remember, those are the potential products. They aren't necessarily all of the products that you can actually sell within your application.
You're going to use Store Kit to determine the sellable subset of those products. And by sellable, I mean it's those products that have been entered into iTunes Connect, as well as those that have cleared through the app review process. Now, clearing app review is not required for testing. However, both of these steps have to be complete for you to be able to sell a product using the Store Kit APIs within your application.
So how do you do it? Well, first you need to take that set of potential products that you've built up and call init with product identifiers passing in that set. Finally, you call start on your product's request. By calling start, You'll pack up those products and send them to the App Store using the Store Kit APIs. And then as a result, we'll look at the products you've provided and return back the sellable products back to your application. It's that subset of products that you can sell within your application.
Those products come back, all of them, in the response object of the didReceiveResponse method. They're all returned, however they're broken into two separate arrays. One, a set of invalid product identifiers, and then a set of valid products in response.products. You're going to want to use response.products within your application to build your display. The invalid product identifiers might be products that haven't made it through app review, or perhaps you didn't even enter them into iTunes Connect.
You're also going to want to make sure that you use the localized product attributes for your display. When you're building your list of products for sale, you want to use the localized title, the localized description, and the price that's provided as well. We're doing that for you so that the information that is displayed is in the language of the particular store that your customer is using when they're buying your items. So make sure that you use that. That same language, that same localized value, is used as part of Store Kit dialogues that are presented to a user as part of their checkout process for buying items.
Next step, after a user has selected the item, you're going to request payment. And again, of course, it's back to the Store Kit APIs to talk to the Store Kit. You create a payment request, you send it to the Store Kit. And then we're going to send you back the results. The way you build your request is by selecting the product ID associated with the item the user has chosen to purchase and adding it to the payment queue via the Add Payment method.
Once you do this, Store Kit is going to present a series of payment request dialogs to your customers. The first one is going to request the iTunes password of the customer that's using the device. Keep in mind that if you're in testing mode, this user ID that you see in the dialog should be your in-app test user. Make sure that this isn't your production user.
If so, if it's got your production name in here, then all of the workflow is going to break as part of your processing of these transactions. You want to make sure that this has your in-app test user, the same one that you created within iTunes Connect at the beginning of this process.
If you see the wrong user ID in here, if it's perhaps your production user ID, the way to clear it is in the Settings section of the iPhone OS. So go to the Settings section and you'll see there's a Store item down at the bottom of the settings.
Tap on that and you'll see the account settings for in-app purchase as well as any item that's purchased on the device. You're going to want to press the Sign Out button and then make sure that there isn't any account information that's entered here at the top. Make sure it doesn't have your test account information. Make sure it doesn't have your production account information. And another key got you is make sure that you don't enter any value here. Don't enter your in-app test user here. Just make sure that it's blank. And then you're good to go forward.
The next dialog that's going to be presented is a Confirm dialog. As I mentioned, the dialogs we present when we're talking about product information displays that localized product information. So remember, you want to build your display based on that localized product values that we return associated with your products. Because this is where your customers will see them. You want to make sure that the product name displayed here is the same thing that they thought they were buying when they selected it within your application.
The next dialog is the previously purchased dialog. Now this might not show up. It's only displayed if a user has bought this item before and it's a consumable or it's a subscription type product. From a transaction perspective within your transaction queue, this is going to look just like an original purchase. So if you're doing auditing of your transactions, this won't appear as a different sort of transaction. It's not a restored transaction. It's just another successful buy. So make sure you keep that in mind if you're keeping track of transactions.
The next dialogue, if the user's made it through this process and everything has been successful, is the thank you dialogue. And the user successfully bought your item. The thing to keep in mind is testing environments are different from production. So all of these dialogues are displayed to you when you're testing, as well as when the user is walking through the process of buying your in-app purchase.
However, when you're testing, you want to make sure that you're in the sandbox. And the way to do it is by looking at each one of the dialogues and making sure that you see the environment sandbox within brackets keywords. It's there within each one of these. If you don't see this, then there's going to be a problem with part of the checkout process that you're testing. So make sure it's there. So you've successfully requested payment. As a result of requesting payment, we're going to pass you back a transaction receipt. And you can use that transaction receipt to verify the purchase.
And remember, purchase verification is optional. Not everybody is doing this. It's not required, but it is a nice to have. The purchase transaction contains a signed receipt. And it looks like this. This particular transaction, my payment transaction, has a field on it, Transaction Receipt. What you need to do before you do anything with it is Base64 encode it.
Base64 encode the receipt value. And if you need a sample on how to do that, you can get it from Cocoa Dev. They've got some great examples on how to Base64 encode. It's not one simple Cocoa method. There's a fair number of things that you need to do in order to do it. So go to this website and grab the source and do it.
Once you've encoded your transaction receipt, it's time to verify it and do that by sending it to your server. You don't want to encode and verify the receipt right there on the device. If you're worried about the transaction, move it off to your server and have the validation status passed back to your application before you finally go and unlock that purchase.
Once you feel comfortable with the purchase, the next step is you need to remember it. Remember, you want to make sure that the item that the user has purchased is available between different launches of the application. So you need to remember it. And there's a couple ways to do that.
First, and probably the most popular way, is to use the NSUserDefaults class. And it looks like this. It's a very easy way to go and write an array of information, a dictionary of information, out to the file system in a standard location on iPhone. It writes to the application support directory. And if you're looking for a sample on how to use the NSUserDefaults, then take a look at the drill-down save sample.
It's got a great example of providing user navigation, drilling down within a multi-list environment, and then saving the depth of the user's drill-down in the NSUserDefaults. So it's there the next time the user launches the application. It's a great sample, and it's got a great implementation of NSUserDefaults.
Another mechanism that's popular is using the Keychain APIs to go and remember this. Remember, you can write all sorts of things out to the Keychain. Most people use it for secure ID, secure URLs, passwords, those kinds of things, but you can also remember purchases, remember the product ID associated with the purchased item in the Keychain as well.
As part of using the Keychain, you'll notice that you get a unique slice of the Keychain for your particular application. Something that's very nice, however, is that that slice can be shared across all the applications that have the same bundle seed. So if perhaps you want to remember the purchases from one application into the Keychain, you can always use another application to look at that same slice and see, oh, within this other application that you've developed, these particular products are purchased as well.
If you're looking for a sample on how to use the Keychain, how to read and write, the generic Keychain sample is an excellent example to take a look at. It's got a Keychain wrapper class that makes it very straightforward to go and read and write from the Keychain application.
Keep in mind that both of these mechanisms are backed up. And as user defaults, the entire directory is backed up as part of a user's backup process, as is the keychain. So these items that you've written to either of these locations are going to be remembered between restores of a user's device.
Talking about restoring, let's talk a little bit about restoring purchases. Subscription and non-consumable items are required to be restored across all the user's devices. So if they bought it on one device, you're required to restore it across all the other devices for the same iTunes ID. You need to provide custom UI in order to give the user the capability to do this.
Don't launch the restore process on every launch of the application. Put a button perhaps in your settings or perhaps in a utility section in your application that clearly says, "Restore previous purchases." Users will get used to this. They're used to downloading applications to multiple devices, and they'll look for the previously purchased items in that application, not see them, and they'll go hunting for this type of mechanism. Non-consumables will use the Store Kit API in order to provide the restoration services. And you do it through calling restoreCompletedTransactions as part of the payment queue.
Now remember, as part of calling this particular method, customer sign-in is going to be required. So again, make sure that you're not requesting transactions to be restored with every launch of your application. Make sure it's associated with some sort of user action to go and initiate that. and then process it like a successful payment.
The transaction will have a property that indicates that it's restored, but the goal is that as a result of you receiving this restored transaction, you simply unlock the purchase again, as if the user had bought it for the first time. The customer will not be charged. Remember, restoring is a process that they expect on devices when it's non-consumable as well as subscription-based products.
Talking about subscriptions, as I mentioned in the beginning, you're required to manage all the information associated with subscriptions. So whether the subscription is valid for a given period of time, all those things that you need to track, it's really in your best interest to perhaps collect a user ID so that you can restore the purchases for the user. They will not come back as a result of calling restored purchases. Consumables as well as subscription information is not returned as part of restoration.
So that's it on the client implementation side. Let's take a look at what you can do on your server in order to go the next step. Now as I mentioned, having a server is optional. However, there are a lot of use cases where a server would be incredibly useful. First and foremost, you could serve product IDs to your application.
Perhaps you have a content service and you're dynamically creating multiple product IDs over time. Rather than delivering a new version of your binary every time to encompass those product IDs, you can just serve them up over a server. If you're serving content, most likely you've got a server already in order to provide that content to your user.
It's sitting out there in the cloud. When they make the purchase, it's unlocked and they're able to stream it down to their application. Some folks are using a server to manage user accounts as well. Again, specifically for subscriptions, that's something you definitely want to do. And then finally, as I mentioned, you're going to use a server in order to verify the in-app purchases that a user has made.
So of all of these things that you could possibly do with a server, verifying in-app purchases is the one where Apple's part of the process. So let's take a look at that. Verifying in-app purchase begins with you sending the encoded receipt up to your server. Remember, it's a base64 encoded receipt. And then you're going to create a JSON object that has that receipt as the value of a receipt data object.
Next up is you're going to post that to the iTunes Verification Service at buyitunes.apple.com/verifyreceipt. That'll send that up to our server. We'll take a look at the package that you've sent us, and then we're going to respond with a JSON response that you can inspect for validation. Looking at the JSON object, you'll see it's got a status value, as well as some other information in there.
Key for validating the receipt is the status. You want to make sure that that value is zero for a verified receipt. Any other value that you see here means that this receipt has not been verified. So after you've validated the JSON response, validated that you received a verified receipt, You're going to take a look at the rest of the receipt for some other interesting information that's part of it.
As part of the receipt we provide product ID, Apple bundle ID, purchase date, all sorts of information that could be incredibly useful if you've got a system on your back end that manages transaction information as well as user information to manage purchases and those types of things. So take a look at these fields, they're incredibly useful. And then the final step is you're going to pass the verification status off to your application. Basically tell your application whether it can unlock the particular feature that a user has just bought.
So, that's it with the server side. You've verified your purchases. And that's it from a preparation and implementation perspective. Program Portal, iTunes Connect, your app, your app server, you got it all together. So let's wrap it up with some debugging techniques. Well, those debugging techniques are all those things that I called out as part of the presentation with the little stars next to it. Each one of these issues have caused some users grief as part of their implementation. So be mindful. Make sure that you've got the appropriate contract in place. Make sure that you've got cleared for sale checked in iTunes Connect.
That the appropriate agreements are there. That you don't change metadata before you've actually submitted your application. You don't want to out your products, the features that you're going to have in your application, before you actually submit it. And then finally, make sure that you're using the appropriate in-app test user information as part of your testing process.
So here's what we've covered: a bit of overview, architecture, some development and preparation steps, as well as some implementation details and debugging techniques. I'm the iPhone and Server Technologies Evangelist. My email address is [email protected]. If you have any further questions, feel free to send me an email and be sure to check out the documentation available on the program portal at developer.apple.com/iphone. Thank you.