source: https://developer.apple.com/in-app-purchase/

Digesting In-App-Purchasing APIs

Sergey Rudenko
The Startup
Published in
9 min readAug 20, 2020

--

This article will help you get understanding of how purchasing works with Apple/Google’s In App Purchase SDKs/APIs.

There are plenty of articles about technical integration with In-App-Purchasing (Apple) / In-App-Billing (Google) APIs for mobile applications, but there is a lack of explanation for why these APIs are built the way they are which is super helpful to understand when you actually perform the integration. This article will hopefully help explain the logic behind In-App-Purchasing as it is designed by major platforms and will serve as a good introduction for somebody who is just starting on the monetization journey for their mobile apps.

Purchasing as a concept

When it comes to “purchasing” something, it is a good idea to think about it through the following simple and generic user journeys:

  • User can browse through offers for items they can buy (“list of offers”)
  • User can purchase such offers (“purchase item”)
  • User can receive the goods they just bought (“fulfill item”)
  • User can refund their purchase (“refund”)

In our physical world the concept of “purchasing” is easier to understand mostly because after the item is purchased and delivered (fulfilled) to us — we “own” it, meaning we actually possess it (like it sits in our house somewhere for example) and there is no further need to prove to somebody that we actually own it and we are free to use it however we want (subject to warranty, etc).

In the digital world (such as mobile applications or games) however, the fact of ownership has to be recorded somewhere and this record has to be used to check if the user in fact is “entitled” to use purchased items in such an application or a game.

Keeping such a record client-side is not safe — the client can lose it, it can get corrupted or even forged — so in most cases entitlements should be securely stored server-side and queried by clients and other services as needed.

So the purchasing flow in mobile applications in most cases would mean:

Typical purchasing flow in an App or a Game
  • User can browse through offers for items they can buy (“list of offers”)
  • User can purchase such offers (“purchase an item (offer)”)
  • User can receive the goods they just bought (“fulfill item”)
  • User can use the purchased item (“entitlement”)
  • User can refund their purchase (“refund”)

The above means that the digital world is a bit more “advanced” in that it has to keep a good track of our digital purchases via “Entitlements” and use those as flags to allow the use of otherwise “locked” content or functionality.

Now Let’s zoom into this flow through the lens of Apple/Google’s in app purchasing APIs to understand them better.

Offers (== “In-App-Products”)

Just like when we walk through a grocery store and see Items on the shelves with Prices / Discounts etc information attached to them (we call them “Offers”) we have the same concept in the digital world. The seller typically wants to have tight control over the Offers (what price is set for a given item, what discount applied under which conditions, limited time availability etc) hence both Apple and Google require any developer to register their Items for sale as well as key offer metadata (such as Price) on their server-side since in this case they are the “seller” that takes real money from real users.

Here is how developer registers their “Offers” with both platforms:

Apple’s App Store:

Configure “Offers” (In-App-Products) inside App Store Connect

Google Play:

Surely ability to define the Offers (~“In-App-Products”) requires you to have proper developer agreement with the platforms, the actual application that was submitted to the relevant store (all these steps are outside of the scope of this article), but the main point here is that the “In-App-Products” conceptually are just the Offers for items that your user could eventually see and purchase inside of your application.

So why not allow developers to have their offers hosted elsewhere? The reason for that is that when it comes to Purchasing the platform (Apple or Google) wants to make 100% guarantee that what the user sees as an Offer actually is what they are going to be charged for and what they will receive. So basically both Apple and Google want to “host” Offers information on their side for consistency and to avoid issues for users paying for something different than what was shown in the Offer (“In-App-Product”).

Its worth to mention that In-App-Products also feature differentiation based on type of a thing users will be buying:

Apple’s Offer types:

  • Subscriptions— time based offer for access to content (can be auto renewable)
  • Consumables — offer for items that need to be consumed after purchasing
  • Non-consumables — offer for items that are unique and can be purchased only once

Google’s Offer types:

  • Managed Product (Consumables and Non-Consumables)— offers for all items that are not subscription basically, one-time purchases.
  • Subscriptions — same as with Apple — time based access to content

This is done mostly to accommodate the way purchasing and validation of purchase (checking Entitlement) works for these different in nature items: subscriptions assume recurring charges for example, while consumables represent “stackable” items that a user can have a number of.

Once developer setup all of the In-App-Products — they are advised to pull the list of registered and available Offers in their apps to display them for the user:

Google: https://developers.google.com/android-publisher/api-ref/rest/v3/inappproducts/list

Apple: https://developer.apple.com/documentation/storekit/in-app_purchase/fetching_product_information_from_the_app_store

Apple here is a bit different in the approach to retrieve Offers as it requires In-App-Product’s ids to query for their availability. This means the developer has either to “hard code” those IAP IDs in their application bundle (if the offers are static) or to retrieve them from developer’s service, then use those IDs requesting Apple service to confirm they are valid for purchasing.

Purchasing (==Paying)

Purchasing is the most sensitive and crucial part of the overall flow. This is where the Platforms (Apple/Google) provide a lot of value to developers by abstracting the necessity to deal with region specific Payment instruments, fraud checks, local tax, audit etc. To ensure proper and secure purchasing process both Platforms have the integration guidance that drills down to the following:

  • the application has to ensure the Offer to be purchased is valid (as long as it is retrieved from Apple/Google’s platform as valid— it can be purchased)
  • the application needs to call native SDK specific method such as ~purchaseProduct(ProductID) (Apple uses a PaymentQueue for example) and then start “listening” for status changes of this particular purchase while user is going through the payments flow governed by the platform
  • finally when status of a purchase (payment) changes — the application should react accordingly: in case of errors or issues — warn the user, in case of successful payment — inform the user of the further processing step, which is…the fulfillment.

Fulfillment (==Unlocking)

“Delivering the product” might sound a bit strange for a digital environment since we do not really have a delivery truck shipping product to our user. But the process of fulfillment here is both important and nuanced.

Successful purchase (payment) by this stage only means that the user did their part of the exchange — got their money committed to buy the Offer (In-App-Product), now it is up to the developer to ensure the transaction can be completed since at this point it is only the application client-side that is aware of the successful purchase step.

This is what needs to happen next:

  1. Developer needs to validate that the user (client) claim that they purchased something is legit. For that both platforms implemented client side and server side approaches to “validate the receipt” (Apple, Google). So just like in a real store where items get shipped to you afterwards the delivery person wants to double check your receipt.
  2. Once such validation is completed the developer is expected to “fulfill” the purchased item. Fulfillment in case of the digital world is writing a record to some database that says “this specific user has acquired this item and hence should have access to it”. Such record becomes user’s “entitlement” to use this item going forward.
  3. Finally both platforms require the application to confirm that the transaction (including fulfillment) was completed (with a success or failure). This is an important step that concludes each specific transaction preventing situations where a user got charged but never got their item fulfilled or got charged twice.

It is worth noting that what Apple and Google call a “transaction” is not just the fact of user completing the payment step. The transaction is the exchange of user’s money for entitlement to use the item (product). Hence it is important to call “transaction completed” API end point only AFTER you ensured user received the entitlement record. Since writing data is an asynchronous task — this is the stage where a lot of developers get into trouble by doing:

concludeTransaction() {  postEntitlement();  finishTransactionWithApple();};

Instead of:

concludeTransaction() {  postEntitlement().then(success => finishTransactionWithApple())};

Entitlements

So how does entitlement really work to control whether we have access to an item (or a thing) inside an app or a game?

Typically developers implement business logic in their apps and services to “consult” the entitlements service (~call GET /api/v1/entitlements) every time a game or application needs to make a decision that involves the use of locked content. Whether client application goes directly to such a service or indirectly via App Services backend is subject to design decisions of a particular application. But in all cases the above means that Entitlements service has to be highly reliable and available service (API) that clients and backend services can talk to optimized for dominant amount of “reads” (95%+) and some “writes” (< 5%).

Important thing is that entitlements are not just about access control, they typically feature additional details around the context of the purchase made. Such information is vital when it comes to marketing, customer support, and financial audit as it describes the context of why the user has access to a certain digital item (which is also crucial for things like “refunds”).

You can think of entitlements as of purchase receipts that are attached to your user account and can be queried programmatically at any time. In fact, both Apple’s In-App-Purchasing and Google’s In-App-Billing solutions feature a “recover purchases” functionality for those developers that lack their own backend that tracks entitlements thus such purchase history end-points could be used to recover entitlements status for a given user.

Refunds

Finally if a user was not happy with their purchase and wants to get their refund the digital world starts to adapt the legal rules that exist to protect consumers. Unfortunately this is not yet well defined for In-App-Purchases where the refunds are subject to particular platform rules (Google).

For general understanding the Refund is just a reverse of transaction that happened in the past. This underlines why it is super important to keep precise information about context of the purchased offer somewhere safe on the developer’s side.

Summing it all up

So conceptually the Apple/Google’s In-App-Purchase APIs do the following:

  • They host and allow configuration of Offers (In-App-Products)
  • They take care of Payment acquisition for a specific Offer
  • They require developer to perform Receipt Validation and Fulfillment of purchased Entitlement, followed by the conclusion of the Transaction
  • They allow developers to restore context of Purchases made in case something went wrong

While mobile app developers are advised to invest time and effort creating robust and highly available Entitlement services that would keep user’s entitlements records in good standing— as in a way the entitlements are all what those users are getting in exchange for their real money and they expect it to be kept safe.

Here is how the overall flow looks like:

Overall mobile purchase flow

Thank you for reading!

--

--

Sergey Rudenko
The Startup

Tech enthusiast and product leader (Amazon PM Tech, ex Riot Games, ex Microsoft, Nokia), author of something awesome in the future;)