I am trying to figure out the best way to ensure that a user will not lose their consumable in app purchase.
However, I am starting to feel like this StackOverflow user.
After a complete transaction I want to send to a server that the user bought a consumable in app. However, the connection might fail at that point (the server is down or the user loses connection).
I was considering in that scenario to send the receipt as soon as the connection can be made again. However, from what I have read the receipt contains all in app purchases and I can't send only the receipt for the last bought item.
How can I ensure that the purchase made by the user was synced with the server?
You can install your paid apps on as many of your devices as you like, so long as they are connected to the Google account used to purchase the apps.
It should be noted that server validation isn't mandatory — in-app purchases will still work without it. It grants some advantages, though: Advanced payment analytics, which is especially important for subscriptions since everything that happens after the activation isn't processed by the device.
Consumables are one-shot items, such as ammo, or stickers.
The solution is to not call
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
on the consumable purchase until it has been synced with the server. This way, the transaction will be delivered again to your observer every time it is set to observe the payment queue. You will need manage app side whether it's a purchase that has been delivered but not synced, or a new purchase.
Once you have synced the transaction with the server. You can call -finishTransaction:
. See the "Finishing The Transaction" in the docs here:
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/DeliverProduct.html#//apple_ref/doc/uid/TP40008267-CH5-SW3
EDIT
So the user is charged by Apple, and Apple send you a SKPaymentTransaction
object that represents the transaction. If the transactionState property of that transaction is SKPaymentTransactionStatePurchased
, then it means Apple has processed the payment and the user has been charged.
Once you have received this SKPaymentTransaction
object from the paymentQueue, you deliver the content to the user, and sync the transaction with your server. Once both of those have been successfully completed, you call -finishTransaction
. Calling -finishTransaction
tells StoreKit
that you have successfully completed everything you need to do. -finishTransaction
is a synchronous call, you are handing responsibility back to StoreKit
, and you don't need to concern yourself with how that is communicated back to iTunes/Apple, StoreKit
handles it all for you.
You should not call -finishTransaction
until you have done everything you need to do. If something goes wrong (device battery dies, loss of internet connection, app crash), you will be delivered the same SKPaymentTransaction
from the payment queue next time your observer is registered with the queue, and can try to sync again with your server. This will keep happening until you call -finishTransaction
.
There is a scenario where the user is never able to sync with your server, never connects to internet again etc. That is out of your control, and at that point it is the responsibility of Apple to decide whether they charge the user.
It's also worth noting that the user can contact Apple and request a refund if they wish to.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With