ARTICLE AD BOX
I am currently developing an app using Swift.
The product is a non-consumable (one-time purchase), and in-app purchase testing is being conducted via TestFlight.
Some testers downloaded the app using a public TestFlight link and are performing purchase tests with their personal Apple IDs, without using dedicated sandbox test accounts. (These purchases are still processed as test transactions, not real charges.)
The problem is that after a purchase is completed, transaction.finish() does not work in the .verified state.
When the app launches, I check unfinished transactions using Transaction.unfinished. The transaction is detected in the switch statement under .verified, and I call transaction.finish() at that point.
However, after closing and relaunching the app, the same transaction is detected again when iterating over Transaction.unfinished.
In fact, there are no code differences compared to the previously released production version, but in TestFlight purchase testing, transaction.finish() does not seem to complete properly.
Because of this issue:
When attempting to purchase the same product again, the product purchase sheet sometimes does not appear, or
After deleting and reinstalling the app, the product is treated as already purchased and restored.
I have read that behavior may differ in the production environment, but I would like to know how this should be fixed or handled properly.
my simple code
public func buyProduct(_ product: Product){ Task { do{ let result = try await product.purchase() switch result{ case .success(let verification): switch verification{ case .verified(let transaction): await handleTransaction(transaction) await transaction.finish() case .unverified(_, let error): } case .userCancelled: case .pending: @unknown default: } }catch{ print("purchase failed: \(error.localizedDescription)") } } } public func checkedTransaction(){ for await result in Transaction.unfinished { switch result { case .verified(let transaction): awaiat transaction.finish() case .unverified(_, let error): } } }