G'day folks,
I had a bug the other day in my receipt verification code, which caused a crash. Fixed the bug, but since it was caused ultimately by an unexpected response from the backend, I thought "I should probably handle this edge case".
The obvious solution is to persist the transaction state while we're processing it, before calling finishTransaction and marking it as complete. The docs for finishTransaction hint at this being good practice.
However, I hit a brick wall when it came to actually finishing the transaction after a crash. SKPaymentTransaction
doesn't conform to Codable
or NSSecureCoding
. There's no constructor for it. I thought I might be handed the transaction again through paymentQueue(_:updatedTransactions:)
, as would happen if the call to finishTransaction
failed, but that doesn't happen. Restoring purchases doesn't work either, as this is a consumable IAP and doesn't show up there.
Here's the thing: I don't even know what happens if you never call finishTransaction
. Presumably, at some point, the user is refunded? There must be a time limit. I don't know, since I'm in the sandbox environment and I can't even see the transactions on my account, much less whether or not I'm getting refunded. (That makes debugging this super difficult, by the way. Is there a way around that? Some way to say "yes, this sandbox user's fake account was charged this much fake money"?)
Is there some way to prod StoreKit into handing over any unfinished transactions? What's the best practice here?
Ok, never mind – I'm not sure what was going on with my device, but it turns out you are delivered unfinished transactions on startup. The device I was using to test did an overnight OS update, so maybe there was an iOS bug that got squashed? Not sure.
In any case, if you're wondering how to best handle this… yeah, follow the documentation. Keep track of what you've done (persistently!) and call finishTransaction
when everything's complete.
(Actually, just in case you're still having this same bug and you're in precisely the same situation I was in – Plugin.InAppBilling
has a number of critical bugs for iOS consumables, which I've raised in issue #466 on their GitHub. Try it again with a fresh Xcode project in Swift or Objc. This didn't fix my problem, but it did allow me to figure out that the plugin was bugged when suddenly the test Xcode project started working.)