Internet & Web • iOS, OS X • 58:45
In-App Purchase lets you embed a store directly within your app that can be used to sell a variety of items such as premium content, virtual goods or subscriptions. Discover the Store Kit APIs needed to add In App Purchase to your iOS or Mac OS X application. Understand how to perform receipt verification, and learn to manage and test items for sale through iTunes Connect. See how new features of iTunes Connect make it easier to manage large sets of items for sale, test subscriptions that automatically renew, and more.
Speakers: Jean-Pierre Ciudad, Ricardo Cortes, Max Muller, David Neumann
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
All right, let's get started. My name is Max Muller. I run the Digital Supply Chain Engineering Group, responsible for iBooks, iTunes, and the App Stores. In this session, we're going to be looking at in-app purchasing. In-app purchasing was added in iOS 3.0, and in the past two years has grown to represent a significant portion of the revenue generated by our developers.
If you look at the App Store today, in the top grossing application chart, of the top 25 applications in the App Store, 14 of them are free and generating all of the revenue through the use of an app. Now before we get started, I'd like to extend a warm welcome to our Mac OS X developers. On Monday, we announced that with Lion, we are bringing In-App Purchasing to the Mac App Store.
So let's look at what we're going to cover today. First, we'll do a brief introduction on what is an In App Purchase. Next, we'll look at the types of In App Purchases we currently support. We'll look at how you set up your In App Purchases in iTunes Connect.
We'll then look at how you test your In App Purchases in our sandbox test environment. And finally, how you submit your In App Purchases for review. Then we'll jump into the client side and look at Store Kit on both iOS and iOS X. This will be looking at how you retrieve In App Purchase items from the server, how you initiate transactions and complete transactions, and finally, how you verify receipts.
We'll then do a deep dive into our newest In-App type, the auto-renewing subscription. We'll follow it up with In-App reporting, and finally wrap it up with some best practices. So let's get right into it. What is an In-App Purchasse? In a nutshell, this allows enhanced functionality and content to be sold directly within your application.
This is implemented using the Store Kit API, which was introduced in iOS 3.0 and is now new for Lion. Store Kit handles all of the prompting the user to authenticate, as well as securely authorizing the transaction. Once the transaction is complete, you will be given back a receipt.
You can take that receipt and pass it to your server, which can then pass it to our server for verification. This is a great tool for helping fight piracy. One other thing to point out about In-App Purchasing is that In-App is strictly a commerce level feature. If after a transaction is complete, it is your responsibility to deliver any assets from your server down to a device or to a computer.
Now, a few example usages would be adding a pay feature to a free application, adding additional levels to a game, or purchasing virtual goods like vegetables, berries, or brains. And finally, what launched a few months back with the Daily, we've now implemented a full auto-renewing subscription. Allows you to add full subscription support to your applications.
So now let's look at the types of In App Purchases we currently support. There are four of them: Non-Consumable, Consumable, Non-Renewing Subscription, and Auto-Renewing Subscription. So diving into the non-consumable, this is available on iOS and is now new for Lion. This is designed to be purchased once and only once by a customer.
If you think of how the App Store works for applications, if you were to buy an app on one device and then attempt to buy that same application on a second device, we would allow you to download that application on the second device again for free. Non-consumable In-App Purchases work in the exact same way. We will only ever charge the customer once for the purchase of a non-consumable In-App.
Now, one other thing to point out is that it is your responsibility to ensure that non-consumable In-Apps are made available across all devices for a given user. You do this using the Restore Completed Transactions API, which we'll be going into more detail later on. Two examples here would be a new level in a game or an additional feature in an application.
Next up are consumables. These are available on iOS and now new for Lion. These are designed to be purchased multiple times by the consumer. Every time a transaction is completed for the same item, the user will be charged again. Again, a few examples would be pet food or other items that are consumed as part of gameplay or virtual currency within the application as a means of advancement.
Next up is non-renewing subscriptions. This is only available on iOS. We introduced the non-renewing subscription in iOS 3. It is required that you, the developer, do all the work to implement subscription management on your own. We've now deprecated the non-renewing subscriptions in favor of the auto-renewing subscriptions. Now the auto-renewing subscriptions we're not going to cover right here because we have an entire separate section that we will go over those in detail. So now let's look at how you'd set up a non-consumable or consumable in iTunes Connect. First up is the metadata about your In App Purchase item.
This would be the type, either consumable or non-consumable. A reference name, this is only your name for the In App Purchase item. This actually will not be displayed to the customer anywhere. Next is a product ID. This is how you will reference the In App Purchase item. Through Store Kit, you'll be passing the product ID to look it up from the server side. The product ID will also appear in your financial reports at the end of the month.
Next up would be your display name and display description. Here you can localize it into as many languages as you want. One thing to note is that Store Kit, when it actually is popping up the purchase dialog, that's actually a server-driven dialog. So we're using the display name that you've entered into iTunes Connect in the dialog that's popped up for the user.
Next would be pricing, where you'd be setting cleared for sale, as well as a price tier. All price tiers are available, with the exception of the free tier. And finally, for review purposes only, we ask you to provide a screenshot. Now to get to add In App Purchas items to an application, you log in iTunes Connect, select the application, and click Manage In App Purchases.
You'll then click the Add New In-App Purchase Item and select the type. In this case, I'm going to choose a consumable. First up, we'll be setting up the reference name, as well as the product ID. So I've set up rockets. And we recommend using a reverse domain name syntax for your product ID. Once that's set up, you'll now be adding the localizations for the display name and the display description. Here we recommend localizing all of your In App Purchas items in the same number of languages for which you've localized your application.
Next up would be pricing. And finally, again, for review purposes only, a screenshot. So once you've set up all of your In-App Purchas items, the next step is to test them. For this, we've actually built an entirely separate environment that we call the Sandbox. A few things to point out about the Sandbox: development-signed builds of iOS or OS X are automatically pointed at the Sandbox environment. Payments are not processed in the Sandbox environment, but transactions are returned. And you must leverage a special Sandbox test user account, not your regular store production account for Sandbox testing.
Now the sandbox test accounts, the same sandbox test account can work on both iOS and Lion In-App Purchaset testing. Also, if you are using application receipt verification for app purchases for OS X, the same sandbox account can work for that as well. Now one thing that we always like to point out about when using the sandbox is that you must first log out on your device of your production iTunes store account, go into Settings, select Store and Log Out. Leave yourself logged out, quit Settings, and then launch your application. If you are successfully pointing out the sandbox environment on all the store kit dialogues that come through, you will see environment:sandbox.
To create a sandbox user, you're going to log into iTunes Connect, click Manage Users, and click Add New User. At this point, you'll select the test user. Here we'll prompt you for all the basic information about setting up an account, the most important one being the iTunes store or country. For each country that you wish to test your In App Purchases in, in terms of localized display as well as currency handling, you want to set up a separate iTunes sandbox test account.
Now once you have tested your In-App items, and I mean thoroughly tested your In-App items, the final step is for submission. Now the first time you submit any In-App Purchases items, they must be submitted with an application binary. This means that we're going to tie your In-App Purchases items and your application together. We're going to move through the review process as one.
If there are issues with either In-App Purchases items or your application binary, they'll all be rejected back to you to essentially correct. Now once you have an application live on the App Store, you can then submit new future In-App Purchases items in an ad hoc manner. In which case, you're just setting up In-App Purchases items, submitting them, and they travel through the review process independent.
To submit one In App Purchasse item, log in iTunes Connect, select that In App Purchasse item, and click on the upper right hand corner to submit it for review. And if your application has lots of In App Purchasse items, we also provide a nice listing interface. You can see all your In App Purchasse items, select the ones you want, and with one click, submit all of those for review. And now what I'd like to do is bring up Jean-Pierre to walk us through Store Kit on iOS and OS X. Jean-Pierre? Thank you, Max.
Hi, my name is Jean-Pierre Ciudaad, and I am the engineering manager for the Mac App Store. So I'm here today to talk to you about the Store Kit API, both on iOS and on Mac OS X. So first, I will start by giving you an overview of the API, and then I will spend more time telling you about how you can get product information for your in-app purchases, how you can actually purchase in-app purchases from the app store, and how you can restore completed transactions.
Finally, I will spend more time telling you about receipts and what the differences are between iOS and Mac OS. Now, if you are an iOS developer who is already familiar with in-app purchases, you will find this presentation very familiar, because the API is essentially identical between iOS and Mac OS X.
So let's start right away with an overview of the Store Kit API. So step by step, the first thing you need to do is to get your In App Purchases identifiers, the product identifiers. You get these either from your application bundle, or you get them from your server.
Once you have those identifiers, you actually use the Store Kit API to get product information. The product information includes things like the title, the localized title, localized description, and the price. This is what you will use to actually show UI in your application, and let the user decide which items he wants to buy.
Once the user clicks on the Buy button on one of your In-App Purchases, you want to actually make the purchase. So you make the purchase using the Store Kit API, and you do it from the App Store. Once the purchase is successful, or once the purchase has been processed, you will need to actually process the transaction on your side. And what that means is that either handle the error if there is one, or process the receipt, and we'll talk about this a little bit later.
If the transaction is successful, the user's credit card has been charged or his account has been debited, you need to make the feature available to the user or you need to download additional assets from your server. And once you're done with that, you need to tell us, you need to tell the App Store that the transaction was finished. This is very important. If you forget to do that, we will keep bringing back the unfinished transaction over and over again, every time the user launches the application.
So out of those seven steps, four steps actually we will be providing you with APIs in Store Kit for four of these steps. Getting the product information, making the purchase, processing the transaction, and finishing the transaction. So let's look at those steps. How do you get product information? So like I said earlier, the first thing you need to do is to get the list of product identifiers out of your application bundle or from your server. Now those product identifiers should match the data you've been entering in iTunes Connect previously.
So once you have this array of product identifiers, you use the SK product request to create the request. So here you have an example of how you can create the request. You can see that you pass in an array of identifiers. You set yourself as a delegate, and then you start the request. Now, you need to implement the SK product request delegate protocol.
And obviously, you need to implement the product request In that method, you will get a response back, and the response will contain an array of products, and that array of products, for each product, you will get a localized name, localized description, and the price. Now, you will also be getting an array of invalid product identifiers.
What these are, they are identifiers that you actually have passed to the App Store, but we didn't recognize them. So this could happen if, for example, you have hard-coded identifiers in your app, but you have not yet entered them into iTunes Connect. Now, in production, this could also be in-app purchases that were submitted but not approved.
You also need to handle the error case, obviously, and present appropriate UI to the user. So once you have the list of products and you have the names and the price and all that, you need to actually show UI, and you need to let the user decide which In App Purchas he wants to buy.
So once a user clicks the Buy button, you know what product the user wants to buy, and you need to prepare for the purchase. So the first thing you do, you need to add yourself as an observer of the SK Payment Queue. The SK Payment Queue is an asynchronous API. You need to implement the SK Payment Transaction Observer protocol. So here you can see the Payment Queue, which will be the callback that will be invoked once the payment has been processed.
So how do you make the purchase? With the product that the user selected, you create an SK payment. And then you just add this SK payment to the payment queue. And that's all you need to do. What will happen is that your observer, once the payment has been processed, your observer will get called, and you will get an array of transactions when your observer gets called.
And if you bought one product, you will get one transaction back. You will see a case later with restoring where you can get an array of them when you're restoring. But for now, you get one transaction back, and you're going to check the state of the transaction. If the state is purchased, or the SK payment transaction state purchased, that means that the transaction was successful, the user has been charged, so you need to make the asset available. At that moment, receipt data is also available, and we'll talk about that a little bit later. Another state that you can have is the transaction failed. And in that case, you need to show UI to the user.
Now, if the state is purchased, again, you need to make the content available to the user, either by downloading additional data from your server or by unlocking features in your application. Then you need to complete the transaction by calling Finish Transaction on the payment queue. Again, this is something very important. Do not forget to do that. And you need to do it whether the transaction was successful or failed.
Restoring. So Max earlier talked about restoring completed transactions. So if the user decides to move the application on a different device, or to re-download the application from the Mac App Store, for example, on a different Mac, the user is entitled to get all these non-consumable In App Purchases back on the different device. So the way you do this, you can get all of them at once by calling restoreCompletedTransactions on the payment queue.
Basically, the same observer that you set earlier will be called with a list of transactions. That's when you get an array of transactions. And then for each of the transactions, you need to verify the state, make the content available to the user, and then for each of them, you need to call finish transaction in the payment queue.
Optionally, you can also implement, I'm not going to read it, but you can implement this method at the end, which basically would allow you, for example, to stop a progress bar if you decided to show progress in your app. Restoring, by the way, is not currently available in the DP4 version of Lion, so for Mac OS developers, if you try the restoring APIs, they are not yet fully implemented, but they will be available for the GM version.
Receipts. So receipts are signed files signed by Apple, and those files allow you to verify the purchase of In App Purchases. They are very different between iOS and Mac OS. The format is different. So on iOS, receipts are opaque. You cannot read them. And when on Mac OS, they are using an industry standard for signed archive called PKCS7.
And you can find documentation on the web. How do you verify the receipt? On iOS, you send the receipt to your server, and your server is supposed to turn around and send it to Apple. What Apple will do is that it will actually expose the information in the receipt for you. And it will send it back to your server. And then your server can decide whether or not to make assets available.
On Mac OS, because this is a standard format, you are able to verify the receipt locally. So you can do it on launch of your application, or you can do it whenever you want. In addition to that, we are planning to make receipt verification available by your server with Apple. This is not yet in place, but it will be in place by the time we go GM online.
The scope of the receipt. The iOS receipt is specific to one In App Purchas. What that means is that if the user made 100 In App Purchases, you will have 100 receipts in your application container. Very different on Mac OS. The receipt that contains the In App Purchases on Mac OS is exactly the same receipt as the one that is delivered today when the user purchases the app.
So that same receipt, in addition to containing information about the app purchase, will contain information about all the In App Purchases. Actually, sorry, let me rephrase that. About all the non-consumable In App Purchases. How do you get the receipt? On iOS, the receipt data is available for you as part of an NSData blob that comes back with the transaction when the transaction is successful. basically purchased or restored.
On Mac OS, the receipt is actually delivered into your application bundle by the App Store. This happens automatically, you have nothing to do. On iOS, when I mentioned the blob of data, you are responsible for taking that data and saving it in the application container. So you can see that receipts are very different between iOS and Mac OS X. And this is basically the main difference in the Store Kit API between iOS and Mac OS X.
So let me, just to make sure we all agree on this, let me go back a little bit on the differences. iOS receipts, this is a blob, you get it via a blob of NIS data that is a property of the transaction object, and you will get the data when the transaction was either purchased or restored. You are responsible for saving the receipt in the application container. You can use that receipt to verify transactions by sending it to your server and have your server send it to Apple.
Mac OS Receipt, however, are placed in the application bundle by the App Store. This is done for you automatically every time a transaction is successful. There is one receipt per application. The same receipt today that contains information about the application purchase also includes information about all your in-app purchases, all the non-consumable in-app purchases.
To validate, you need to validate the in-app purchase -- well, you need to validate in-app purchases in launch if you want to enable some features in your application. So you can do that by looking at the receipt. You can do that locally. It's a known archive format, PKCS7 using an ASN1 format. It's signed by Apple.
And the receipts on Mac OS are tied to the machine. And there is documentation available today that will tell you how to verify that the receipt is valid on a specific machine. Like I said, by the time we ship Lion, you will be able to send the receipt to Apple to extract data out of the receipt.
So a few tips. Do not forget to call finish transaction on the payment queue every time you have a successful transaction or a failed transaction. Believe it or not, today on iOS, this is the cause of most problems that developers encounter within app purchases. People always forget to call finish transactions. So do not forget to do that.
It is best to register as an EscapeMNQ observer on launch of your application. And the reason for that is because some users may Purchase something. Purchase transactions take a while. It could take up to 10 minutes. And if this is the case, the user may quit the application.
That means you will never process the transaction back. So you cannot make the asset available. The next time the user will launch the app, by registering as an observer of the escapement queue, we will actually send you back the transaction, so you will be able to make the asset available to the user.
Only restore in apps when the user needs to access the in-app purchases. So, for example, on the Mac, if a user moves an application to a different machine -- or, actually, if the user redownloads the application from the Mac App Store, the receipt that you will get will be a receipt that will only contain the transaction for the application. It will not contain the in-app purchases.
So you are responsible for providing some UI for the user to get back the in-app purchases. Now, you could do it on launch as well. But this is why we don't want you to do it on launch. We don't want you to do it on launch because every time you try to restore in-app purchases, the first thing we will do is we will ask the user to authenticate.
So it would be really strange if every time the user double clicks the app, it's presented with an off panel. You wouldn't know why and why do I have to do this. So, you actually need to have either a menu item or a button somewhere to restore the in-app purchases.
And now for Mac OS developers, you need to check the receipt validity on launch. So there are several reasons for that. Like I said earlier, receipts are machine specific. You want to make sure that the receipt that you currently have in your application is not some receipt that somebody posted on the internet somewhere. So by verifying the validity of the receipt, you will make sure that this receipt is for the user that actually purchased the In App Purchases.
If the receipt is invalid, you need to exit with 173. And when you do that, we will do one of those two things. If the application is a production application, which means it is currently used by a regular user, we will allow the user to re-authenticate to the App Store, and we will automatically deliver a new receipt, a valid receipt this time.
If the application is signed by you, by the developer, we will directly go to the sandbox and we will deliver a test receipt that you can then use to process In App Purchases. Without a test receipt, you will not be able to process In App Purchases. Very easy to get a test receipt.
Check if there is a receipt in your app bundle. If there isn't, exit 173. You will be presented with an off panel. You will enter your test user account and we'll give you a receipt. Again, receipts are required to use the sandbox, so if you think that your In App Purchases are not working, it's probably because you didn't get a receipt, you didn't exit 173. And the store will automatically give you a new receipt after you authenticate.
More information. There is a document that we issued last January and we've been updated. This is for Mac OS X developers that explains to you how to verify App Store receipts. There is another document that explains to you how to submit your application to the Mac App Store, again for Mac OS X developers.
For iOS developers, there is a document called In-App Purchasse Programming Guide. This documents the Store Kit API, and because the Store Kit API is mostly identical between iOS and Mac OS X, this can be used on both platforms. Finally, the Store Kit framework is not located by default on DP4, so you need to download it from the ADC website.
And now, just to show you how things come together, I will show you a small demo of the next top seller in the App Store, the Fruit Stand. So what the Fruit Stand is, it's a small app. The first thing we did was add ourselves as an observer of the Escape MNQ, and then we loaded a list of In-App Purchases identifiers from our app bundle.
And what I'm going to do, I'm going to click on this beautiful UI, this beautiful button, Fetch Product Information. And what that's going to do, it's going to go to the App Store and look at what we have registered in iTunes Connect. So for each of these product identifiers, it's going to get the name, the price. Obviously, we didn't display the description.
So now that we have the name of our In App Purchases and the prices, we can actually populate our UI, which we've just done by actually adding those items in this pop-up menu. So I'm going to purchase a banana. So I select the product, click purchase. At that point, we create the payment.
And we add it to the payment queue. The App Store is going to present that dialogue. This is not your dialogue. This is our dialogue. So the user can confirm that he wants to buy that item. And you can see that you have here, you know that you're working out of the sandbox because we're actually adding it to the dialog. So I want to buy. We present an authentication dialog. So here I am entering my test user account, Apple ID and password.
If all goes well, you will see that the transaction has been moved to purchased. We process the transaction. We called finish transaction and the app store is actually displaying the thank you dialog. And we made the asset available by basically presenting the picture we just bought. Let me do it just a second time. Let's try to purchase a lime this time. Okay, confirm, authenticate. And if all goes well, I should get a picture of the lime.
So I think it's going to be a smash. So let's look at how How we've done this, very briefly. So, now obviously this is a Mac OS X application, and... Here, the first thing you want to do is, if the receipt is not present in your application bundle, you want to exit 173. So that the first thing you will be asked to do is to authenticate with your test user account to obtain a receipt from the Mac App Store.
Second thing, when your application finishes launching, there are a couple things you might want to do here. If you want to make the non-consumable available in your application, like enabling features, this is the place where you actually want to look into your receipt to verify which In App Purchases were actually purchased. Then you can make those In App Purchases available by unlocking features or downloading content.
This is also where we have chosen to actually get the list of product identifiers out of our bundle. You can do that somewhere else if you want. Anyway, so we got the purchase fruits right there. How do we get the product information? Well, we have a list of product identifiers, and we're going to create an escape product request.
We're going to set ourselves as the delegate, and then we're going to start the request. Prior to that, of course, you know, we have implemented the failure delegate method and the successful delegate method, where we actually get a response. That response basically contains an array of products. And we use that array of products to basically populate a pop-up menu.
Now the user selects an item In the pop-up menu, and what we need to do now is to actually purchase the product. Now, right at the beginning, I don't know if I actually pointed it out, we actually registered ourselves here as an observer of the SK Payment Queue.
So now we're going to create a payment using the product that was previously selected by the user in the pop-up menu. So we create an SK Payment, and then we add this payment to the SK Payment queue. Once the user confirms and clicks buy, and once the purchase has been processed, we will get our callback and we will get a transaction. Our callback will be invoked, we'll get a transaction. Now for each transaction, we're going to look at the transaction state.
And if the state was purchased, we make the content available to the user. And very important, we will actually call finish transaction on the transaction. If you were restoring, for each transaction you will get this state restored. For each of the transactions, you need to call finish transaction. And you can see here that we also called finish transaction when the transaction was failed. So this is it. This is how we process our In-App Purchases. So to talk about auto-renewable subscriptions, Ricardo Cortes.
Good morning. Thank you, JP. Auto-renewables. There's a lot of steps in doing auto-renewables. A lot of it's different from the non-consumable and consumable case, so we have a lot of things to cover. We're going to give you a quick overview, then we'll get into the metadata differences between non-consumables and consumables, how to use that metadata with auto-renewables, receipts, policies, the cancellation flow, testing in Sandbox, as well as how your app looks in app review with auto-renewables.
Auto-renewables are only available on iOS. And they enable true subscription support within your app. Unlike the non-renewing subscription, which is being deprecated, this is the type you want to use if you want to offer your customers subscriptions. And the subscription is automatically renewed at the end of the subscription period. The customer is given the option to opt out in iTunes. There's a Manage Subscriptions page in both iOS and on the desktop version of iTunes.
And new content is automatically delivered to all devices with the same customer Apple ID. Duration options: one week, one month, two months, three months, six months, and a year. And yes, it is the most complex In App Purchas type to implement, so hopefully this presentation and the many steps we're going through will elucidate it for you. A few examples. Golf Digest. LUS, and launch in early February the first auto-renewable, The Daily.
The developer in the auto-renew case is responsible for checking receipts to validate their subscriptions. And you must pass over a generated shared secret in iTunes Connect with your receipt to validate that subscription. Now, if you haven't purchased an auto-renewable, when you do so on iOS, you're prompted to share your personal information. If the customer chooses yes, you as the developer/publisher have the option of providing a bonus duration. You choose this bonus duration in iTunes Connect, and you are responsible for displaying this bonus duration UI in your application. A privacy URL is required. It's shown in the customer's invoice.
Now let's look at the iTunes Connect setup pieces and how they differ from non-consumables and consumables. You go back to the In App Purchase Type page, you choose Auto Renewable. And when you land on the pricing page, there's a few extra fields. There's the duration, and then there's the offer marketing opt-in incentive. Upon choosing yes, you're then given the option of choosing a bonus duration. And below the usual, it's clear for sale and price tier fields for all In App Purchases.
Now you get to the Reference Name and Language page. And in the Auto Renewable case, the reference name can be thought of as your family. In this case, I have Touch Fighter Game Strategy. And I have two durations, seven days and one month. For most developers, a single family/reference name in the Auto Renewable case is sufficient. Each of the durations is presented as options in your UI. And on the Manage Description page in iOS, the customer is given the option to upsell, say, from the seven-day to the one-month subscription if the durations are all part of the same family.
Here you can also localize your auto-renewable in the various languages. Privacy Policy URL, which is required in the auto-renewable case, as well as the ability to generate your shared secret in iTunes Connect. And now to talk a little bit about how to use this metadata in the auto renewables is David Neuman, Engineering Manager, iTunes Store, Commerce. Dave.
Okay, so I want to start with something that has affected a lot of folks, because I've tried to help a lot of developers do this stuff, and I want to start off with, I guess, landmine number one, which is the difference in auto renewables between the subscription title and the offer title. Okay, when you get back an SK product in your Objective-C code, it's got a field called Localize Title.
And unlike all the other type of in-app subscriptions, this isn't the name of the specific offer the person's buying. It's the name of this collection of in-apps. Okay, what the user's going to buy is something like I have there for the, for example, a weekly plan, a monthly plan, or a yearly plan. But this Localize Title needs to be something for the subscription as a whole. I call it the subscription name, and that's like, for example, the Oregon Times.
Now, okay, so if you don't use that thing directly, if you don't use the Localize Title on your SK product directly, what is it used for? Well, we use it at Apple, okay? We need it for dialogues, as you've seen. We need it for management UI, which I'll go to in a second.
Okay, so if you don't use that thing directly, if you don't use the Localize Title on your SK product directly, what is it used for? We need it for management UI, which I'll go to in a second. And we need it for emails. But by you, directly in your app, you might not even use it. But nevertheless, you need to have an offer name. You need to put something by that buy button.
So what we recommend is, of course, start with a product ID. For example, com.org.times.sub.1month. If you encode the duration inside of the product ID, you can use that, combine it with a Localize Title, and you can present that to the user. Okay, so if you don't use that thing directly, what is it used for? You can present that to the user. But the most flexible solution is to take that product identifier, send it to your server, have your server translate it, and put that output in, put that by the buy button.
Okay. Now here's an example of how we use this metadata. Because even if you don't use it directly in your app, it is very important because we use it, and therefore your customers are going to see it. So this is just an excerpt of what things look like in iTunes.
You go to iTunes, you select the account, you select manage subscriptions off of that, you'll get a page, and it'll list all the applications. You'll see artwork and the name of the application, and underneath that, all the subscriptions that are in that app. And yes, you can have more than one subscription in a given application. So I've highlighted there Nylon Magazine iPad Edition, and the subscription name there is Nylon Magazine. So let's say I click on one of these. I'll see a page that looks like this. Again, you see the app name and the subscription name there.
And now here's what it looks like on iOS. Same kind of deal. You get a list of the applications and you click on one of them and you see all the subscriptions for that. In this particular example you've got two subscriptions there for the particular app. And then you select one of them and you go to edit it. Now, notice the subscription name is used prominently on that final dialog there where you see the description name up there in the title bar.
Now, imagine if you had named that something like, I don't know, quarterly. Okay. And user can sometimes get to this last page there to edit their subscription off of a dialog or off of an email. If that just said something like that, it wouldn't be clear to the user what it is they're actually editing. So it's important you name -- you give that display name in iTunes Connect something which will make sense for a context like this.
Okay. So I want to talk a little bit about receipts. Because they are a little different. It's the same format and stuff, like you'd expect. But there are a couple differences. All the fields are pretty much the same except for these two: the purchase state field and original transaction ID.
Now, the purchase state on a non-consumable is the date of download or re-download. Basically, it's the date that that download type of event happened. But for auto renewables, it's actually the date that the purchase event happened. Original transaction ID for auto renewables, this is the transaction ID of that first subscription buy, but it's also the transaction ID of everything else that comes afterwards.
So I just want to kind of explain how that works. So you buy this thing. You buy another one, and it's got a renewal receipt. So you've got the original receipt and the renewal receipt. They both have the same original transaction ID. You'd buy it again, the second renewal, and now you've got, again, the original transaction ID is the same for all three of these.
And then you do a restore, and when we restore, we restore all -- we restore receipt for every buy event. And so all these guys have the same original transaction ID. In essence, the original transaction ID is a customer ID as far as you're concerned. Okay. So purchase state.
Similar deal. You've got the original buy, the receipt, and the renewal. Each one of those, though, is going to have a different purchase state. Now, when it comes time to restore these guys, you're going to get a receipt for each of those. But instead of being the date that the restore happened -- I know you're going to get a receipt for each of those, but instead of being the date that the restore happened, I need to get a receipt for each of those. The purchase date is going to refer -- is going to be the exact same date of the transaction it's restoring.
The one new field is expire date. It means what you think it means. Just because the latest receipt you have is expired doesn't mean the subscription is inactive. To find out whether or not a subscription is truly inactive or not, you need to invoke our verification API. All right? And so this is what happens when you send that receipt for verification. We're going to give you back a status.
If you get back status zero, that means the subscription is active, and maybe that's all you care about. Now if anything goes wrong, you're going to get one of these error codes. Now I highlight 21006 error code down there because it's not a true error code per se. In essence, in other words, there's nothing malformed about the receipt. There wasn't like any exception happened on the server or anything. It's just that that receipt, while valid, is associated with a subscription which is no longer active.
Oh, actually, I do want to highlight a couple things. The last two statuses are fairly new, 21007 and 21008, Sandbox Receipts Sent to Production, Production Receipts Sent to Sandbox. These can come in handy for development, and they can definitely come in handy for app review. Okay, so in addition to that status, you're going to get some other information. Whenever you send a receipt to us, we're going to crack it open.
That's sort of my phrase for that. We're going to crack it open and show you what's inside. Basically, you can get a JSON dictionary of all those key value pairs that a receipt has. And they'll be under a, in our response, they'll be under a key called receipt.
Now, if the subscription is active, you're going to get some other goodies. And that includes the latest receipt, just the brand new blob of whatever the latest receipt is. And this blob might be the same as the receipt that was passed. But you're also going to get this field I call latest receipt info. When we first rolled out auto renewables, this wasn't available, but it is now. And it saves you a round trip to the server.
Basically, we're just taking that latest receipt and cracking it open right there. Before, if you've used this previously, you'd send a receipt to us, we'd crack it open and send it back to you. And you'd have to immediately take that blob and send it right back to us so we could crack it open again. Well, here it's already there for you so you can see everything that's inside it.
And I'd just like to point out this works regardless of the receipt that you sent, whether it's the latest one that you had or the first one you had or even a restored one. It doesn't matter if it's associated with that subscription. We're going to give you back the latest receipt and the latest receipt info if it's active. Now, if the subscription is inactive, before, we just gave you status 2106. And maybe that's all you cared about.
But frankly, it wasn't very helpful, particularly in development. So over the last, like, few months ago, we introduced this additional field called latest expired receipt info. Again, this is just a cracked open receipt that just shows you information about what that last good receipt was. Now, this might not be relevant for you in production, but it definitely is useful in development. But it could be useful in production, too, because you might want to offer certain customers maybe a grace period. And if you knew when the last subscription lapsed, you know, you could do that. You could do something like that.
All right. Now, restoring of these guys. You might think that, well, when you restore one of these subscriptions, you're just going to get back maybe nothing if it's expired, or maybe you get back the first one, or maybe you get back the last one. I just want to demystify this. What you're going to get back is everything.
For every single purchase event, you're going to get back a receipt. I kind of implied this on an earlier slide, but I just want to make it clear. If you had a monthly subscription and someone does a restore all, they get a brand-new iPad, they do a restore all on it, you're going to get a receipt for that original buy and every single renew event. And these receipts, of course, have an expired date and they've got a purchase date. And they've got that original transaction ID tying them all together.
So you have a full purchase history. Now, some of you might think, well, I don't really care about that. I've got a streaming video app or a streaming music app or maybe I've got a level inside a game. In a case like that, well, you just care whether it's active or inactive and that's it.
But if you have an application which has publications, it's got this content, you're going to want to give it back to the user most likely. They get a brand-new iPad or maybe they screwed up their iPad and they need to, like, reload it. With this information, you know when everything was good and when it wasn't.
And so you can say, okay, they're entitled to this issue and this issue and this issue. And this is an important point because having that quote there at the bottom, physical magazines don't vanish on expiry and digital ones don't have to either. And with this information, you can do that.
Okay, so how does the client become aware of a renewal event? We do this thing in the background. So what's going on? So we do the buy in the background on our servers. We put a transaction in the queue. So then the question becomes, when does the application actually check the queue? All right, just to be clear, it checks on launch, and it checks when an application rotates out of the background. So what I mean by that is, you're in the application, you go to check mail, you answer a phone call, whatever, you come back to the app, and then it checks.
Now, I bring this up, because normally it's like, so what? This thing's lasted a minimum of seven days. Of course, that kind of thing's going to happen. What's the big deal? The big deal is if you're in development and you don't know this, you're sitting there with your app, you might not ever switch away from it or restart it, and something renews, and you go, how come I don't see something? Well, this might be why. Maybe you haven't switched away or bounced the app.
Okay, now there's another way of doing renew. I call it the interactive renewal. It's what happens when you click buy inside your application for a subscription the user's already purchased. So what happens when you click a buy button like that? Well, if the subscription is currently active, you're going to see a dialogue. We'll basically say, hey, this user's already -- Mr. User, you've already subscribed to this.
You can click this button to dismiss this dialogue. You can click this button called manage, and it'll actually take you to one of those screens you saw at the beginning of my talk. So you can click this button to manage the subscription. Now, if the subscription is expired, or I should say totally inactive, we're going to do the buy right there.
In fact, the experience is just like if they bought it the first time. And, in fact, the only difference is you're not going to see that data sharing opt-in dialogue. Otherwise, it looks exactly the same. And it behaves just like any other kind of renewal as well. So this is going to be important when you start working in the sandbox because of some limitations in the sandbox, which we'll get to in a moment. So we're going to go over all these, but I do want to stress the first three. Just so you know, we renew a few hours before expiry so we can guarantee some level of continuity.
And another thing you might not know because it's not in the docs is if you jack up the price or you take something and you make it unavailable, we're going to disable auto renew. We're going to send an e-mail to the customer, and it's going to be up to that customer to respond to that e-mail. There's a link on it to go straight into the management screen so they can go and decide what they're going to do. Now, let's say you have a year-long subscription.
Just because the price goes up for an hour and then back down, like maybe you screwed up or maybe just an accident happened and something became temporarily unavailable, that isn't going to cause this storm of e-mails going out and auto renew getting disabled. That's because we don't check immediately. What we do is we just basically, like for a year-long subscription, we're going to check 10 days before expiry. That's when we're going to make these checks for price increase and for item unavailable.
And then that gives the user, like, a little bit of time to check. At least a little over a week to get that e-mail and decide are they going to actually renew with a new higher price, or are they going to -- that gives them some time to choose maybe a different duration with which to renew with.
Okay, so a little bit on cancellation. Cancellation is a word that can mean different things to different people, so I want to be clear on the different flavors of cancellation. I would say there's no cancellation per se for the user. What a user can do is manage their subscription, go into the management screen and flip a switch that turns out or a new off.
That in no way invalidates their current subscription. All it does is, it says, "Okay, I'm just not going to buy the next one." That's all that means. Now, having said that, our support organization, for customer satisfaction reasons, does have the ability to do a true cancellation. If someone calls up and says their kid just ordered a $60 subscription to something for a year and it was an accident, support may elect to go, "Okay, fine, we'll refund that." Now, when they refund that, it changes how you respond to verify receipt.
You send a receipt to us on something that's been canceled like this, even if the expired date is in the future, we're going to come back and say that, "Hey, this is 21-006 inactive." That can be useful for, I guess, fraud or maybe you don't even care, but I just want to let you know that's what we do there.
Okay, now a little bit about how this works in the Sandbox. Sandbox is supposed to be just like production. Unfortunately, for auto renewables, it can't be like production because we can't have you sitting around waiting seven days just to wait for something to renew. So, and we don't want these things to renew over and over again. So the first thing new about Sandbox, different than production, is we automatically cap renewals at six. And stuff renews really fast. You might want to test with years, and I'm not kidding.
Stuff renews so fast, sometimes the renewal happens after expiry. I just told you earlier that renew happens like hours before expiry. But in Sandbox, if you have a subscription that is over in three minutes, it might be a minute after expiry before the thing actually renews. And finally, the management interfaces are not available. Okay? So those screens that I showed you at the beginning that the user gets to see, they're not available in Sandbox because Sandbox is a server-only type of environment.
All right, so here's the -- I'm not going to go over all of these, but as you notice at the top, seven days is three minutes. One year is 60 minutes. So that means if you do the seven-day one for three minutes, in 18 minutes, 18 to 20 minutes, it's already expired. And I bring this up again so developers aren't mystified by what's happening.
They subscribe to this thing, they go and get a latte, they come back, and they go, "Wow, nothing renewed, and this thing says it's expired. It's busted." It's not necessarily busted. It just means that it is dead now. It has totally expired, and it actually renewed six times.
Okay, so why do we cap at six? Number one, we want to allow you to test how your app handles the end of a subscription. Number one. Number two, the fact that this thing goes expired means you can use that interactive buy to do a few things. Basically turn your app into the management interface because you can do that interactive buy. You can basically wait, buy another one, maybe wait again, buy it again.
You can also change the duration. Maybe you started with a weekly and you waited a bit and you bought with a monthly. Anyway, this allows you to test a non-contiguous history and it allows you to change durations and test with that too. You can create a fairly complex history, do restore all on a blanked out device and test how things work in all those different cases.
Okay, and finally, I'm going to talk about auto-renew and the app review flow, because I don't want you to get hung up in app review. I want you to understand how this works. What we do in app review is we put your app in the sandbox, the same sandbox you were using for development.
But we don't use a developer-signed app, we use a production-signed app. Now, why do we do that? Well, we need to review what customers will receive. Now, some bugs only affect a production-signed app, and we don't want to basically have a brick go out into the store. But the problem is you've got a half-production, half-development situation here.
So to elaborate on what I mean by that, if you're in development, you've got a test dev app that's talking to your test server, and both of those things are talking to our sandbox. Now, you go into production, and you've got a production application, it's talking to a production server, probably, it's probably wired to only talk to your production server, and it's all talking to Apple's production servers.
But if you get into app review in the middle, we're in this sort of weird state where you've got a production-signed app that's probably talking to your production server, and yet both of those things have to talk to our sandbox. Now, it's easy for us to fool the app to thinking it's talking to production with some DNS tricks, where it talks to our sandbox, but that doesn't apply to your server. So you see your server in the middle there, it seems to be -- it's like we're asking it to the impossible.
The production dev server needs to talk to our sandbox in one case for receipt verification, and it needs to talk to our production in another case. So how can you accomplish this? What most people do is the first option is sort of avoid it altogether. I call it the "darkness" option. I call it the "smart production signed app." In this situation, the app knows the live version, maybe by talking to your production server, and it knows what version it is.
And so that's enough information for it to select the right version of your server for receipt verification. Now, the other option is what I call the "smart production server." In this case, your client would pass a version number that it is and the receipt, and then your server would go, "Okay, I know what's live. I know what I just received. I'll send this to the sandbox or send it to production." That's another way to go.
The third way, which might be the best -- I think this is maybe how I do it, but it wasn't initially available -- is to take advantage of one of those statuses I talked about earlier on in the talk. I call this the "reactive production server." In this case, your production server receives a receipt, and it just always goes "receipt to Apple production for verification." "Receipt, Apple production for verification." Okay? And the only time it does anything different is when it gets back 2107, you know, double 07. That means sandbox receipt sent to production.
If you get that, then you go off and you send it to our sandbox and then just proceed. So I like this better because there's no checking. There's no version passing. No one has to know what the active version is. It sort of just works, and the only time you have an extra call is in that case where you actually hit the sandbox or need to hit the sandbox. So that concludes what I needed to squeeze in here. To resume on this in-app purchase reporting is Ricardo.
Thank you, Dave. So In-App Purchas reporting. For consumables, non-consumables, and auto renewables, you log into iTunes Connect, Sales and Trends module. You can see your free apps, paid apps, updates, as well as your In-Apps clicking on the In-Apps tab across your weekly and daily views. We also have iTunes Connect Mobile 1.2, which was released last week. An update for push notifications. Again, a similar review.
Another view of iTunes Connect Mobile. In the auto-renewable case, your personal information reports are available in the Sales and Trend module in iTunes Connect. You log in, go to the opt-in report, and use your opt-in passkey to unarchive that zip archive. And now to talk a little about best practices across all app, In App Purchases, I'll bring Max back on stage. Thank you, Max. Great. All right. Thank you. So now what I want to do is just walk you through a few best practices for implementing In Apps in your application. The first is to know that In-App Purchases are not cross-platform, nor are they cross-application.
Meaning, in-apps are scoped to a single application. So when you're restoring, you're always restoring to a given application. Also, virtual currency is allowed when used within an application, but it's non-transferable to goods and services outside of your application. And again, to point out what Dave stressed, AppReview is reviewing a production-signed application that's pointed at the sandbox environment.
So to wrap it all up, I think one thing that you should definitely take away from this is that the auto-renew subscriptions are fairly complex, and you want to make sure that you've handled all of the different cases when implementing them. Also, restoration of In-App Purchases is required for non-consumable as well as subscriptions. If you're currently using the non-renewable subscription types, you want to look at migrating over to using the auto-renew subscription types. And for our Mac OS X developers, Lion is just around the corner, and the sandbox is ready for you to start testing.
So for more information, Bill Dudney is the Application Frameworks Evangelist. In addition to the documentation that Jean-Pierre referenced, there's also the iTunes Connect Developer User Guide. And of course, we always welcome your feedback on the Apple Developer Forums. There's related sessions directly following this one. It's a What's New with App Publishing and iTunes Connect in the Presidio. And with that, I'd like to say thank you very much, and have a good day.