The StoreKit API allows apps to request payment for additional functionality or content. Hear about the latest changes to StoreKit including Swift 3.0 APIs, updates to Subscriptions and using StoreKit with iMessage apps. Learn best practices for receipt management and Sandbox testing.
[ Music ]
So my name is Dana DuBois.
I'm an engineering manager on the team
that writes the frameworks
that help power the App Store on iOS and tvOS.
And today we're going to talk about one
of those particular frameworks, and that's StoreKit.
Many of you know, StoreKit's been
around for a long, long time.
It was introduced in iOS 3 for the iPhone.
Since then it's been used by thousands and thousands of apps
to power all sorts of business models.
Everything from newspapers and magazines, games,
even dating apps are using StoreKit.
It's really widely used.
And we've talked about StoreKit a lot at WWDC,
but this year we're going to do something a little new
and we're going to talk about it using Swift.
So that's really exciting.
We've got some new APIs.
There's a couple other things that are new, so Swift API,
so that's really great.
Last week, many of you probably also heard that we have a lot
of big announcements around subscriptions.
This is something we're really excited about as well.
I think a lot of developers are going to end up taking advantage
of these new enhancements with subscriptions.
So I'm going to give you a quick overview on them.
First up, categories.
We're really you know excited to announce
that category will no longer be a factor if you're choosing
to use auto renewing subscriptions
in your applications.
There are still going
to be criteria behind how you can use auto renewing
subscriptions, but category will no longer be a factor.
Second, everyone's got to be excited about this,
we're giving more proceeds to developers.
If you keep your subscribers for more
than one year, that's really great.
And I think that's going to be a big deal.
Pricing. A lot of control now we're going to be giving
to developers through iTunes connect to set the pricing
for their subscriptions based on territory
to territory, region to region.
If there's a business reason you might need to adjust the price
in Europe compared to the US, there's a lot of control
that you now have over that.
And then along with pricing, we're giving you the ability
to save the price, to preserve the price for users
who may have already been using your subscription while
adjusting it for new users.
So, if you have early adopters that you want to reward
and you want to keep them using your subscription, but you want
to adjust the price for newer users, you have that power now.
And then upgrades and downgrades,
this is us giving the user a lot more power
to control exactly what level
of subscription they might want within your service.
So if they want to go up to the platinum level,
or go back down to the basic level, they can do that right
in the Manage Subscription UI right on the device.
So that's a quick overview of what's new in subscriptions.
There's a lot more to it.
I think if you're going to have subscriptions
in your application, you really should go
to Introducing Expanded Subscriptions in iTunes Connect,
that's at Pacific Heights today at 4.
Really, they're going to get a lot more in-depth on how
to set this up, how to manage this in your application
and I really highly recommend you go to that.
So that's subscriptions.
There's one other new thing that I'm really excited to announce,
and that's iMessage apps.
We announced that yesterday at the keynote.
We're bringing apps, a whole new class of apps right
into the iMessage app, iMessage.
You'll be able to build custom extensions, and we are going
to allow in-app purchases right in those extensions,
right in iMessage aps using the exact same StoreKit APIs you
would use in a normal application
that you have in the store today.
So if you have additional content that you want to market
or provide right inside the iMessage experience,
that's now supported.
And this will all be available in iOS 10,
so that's something we're really excited about
and I think developers are going
to take a lot of advantage of that.
So as I said before, StoreKit's been around for a while.
People have been using in-app purchases for a long, long time,
but maybe some of you are new to it.
So I'd like to just give a quick overview
of what exactly in-app purchases are.
In-app purchases are digital content or service
that can be bought right inside your application.
However, to be clear, it's not for physical goods.
There's other ways of doing that.
This is really just about digital content or services.
Now when we're talking about digital contents or services,
there's a bunch of different types.
When you're configuring this in iTunes connect, you have a lot
of options and you need to make sure
that you choose the right type that fits your content.
So let's take a look at what those are.
Everybody's played a game and they have coins in that game,
currency, or gas in your racing car, or something
that they user's going to buy, and buy again,
and buy again, and use up over time.
That's what a consumable purchase is.
A non-consumable product is something that sticks around,
it will stick around for as long as the user wants to use it.
They'll be able to restore it.
They'll be able to move it from device to device.
So that's a little different.
And again in a game you might have a sword,
or you know some sort of weapon, or you know a racing car,
or a level, or if you have a utility app,
you might have a basic edition of your app and you might want
to offer a pro-edition of your app.
That's kind of a non-consumable product.
We also have two types of subscriptions
when we're talking about subscriptions.
There's non-renewing subscriptions,
as the name suggests these are subscriptions
that don't automatically renew, it's up to you
and your application, and your back end to manage how
to renew those subscriptions.
But then we also have auto renewing subscriptions.
And these are subscriptions that Apple will bill to the customer
on a periodic basis, based on what you configure.
So if it's a monthly subscription,
we'll bill the user every month, as long as they continue to opt
into that subscription.
So these are the types, let's get into the heart
of adding in-app purchases to your application.
So, what I'm going to do is I'm going to do a quick overview
of all the various steps, and then we're going to dive
into each one and we're going to talk
about how to do this in Swift.
And you know exactly what you might need to worry about as far
as pitfalls, or any concerns you might have along the way.
There's a lot of things that can get kind of tricky sometimes
when you're developing against StoreKit.
A couple of things to keep in mind.
So first off you're going to want to figure
out exactly what it is that you're going to sell
to the consumer, the user of your app.
So this is done just by determining the identifiers,
those in-app identifiers of what you're marketing
to the user right then and there.
Once you have the identifiers, you go off to the App Store
and you fetch the information,
localized product information that's related
to those identifiers.
And that's key.
This is localized information.
This is a global marketplace, you want to make sure
that you're displaying the information
to your users in a localized way.
And now once you have that information you're going
to show off the products.
You're going to market them.
You're going to sell them.
These are your products, this is your application, you're going
to build the best UI you can to show them off.
The users then are going to be enticed to make that purchase.
They're going to be you know, sold, and they're going
to select the product right then and there.
But it's up to you to then create a payment
for that product and add it to the Payment Queue.
And we'll be talking a lot more
about the Payment Queue as we go on.
As the payment is going through the Payment Queue your app will
be notified about that transaction and you're going
to have to make some response to it,
and that's how you process these transactions.
Finally, when the payment is completed, you're going to make
that product available.
Give the user what they paid for.
And then finally tell the Payment Queue you're done
with the transaction, everything's completed,
the product's available,
so that's finishing the transaction.
So those are all the different steps you need to take.
We're going to dive into each of those as we go through,
but first special note about the Payment Queue.
The Payment Queue is the center
of your in-app purchase implementation.
It's the source of truth for state about purchases
and payments as they're going through all the way
from when the user selected that product to when it's paid for.
And it's important to keep in mind that you should rely
on the queue and only the queue to know about transactions
that are progress, payment updates,
and if you're using hosted downloads,
the Payment Queue will tell you all about those downloads.
And then another thing to keep in mind is
that if the Payment Queue tells you about a payment,
it's a valid and real payment.
In fact, there are cases we've seen
where developers might have their own side cache,
where they've noticed that a user has clicked on a product
and they're managing state about that payment.
And then their app will crash,
or something will happen along the way,
the user will close the application before finishing the
payment, and they'll come back into the game, or whatever it is
that they were purchasing then there.
And they don't necessarily respect the response coming
from the Payment Queue because they weren't listening
to those payment transactions
because their own queue no longer had them in state.
So you should really just rely on the Payment Queue
to tell what's going on with those payments
as they're happening.
And in fact it's very important and we're going to get
into some code here, to listen
and observe the Payment Queue right when your app starts up.
This can be done in the example we have here,
we have didFinishLaunchingWithOptions is
the first thing that happens with your application
when it starts up and we create a payment transaction observer,
in this case it's the app delegate itself.
And we set it right on the Payment Queue,
we add it to the Payment Queue.
And then if there's anything in the Payment Queue
that may have been there before our app launched,
we'll get notified about it right away.
Another kind of case that comes up is there are applications
that have in-app purchases where they have redeemed codes.
So the user might have actually gone into the App Store
and redeemed that in-app purchase completely outside
of your app.
The user then is exciting about consuming that in-app purchase,
they launch your application, and if they're not listening
to the Payment Queue that product won't become available.
You got to do it right when the app starts up.
So that's a quick note about the Payment Queue.
Let's get back into the process and understand exactly how
to add this to your application.
So the first thing you want to do is load the identifiers
for your in-app purchases.
These are the same identifiers
that you set up in iTunes Connect.
You define them, you name them.
And you just need to get a list of them.
There's a couple different ways of doing it,
if your app is very simple,
you might just bake the identifiers right
into your application.
If you have an application that has a basic version
and a pro version, you might just have one consumable
and you just baked it right into your application.
However, we've seen more and more applications out there
where they're interested in going out
and fetching those in-app identifiers from a host
that they provide so that
over time maybe they can change what they're marketing
to the users, or exactly what appears where.
That's okay to do.
Completely valid to do.
The thing we want to call out is if you're doing
that make sure your host is scalable and reliable.
This is the beginning of your in-app purchase process.
The worst thing to show a user right now is just a spinner
while they're waiting to make a purchase.
This should be, and if you can fetch in advance, that's great.
If you can cache on the device that's even better.
Be very cognizant of how you are fetching
and preserving these identifiers.
Now that you have the identifiers you need to go
to the App Store to fetch the localized product information
associated with those products.
This can be done with an SK Product Request.
You pass in the identifiers that you're interested in.
Again, for the smoothest experience possible,
you want to do this in advance.
You want to anticipate when the user might be interested
in looking at your in-app purchases,
and have that information available ahead of time.
So first thing you do, create your SK Product Request.
You pass in the identifiers you're interested in.
You set your delegate.
This will give information back to your application
about when those products are loaded.
And then you just call start.
The delegate looks like this.
We have product request, didReceive response.
This will pass in all of the products
that you requested from the App Store.
And each of those products will retain information
like a localized title and description.
As I said before this is a global market place,
you're marketing your in-app purchases around the world.
So it's important to make sure
that you're actually using localized information
to make your sales.
So localized title and description,
even more important is price and price locale.
You want to present the user the price of your in-app purchases
and you want to make sure it's presented
in a format that they understand.
Currency is represented differently around the world
and you know it's important that you do it right.
We'll get into that in a moment.
And then finally if you're hosting your in-app purchase
content, this is something that you've set up in iTunes Connect,
we actually give information
about the download contact length
and versions associated with those purchases.
So as I mentioned the price, it's very important
that you do the right thing when presenting those price strings.
When you're presenting those prices, you want to use
that price locale and pass that into an NS number formatter,
and that will get you information
about that pricing information.
That NS number formatter, will take that price information,
take the locale associated with it.
If you set it to a currency format, you can make sure
that you're getting that pricing information correct.
The other thing you want to do is to not bother doing any sort
of currency conversion of your own.
The App Store knows how to localize,
convert those currencies.
So you don't need to bother with that at all.
Just present the price using the NS number formatter as is.
The next step after that is to present your UI.
Not really going to talk too much about that,
these are your products, these are your applications.
You know how to present them in your UI
to make the best sales pitch possible.
However, once the purchase has been complete,
or once the UI has been shown, we're going to jump right
into making the purchase itself.
And that can be done by adding
and creating an SK payment object
and adding it to the Payment Queue.
Once you've created that SK payment object and add it
to the Payment Queue, you'll get a callback
as the payment is being processed
through updated transactions.
So this is that Payment Queue Observer you added right
when the application started.
You created your Payment Queue Observer.
It called Payment Queue updated transactions.
And you'll get information about the payment as it's going
through the process so all you did was you created your
Added it to the Payment Queue.
The information started coming in and you're going
to get information about all the transactions in process.
You might have one, you might have many.
You should iterate through those transactions and then listen
to the state for each of those transactions.
It's a couple different states,
the one you're probably most interested
in is the purchase state.
This is where you know that the purchase was completed
and should go ahead and validate that purchase,
we'll get into that in a little bit,
and make that content available.
However, there's one other state I'd like to talk about as well
and that's the deferred transaction state.
Deferred was added back in iOS 8 and it's
for the Ask to Buy feature.
This was to allow iCloud families
where children could attempt to make a purchase,
such as an in-app purchase, and their parent or guardian,
their approver, will have to decide whether or not
that purchase will go through.
The deferred state is the state
that you're in-app purchase lands
on when it's currently pending approval from the parent.
One thing we've seen a lot and we want
to make it very clear is you should not block your UI if it's
in the deferred state.
You should handle that in a way
where maybe the purchase hasn't even occurred yet,
just let the child who's actually attempting
to use your app make that purchase, just let them go back
and continue to use the game
or whatever it is they're interested in.
Because it might be hours,
it might be days before the parent goes through
and approves that purchase.
So no spinner, no modal dialogues.
Just treat deferred state as if the purchase hasn't even,
you know hasn't even started yet.
One thing I also want to get into is it's very important
to test your applications when using in-app purchases,
just like testing your application any other way.
And this can be done through the iTunes store
This is a special environment.
If you're running your application
and it's a developer signed application, any purchase
that you make will go to the Sandbox environment.
However, if you're interested in testing deferred transactions,
there's really no good way of creating a family
so that you can actually test the Ask to Buy flow.
So if you want to test your deferred transaction in Sandbox,
it can be done using SimulatesAskToBuyInSandbox.
This is where you create your SKMutable payment object.
You pass in that product
and then you set the SimulatesAskToBuyInSandbox flag.
This is a flag that's going to tell the App Store, hey,
treat this as if a child was buying this
and that child was part of a family.
Once you add it to the Payment Queue that gets sent
up to the App Store and the App Store will respond back
with a deferred state to your application.
This is your way of knowing, hey my app is going to work
when kids are using it.
We also should talk a little bit about handling errors.
Not everything is going to go right.
There's going to be error states in your application.
Especially with in-app purchases.
One thing to keep in mind is not all errors are created equal.
I really encourage you to check
out the In-App Purchase Programming Guide,
or the StoreKit Framework Reference Guide
to get a good sense of all the possible errors
that can be returned in your application over time.
One thing to keep in mind is most
of these errors aren't something that you need
to inform the user about.
Most of these are just errors that we're informing you
to handle in your application.
A great example of that is I'm going through,
I'm using your application, I'm browsing around,
I'm doing a little bit of window shopping.
I click on purchase.
I'll get the price confirmation dialog that StoreKit will show.
And then I change my mind, I want to go back
and see what else is there.
And I hit cancel.
Cancel error, StoreKit will return a user did cancel error
to your application.
There's no need to present the user
with a user did cancel alert.
And we'll see this in applications from time to time.
The user knows that they cancelled.
There's no reason to repeat that back to them.
Let StoreKit handle the transaction flow
as much as possible.
Again, we got into the Payment Queue.
The Payment Queue is where the payment will be processed.
The App Store and StoreKit
for you will confirm the purchase with the user.
They'll present a price.
That price should match what was inside your app.
So that's why isn't important
to make sure you localize the pricing information correctly.
We'll authenticate the user.
If there's any issue with their billing information,
we'll handle that.
No need for you to pop a confirmation
or do anything special, let StoreKit handle that for you.
So we talked a little bit about before the transaction queue
and we talked about the states
that can be returned for your payment.
Once your payment has made it to the purchase state,
you have a number of choices you need
to make in your application.
Specifically, around validating that that purchase is backed
by a real monetary transaction.
So we'll get into a couple different ways of doing this.
But again, it's your application,
they're your products.
So it's really important to keep
in mind exactly what technologies you're using
and what level of security you want to use
to validate your purchase.
So receipt validation, this is the receipt that is returned
to the application at the end of the purchase.
It's just like a bill that a consumer might get when shopping
at a mall or something like that.
It includes all this information about the purchasing of the app
and the purchasing of your in-apps.
And there's kind of two main ways
that you can attack validating that receipt.
First is on the device itself.
This receipt comes down, you can write code right there
on the device to pull it apart, inspect it,
make sure you know authenticate that it came from Apple,
make sure that it's from a valid monetary source.
And this can be done kind of generally is
for just unlocking features and content right within the app.
So again, this is one of the choices you have to make.
Is this a purely client side,
right inside your app type of purchase?
Or if you have a server side, you might want
to actually have the server validate the receipt
because you want that to be the gateway
for your content or service.
And this can be done by taking that receipt that was sent
to the device, uploading it to your server and then having
that server send the receipt over to the App Store,
there's a backend API to verify that receipt.
And that can be done server-to-server.
One note with that though,
is yes the App Store does have a backend API that can take
in that receipt and validate it, but you should never send
that receipt to that API directly from the device.
That is not a secure mechanism and there are limits
to how trustworthy that can be from your application.
So if you're going to use the verify receipt endpoint,
it should really be from your hosted server,
right into the App Store itself.
So let's get a little bit deeper into what the receipt is.
The receipt is a trusted record of app and in-app purchases.
It contains information that will allow you to know
that this app was bought by this user on this device,
and those in-app were bought by that user on that device.
Stored right on the device,
right into the application container of your app itself.
It's issued by the App Store and it contains information in it
that allow you to verify that it actually came
from the App Store itself.
And again, it's for your app, for that device only.
If your app is running
on a different device it will get a very different, you know,
it will get a different receipt for a different user.
This is kind of, this just gives you a sense
of what it looks like.
Again, stored in the app bundle.
We give you an API to get it.
We'll see what that looks like in a moment.
And it's a single file.
Old, old, old versions of the receipt there used
to be multiple files for each in-app purchase,
but since iOS 7 we've had a unified receipt
that contains all this information in one single file.
It also, again, contains certificates and signatures
to allow you to verify that this receipt is valid.
We do this through a Public Key Cryptography Standard
This is the container that contains all this information
in it and this is an open standard.
So there's a lot of information that you can use out there
on how to work with a PKCS7 Container.
The payload of that container,
the thing that contains the actual information
that you're going to be parsing out, that's encoded
in an ASN1 format, again public open standard.
And there's a lot of great options out there
for verifying this, OpenSSL is a very common one.
Sometimes people create their own.
But again, something to stress here is
that this is your application, this is your money,
this is your business.
So you've got to make good choices on how best
to verify this receipt and what technologies you're going
However, whatever you choose, there's some similar processes
that you're going to go through.
First up, is you're going to locate the receipt
in the application using an NS bundle API.
And again, this is what it looks like in Swift.
You can call right in that NS bundle,
and there's an App Store receipt URL
that will be returned by that.
This is a local URL, local to the file system.
Once you have that URL, you pass it into NS data
and you get the binary payload of that receipt.
Now that you have that binary payload,
a couple things to keep in mind.
The certificates on there will have an expiration date,
but you've got to be very careful
about checking that expiration date.
Just because it was issued at a certain time, doesn't mean
that that expiration date is valid
for all time in the future.
So if you're checking the expiration date,
compare it against to when the receipt was issued
from the App Store, not to what the current date is.
It's not like an SSL handshake, where you want
to check it every time.
It's only valid for when it was issued, or it's only valid
to check the date for when it was issued.
Or it's perfectly valid not even to check the date at all.
But what you do want to do is check
up to the root certificate authority on the receipt.
That will verify that it came from Apple.
That you can trust it because it is Apple's receipt.
So check up to the root.
So again, this just kind of gives you an idea
of what it looks like inside the receipt.
The payload of it, that ASN1 format that I was talking
about is a series of attributes.
You can think of it almost as an NS dictionary.
It contains types and values.
And we're going to highlight some of those types and values.
There's more in there than we're going to talk about today.
And you can get a lot of that online
through our Receipt Validation Programming Guide.
But some of the main ones you're going to want to use are type 2
and type 3, that includes the bundle identifier
and the bundle version that the receipt was meant for.
Hopefully that matches what's in your application
and you should check it.
So you should check the bundle identifier.
You should check the bundle version.
And then one thing to keep
in mind is you should use hard coded values right inside the
binary of your app.
It's a lot easier for me to go in and change the info P list,
if that is what you're using to match a phony receipt than it is
for me to change the payload
of your application to match the receipt.
So if you really want to make sure that that receipt is
for your application, use hard coded values.
Now that you know that this receipt is for your application,
you want to make sure it is
for the device that's running the receipt right then
And this is a little trickier.
What you want to do is take a look at the SHA-1 hash
that is returned in type 5.
Type 5 contains this hash.
The hash is made up of pieces of information
that the App Store knows at the time of purchase.
And pieces of information that you know a time of verification.
That specifically is the bundle ID.
So again hard coded value you want to keep in your app,
the bundle ID of your app.
The device identifier.
This is a, there are APIs for that.
It's a little different on iOS versus macOS, but you want
to load up that device identifier.
And then this Opaque Value.
This Opaque Value is basically it's a little bit
of cryptographic entropy.
It's a secret salt that is included in the receipt.
It allows the hash to change over time even if the bundle ID
and the device identifier aren't changing.
You should basically take the Opaque Value that's
in the receipt and include it in your hash.
Once you have that, SHA-1 hash compare it to attribute 5
and if they match, you know it was for your device.
And again it's unique to your app on that device.
The receipt also contains information about all
of your in-app purchases.
So what we see here is a whole bunch of, more than one Type 17.
Type 17 is for each and every purchase that the user's made
with your application it will include one record
for that in-app purchase.
The pay load for Type 17 won't be a string,
it will actually be another ASN1 document
and that will have its own values inside of it.
So what do those look like?
Well 1701, that's the quantity of purchases made.
So we talked about consumables before,
the user could have purchased 10 bags
of coins inside your game, or 100 bags of coin.
That's going to be the quantity, the number of purchases
that was made against that particular identifier.
The product identifier, we talked about this before.
This is that identifier that you use
to load your in-app purchase data from the App Store
and what you set them up in iTunes Connect as.
The identifier, this is a transaction identifier.
This is a unique identifier for the transaction that was used
to make that purchase.
The date of the purchase.
And then finally one new thing, it's not new,
but one thing I want to highlight is we also include
for auto-renewing subscriptions,
the subscription expiration date.
So if you're switching your app over to subscriptions,
that field's important to you.
You're going to use that to kind of, you're going to use
that to know is this subscription still valid?
Do we need to ask the user to, or you need to double check
that the user is still in a valid subscription?
So that field is very important.
And then one other note.
If you have an app that's currently in the Store,
and it's a pay for app and you're interested
in switching it over to a subscription model,
one thing you want to make sure you check is inside the main
receipt, the app receipt itself is Type 19.
This includes the original application version
that that app was bought with.
So if I bought it as version 1.0, which was a pay for app
and in version 2.0 you moved to subscriptions,
I want to take a look at that original application,
because I want to make sure I treat that user as the paid user
that they are and not as the subscription user.
I think it's a really bad experience if the model moves
over to subscriptions and you don't respect
that they purchased that app originally.
So it's important to keep in mind
if you're switching to subscriptions.
A couple other notes about the receipt.
The receipt is issued at the time of purchase.
But it actually is also renewable.
But it's only renewable
for certain types of in-app purchases.
So when we're talking about consumable
and non-renewing subscriptions, they are not going
to be refreshed with the receipt.
So consumable and nonrenewable subscriptions only appear once.
They appear right after that transaction was made.
And they're not going to be there when the user refreshes
that receipt either on that device or when they switch
to a different device.
However, non-consumable and auto renewing subscriptions will
always be in the user's receipt.
And you can get those back
and should get those back via a StoreKit API.
We can take a look at what that looks like.
It's a little different on IOS versus macOS.
On iOS, the receipt doesn't exist or is invalid,
you're going to want to use this StoreKit API to refresh it.
But keep in mind that you're going to have to have network.
We have to make a connection to the App Store.
We have to validate the user.
We've got to know that they're the ones
who have actually bought this thing.
So they're going to have to either enter in their password,
or use their thumb print.
And if you're doing anything
like refreshing the receipt every time the app launches,
which is really not a great pattern to follow,
or if you're doing anything
where you're checking the receipt is invalid
and then fetching it because you know maybe there's something,
something doesn't look right, you want to be careful
that you don't get stuck in a loop over and over again.
If your app crashes and you're constantly checking your receipt
Or if you keep checking and it's invalid
and there's something not quite right
about your validation code, you don't want to validate and fetch
that receipt over, and over, and over again.
So that's something to be careful about.
This could be done through again, on iOS, this can be done
through an SKRecipt Refresh Request.
You set your delegate and you call start.
This will inform your application right
on the delegate when the receipt is updated and you can go
and process the transactions in that receipt just
as if they were purchased by the user.
On macOS a little different if the receipt is invalid,
you're going to want to exit with code 173,
this will tell Finder, hey go fetch the receipt for me.
Again, it's going to require a network and the user's going
to have to be signed into the Store.
And this can just be done by calling exit 173.
And then I just want to re-highlight again
with server-to-server validation.
If you're doing an auto renewing receipt and you have,
an auto renewing subscription
of if you have content that's available on the server,
you probably have a hosted implementation backing
up your in-app purchases.
And so if you're doing server-to-server validation this
will allow you to validate on the server side that the receipt
that the user got for their in-app purchases were valid.
So again, you take that receipt that was on the device
and you upload it to the server.
However, I'm going to highlight it one more time,
don't send the receipt directly to the verify receipt endpoint.
It's not secure and you should not be doing that.
One thing to note the verify receipt endpoint returns a JSON
payload and that will actually include information
like if the receipt you had was maybe a little out of date,
you'll get the latest version right back from the App Store.
And it will include some information about was it valid
or if there was some other state wrong with the receipt.
So again, there are documentation online
about exactly how the verify receipt endpoint works.
Okay so now we've gotten through that, we've made the purchase,
we've processed the transaction.
It's up to you to decide exactly how you're going to verify
that receipt and what level of security you're going
to put behind it and what technologies you're going
You validated that that purchase was real.
That there was a monetary transaction behind it.
It's up to you to make what the user purchased available
Make good on your end of the deal.
And so there's a couple ways of doing this
and we talked about it before.
You might just have functionality that's hidden
in your app that you're about to unlock.
A basic version of your application.
A free basic version that now is a pro edition and you just need
to set that state and make that available to the user.
Or if you have content that's coming down from the server,
you need to download it.
Whole bunch of different technologies,
whole bunch of different ways of doing that.
I want to highlight a few of them now.
One that's a little newer
that Apple provides is on-demand resources.
This is a way of taking your application
and having the initial download be as small
and compact as possible.
Just the binary.
And if you're going to have other resources associated
with that application, if your games have a bunch
of different levels and they have you know graphics
or videos associated with them, you can break that up
into different components within your apps manifest.
On-demand resources is hosted in the App Store, so you don't have
to worry about hosting.
It's scalable and reliable.
We have caching all over the world for this.
Your users will be able to get their content fast.
One thing to keep in mind is it can contain any type except
So all that code has to be right in your original binary,
but it can contain any other content you might want to have.
And it's also available only on iOS and tvOS.
macOS doesn't currently support on-demand resources.
So that's a technology you may choose to use
to fetch additional content after a purchase has been made.
If you're interested in learning more about it,
I highly suggest you check out Optimizing On-Demand Resources.
It's in Mission, this room, Thursday at 10 a.m.
Another technology that Apple provides is hosted in-app
This is content that you can associate right
with your in-app purchase, right in iTunes connect and again,
it's hosted on Apple servers.
So you don't have to worry about hosting them yourself.
Scalable and reliable.
Around the world caching.
One thing to keep in mind with this and as with the ODR,
is that this will download your content in the background.
Your app doesn't need to be running.
So the user makes a purchase, and then leaves your app,
launches another app, and you have to download this content,
that will keep running.
You get up to 2 gigabytes per in-app purchasable product.
So that's not 2 gigabytes
for your whole application that's 2 gigabytes per product.
And this is supported on iOS, tvOS, and macOS.
So, again another great way of having Apple host content
for your in-app purchases.
Let's take a look at what that might look like a little bit.
A payment came through, the user, you validated it
and you're ready to download content.
You're going to be in the updated transactions call back
of your payment observer.
And you're going to go down a little bit and you're going
to look at your transactions and you're going to notice that one
of those transactions contains one or more downloads.
And all you've got to do is pass that download right back
into the Payment Queue and that will kick off the download.
If your application is interested
in using hosted in-app purchases, you're going to want
to have a Payment Queue updated downloads method inside your
Payment Queue Observer.
And this will give you all this information about the downloads
as they come in, including things like progress will call
in and let you know progress and you'll be able
to use this to update UI.
Or time remaining.
Or if an error occurs and you have to react to that,
that information will be there.
And then once the download is finished a URL will be provided,
again that's a local path URL, where it is on the file system,
so you can grab it and interact
with your content right then and there.
So that's how hosted in-app purchases work.
But you may also want to self-host this content,
perfectly valid thing to do.
If you have a catalog that changes over time,
of if you have different things you don't necessarily want
to have Apple host, perfectly valid
to do self-hosting content.
One thing to keep in mind is there are background download
APIs that you should be using NSURL Session.
It's the way to host this content.
Content is downloaded even when your app is not active.
If you're still using NSURLConnection
And that's not going to be as great of an experience
for the user as NSURL Session.
So it's very important that you use these APIs.
This is how it looks in Swift.
You're going to create a session configuration.
This is a configuration you want to name is something unique
to your application for what that session is all about.
You're going to create your session.
You're going to pass that configuration in, you're going
to pass in a delegate, this will be whatever object you want
to get information back about those downloads.
And you're going to give the queue,
this operation queue is actually what's going
to call into your delegate.
What thread or what operation queue is going
to call into your delegate.
So you're going to want to make sure you create a dedicated
operation queue for that.
And then to kick off the downloads, you create a task
and you hand in the request and URL associated
with you in-app purchase.
And you call resume.
That will kick off
in the background your self-hosted in-app
As the download is occurring your delegate is going
to get information, it's going to get called
into URL session didWriteData.
And that will give you the ability,
you can take this information coming in
and it will give you the ability to update UI.
You might have a progress bar, or something that you want
to tell the user about how your downloads are going.
But it's also important to keep in mind
that your application may be exited during the
And so when your application is re-launched,
you want to actually reattach
to those background download sessions.
And so in your application delegate, you're going to want
to implement handle events for background URL session.
This will allow the operating system to wake
up your application and tell it
about hey this background download just completed,
or is in progress, or something's going on with that.
So handle events for background URL session.
It will pass in the identifier for that configuration
that you used earlier.
You just recreate
that configuration with that identifier.
Re-create a session that will re-attach
to that background session.
And then what you want to do is there's a completion handle
that's passed into that app delegate method and you're going
to need to call that completion handler once you're done doing
whatever you need to do with that download.
So if the download's complete and you need to move it
into your container, and unpack it, and do work,
you need to call that completion handler once you've done
everything with it and let the OS know
that you're done doing what you need to do.
So that's making assets available,
but you're not quite done yet.
Even though you've made all this available
and the user has what they bought,
you've got to do one more thing and you've got to tell StoreKit
that hey you're done with the transaction.
This is important because we keep that transaction
in our purchasing queue, we keep that in our state machine
and if your application dies and gets relaunched
or if the user leaves and comes back, the Payment Queue is going
to keep telling you about it.
It actually might continue to do it
on your behalf background API calls, so that's going
to use up user's data.
So it's important to keep things clean and finish
up the transaction when you're done.
But you should also make sure that you do it
when the content is finished downloading.
If you finish the transaction and then kickoff the download,
we're not going to tell you
about that transaction ever again.
So if the download fails, or if something goes wrong,
you're not going to get updates on it.
So you want to make sure that the download is complete
and then call finish transaction.
So, again, the payment will stay
in the queue until you finish it.
And if you're downloading hosted content, another thing to keep
in mind is yes you need to finish downloading it
and if you finish the transaction before the
download's complete we will stop downloading.
And this can be done simply by calling SKPayment Queue,
Finish Transaction and passing in that transaction right
into the Payment Queue.
So, the user has been using your app,
they've been buying in-app purchases,
they love your content, and they decide,
you know what I'm running out of space,
I'm going to delete the app, maybe I'll re-download it later.
Or they switch to a different device.
It's always important that they can get back those
non-consumable and auto-renewing in-app purchases right back
into the app.
They need to be able to restore that content.
So restoring transactions allow the user
to restores non-consumable and auto renewing subscriptions.
Consumable and non-renewing subscriptions,
that's up to you to manage the state.
So it might be something that you just save locally,
it might be something that you store in the Cloud, or you store
in your own hosted backend.
That's up to you guys to manage how exactly you want
to restore those, but for non-consumable
and auto renewing, you can restore those using the
Again, we offer APIs for that SKPayment Queue Restore
That will pull down a brand new updated version of the app
and in-app purchase receipt.
Again, you're going to want to observe the queue.
You added that to your app delegate,
so of course you're observing the queue.
You're getting information
about those transactions as they're coming in.
Because we're going to call Payment Queue Restored Completed
That's going to tell you all the restores that occurred
and you're just going to want to process those
as if they were just purchased by the user.
Or we're going to give you an error that something went wrong
and maybe you need to ask the user to try it again,
or update your UI accordingly.
So again, it's important to observe the queue.
Again, once the restore is completed, you take a look
at the receipt and unlock content
and features accordingly.
So now we're going to get into a little bit
of okay you're built your app, you're ready to submit it
to the App Store you want to make sure
that you pass app review.
A couple things to keep in mind.
We've just been talking about restoring.
You really need to have a restore mechanism.
It doesn't have to be a UI button,
you need to have some mechanism inside the app to allow the user
to get their content back, or else it won't pass app review.
Again, for non-consumable and auto renewing subscriptions,
you're not going to get other types
of in-app purchases back on restores.
One thing to keep in mind though is we want to keep this separate
from purchases itself.
Restores are free.
The user shouldn't get confused that if they do a restore
and they're getting a password prompt from the App Store
that it's going to cost them anything.
This has got to be very obvious inside your application
that this restore operation they're doing is not a purchase,
it's completely separate from that.
So it's one thing you want to make sure your UI reflects.
Some other information you want to keep in mind
for auto renewable subscriptions are about policies,
keeping the information in marketing text.
And making sure that once they've subscribed that they get
that content right then and there, that they don't have
to wait until the next period begins for anything to appear.
If you subscribe you should get some information right away.
And you should get the information
that you should only be able to get through a subscription,
not bundled products or content that they would have been able
to get free elsewhere.
So, these are some of the kind of policies.
I highly recommend that you check
out the App Review Policy Guidelines.
I've heard there's even a comic book version of that now,
so I would highly recommend you learn all about these,
because they're changing all the time and you really should keep
up to date with what's going on with that.
And with non-renewing subscriptions there's some other
policies you want to keep in mind, about privacy
and making sure that he user has the ability to opt in
or opt out accordingly.
And then finally the most important thing
to pass app review is
if you have purchases inside your app they should work.
You make the purchase, the content should appear.
They should get that information, they should get
that content right then and there.
If it's buggy or if it's error prone,
or if there's something going
on when the reviewer you know is reviewing it inside
that app review environment, you're going to have issues
with app review right then and there.
So test it.
Test it in Sandbox, make sure everything works
as you want it to.
So just to summarize a little bit of what we went over today.
Always observe the Payment Queue.
I can't stress this enough.
If you're interacting with in-app purchases in your app,
one of the first things your app should do is set a Payment Queue
observer to get information
about what's going on with the payments.
You need to fetch localized product information
from the App Store.
This is through an SKProduct request.
That will return localized information.
So the information for the users in their country related
to billing that's associated with their App Store account.
And again use the product's price locale.
There's the SKProduct that comes back, has a locale associated
with that, you need to use that for displaying the pricing
and currency information.
Use the receipt to validate your purchases.
Again, they're your purchases, this is your business.
You need to make decisions about how best
to validate the receipt, whether you do it locally
or on the server.
What technologies that back it.
Be aware exactly what the pros and cons of each are
and make your decisions with that.
And finally make the content available.
You can just unlock it in your app right there on the device,
or you can make a hosted request from the App Store itself,
or you can make a request to your backend hosting APIs.
Make that content available.
But do it in a reliable and quick way.
If you're hosting it yourself,
make sure your servers are scalable
and you know cache appropriately and are, you know, really ready
for users making great use of your app.
And then finally, always finish the transaction.
The last thing you need to do is make sure
that that transaction is no longer in the Payment Queue
or else your observer is going to continually be notified
about it when your app starts up.
And that will incur weird you know possibly the user might
have to authenticate at certain times,
or there might be backend APIs that are occurring on behalf
of your app, using up data for the user
if you don't finish that transaction.
So always do that.
And then, allow users to restore completed transactions.
You need to have a restore mechanism inside your app,
if you have non-consumable or auto renewing subscriptions.
This will allow the user
to get back what they've already purchased.
More information will be online at the developer website.
I highly recommend you go back
and take a look at that later on.
And then a couple related sessions we mentioned today,
if you're using subscriptions in your app,
you should definitely check
out Introducing Expanded Subscriptions
in iTunes Connect later today.
Or if you're interested in on-demand resources check
that out Thursday morning.
And that's it.
Thanks a lot.
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.