I have an app with several entities per user. User can do IAP for each entity. When I'm adding the payment to the SKPaymentQueue, I know to what entity the purchase is done for.
How can I get this info from the updatedTransactions
callback?
I've tried to match transaction identifier from purchasing transaction with transaction identifier in purchased transaction, but this value exist only in purchased transaction.
I've tried to use applicationUsername:
func buyProduct(_ product: SKProduct) {
let payment = SKMutablePayment(product: product)
payment.applicationUsername = "character ID"
SKPaymentQueue.default().add(payment)
}
But the docs mention its unreliable and only used for fraud detection.
It works most of the time, but Apple do not guarantee to return this in the callback transaction.
Product types
There're four product types you can offer:
Let's skip subscriptions here and focus on (Non-)consumables. What's the difference?
Identifiers
Every product has a unique identifier (
productIdentifier
). It's accessible from everywhere:SKProduct.productIdentifier
SKPayment.productIdentifier
SKPaymentTransaction.payment
which gives youSKPayment
from where you can get theproductIdentifier
Custom data
Can you assign a custom data to a transaction? No. There's just the
applicationUsername
you mentioned. But it has flaws like:You can't use it for custom data. And even if you try to abuse it it's still of no use, because it's not guaranteed to persist.
Buy non-consumable
This is the easy part as it allows the user to buy it just once. You have the
productIdentifier
which is available all over the place and then you can unlock features, download content, ...But it clearly isn't what you want. Anyway, you can achieve what you want in this way as well, but you have to create a unique product for every entity and entity & user combination. Which can lead to a millions of product identifiers. I can imagine that this will be a maintenance nightmare.
Buy consumable
This part is trickier, because you, as an app developer, are responsible for:
In other words - consumable behaves like any other payment gateway (Stripe, ...) - you know that user paid you for specific
productIdentifier
and that's it - everything else has to be handled in your application, on your server, ...An example
Imagine you have a game where user can buy a new game character. There're two ways how to achieve this.
Non-consumable
productIdentifier
Pros:
Cons:
productIdentifier
s can grow a lot, especially if you have a lot of characters, they do differ for each user, etc.Consumable
StoreKit
Pros:
productIdentifier
sCons:
StoreKit
is on youStoreKit
acts as any other payment gateway for you