Generic In-app purchases for multiple contents

We want to allow the enduser to purchase movies from our VOD app using in-app purchases (IAP). Since our app exposes thousands of movies, we plan to create several generic consumable IAP products, one by price tier (according to the expected selling prices). Each productId can be used to buy different movies.

Once a purchase is successful (transaction in purchased state), our app needs to send the transaction id and receipt along with the movie id to our back-office in order to perform checks and eventually mark this specific movie as purchased for this user (our app being multi-platform, the purchased movies have to be available on all platforms, whatever the platform used for the purchase).

But since the purchase is solely based on the SKProduct (hence its id), and since there's no way to attach some kind of userInfo to the SKPayment added to the default SKPayementQueue, there's no direct way to match an SKPaymentTransaction to the movie whose purchase triggered its creation, especially when dealing with "Ask to Buy" and highly asynchronous transactions updates.

So, as far as I know, I have to maintain some sort of permanent context with the movie id, the product id and the last update date in order to try to get the movie id matching a transaction. But there are lots of things to take care of and a high risk maintaining this parallel context synced with the SKPaymentQueue pending transactions.

I am pretty sure other apps have the same IAP strategy so I wonder if I'm missing something obvious. Are there some recommendations from Apple on the way to handle it? Or has anyone been through this road and being able to provide advices?

Thanks for your help,
Aurélien.
Post not yet marked as solved Up vote post of patatrouf Down vote post of patatrouf
2.1k views

Replies

Hi. I'm having the exact same issue.
The common, and only suggestion, seems to be to use "credits" like a digital currency. I don't like this idea since my app is not a game.

I went down the road of "permanent context" you are describing, and trying to "assume" that the ID of the item is the one that user last clicked buy on.

As you know, the risk here is that link is easy to lose, Apple recommends app needs to be able to process a purchase at any given time, by registering observer on launch, but I can't do it because I don't have itemId to match then.

Please let me know if you have found a solution.

I am trying to understand nuances of exactly the same issue as M-S with a digital currency being used to buy assets such as card templates.

The good news from a design is that, from conversations with users and Apple employees, most people are fine with the idea of a digital currency for such in a non-game context.

Technically, I'm still confused and think there are some missing pieces. Assuming your currency is a consumable, because that's the only IAP model that makes sense for topping up a balance:

The App Store Review Guidelines says:

3.1 Payments ... 3.1.1 In-App Purchase: Any credits or in-game currencies purchased via in-app purchase may not expire, and you should make sure you have a restore mechanism for any restorable in-app purchases.

3.1.2 Subscriptions … 3.1.2(a) Permissible uses: Subscriptions may include consumable credits, gems, in-game currencies

We seem to have an obligation but no supported method or helper tools.

Apple feedback 2022-12

The official word from Ross L at Apple via the Q&A on Slack yesterday was Consumable in-app purchases are not restorable via StoreKit. However, you do need to make sure you permanently keep track of the user’s balance for this consumable currency.

and then

One option that many developers choose is to offer an in-app account, and store all this data on their own server.

When I pushed for how

There isn't any list of specifically accepted paradigms, but as long as you properly investigate and test your solution and it allows users to access their currency without losing it, it should be good.

My intention

  1. Generate a local UUID on the app
  2. Use appAccountToken (iOS15 on) so the UUID can be associated with all purchases
  3. Persist the UUID and the currency balance using NSUbiquitousKeyValueStore so it's shared amongst devices and will be restored if they setup a new device.
  4. On our marketplace server, store a list of purchases associated with that UUID so they can be restored if necessary. This mirrors the behaviour of IAP being restorable items but we have to use our own approach rather than just IAP items because:
    1. we intend to have vastly more items available than the IAP limits
    2. using digital currency allows for micropayments and more granularity on pricing than IAP levels
    3. our rights system allows for items to be reusable with or without payment depending on the rules set per-item by the artists.