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.productIdentifierSKPayment.productIdentifierSKPaymentTransaction.paymentwhich gives youSKPaymentfrom where you can get theproductIdentifierCustom data
Can you assign a custom data to a transaction? No. There's just the
applicationUsernameyou 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
productIdentifierwhich 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
productIdentifierand 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
productIdentifierPros:
Cons:
productIdentifiers can grow a lot, especially if you have a lot of characters, they do differ for each user, etc.Consumable
StoreKitPros:
productIdentifiersCons:
StoreKitis on youStoreKitacts as any other payment gateway for you