Apple IAP breaks if user cancels transaction

FYI, we are using the “newer” Apple IAP plugin: https://docs.coronalabs.com/plugin/apple-iap/

If a user attempts to purchase an IAP (in our case a subscription) but then cancels, the transaction seems to get stuck in the queue forever. Our transactionHandler sees the cancel and displays a message to the end user, and then calls finishTransaction. However if the user goes back to buy the same item, the user sees nothing. They are never prompted to complete. And the transactionHandler sees the EXACT same transaction come back, with a state of “cancelled” and even the exact same transaction identifier.

How are we supposed to be handling a cancelled transaction? Has anyone else been seeing this behavior?

@kbradford I had a similar problem; this occurs when a transaction isn’t finished, so make sure, for iOS, to do store.finishTransaction(transaction)

One more thing; if you are testing this on a device where the finishTransaction didn’t run, you’ll be stuck in that loop unable to make a purchase. To resolve this, create a special build and make sure to restore and consume all purchases.

Thanks for the response. We already call finishTransaction on every transaction, whether successful, restored, failed or cancelled.

I’m not quite sure how I would implement what you describe to fix production users. We also have no consumable purchases.

Well after some debugging we DO call finishTransaction after every transaction, but we’ve been passing it nil. A change to the code we made a few months ago does a check for event.transaction, but adding that if statement pushed our transaction variable out of scope of where we can finish. Sigh, such a simple mistake.

What’s interesting is purchases still work 95% of the time. What I think this breaks is edge cases like users cancelling, a user not having valid payment, etc.

@kbradford - yes, you are right about when the user cancels before the finishTransaction can occur. When that happens, that device will forever be unable to create a new purchase because Apple thinks they already purchased it. This is why calling ‘restore’ is important on iOS.