Handling a crash between addPayment and finishTransaction

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?

Answered by gormster_ in 712179022

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.)

Accepted Answer

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.)

Handling a crash between addPayment and finishTransaction
 
 
Q