Flutter in_app_purchase on Android: purchase successful (receipt received) but purchaseStream delivers error — verifyIAP never called

7 hours ago 1
ARTICLE AD BOX

We're using in_app_purchase: ^3.2.3 (in_app_purchase_android: 0.4.0+10) on Flutter. On Android, when a user completes a purchase:

Google Play processes it correctly (test receipt email received, order ID generated, "Test card, always approves" shown in sandbox)

The app briefly shows "Purchase didn't complete. If you cancelled, just try again."

The tier remains unchanged

Our backend Cloud Function (verifyIAP) is never invoked — confirmed via GCP logs

On the second attempt: "You already own this item" — confirming Google Play considers the purchase complete but unacknowledged.

Our purchase stream handler:

void _onPurchaseUpdate(List<PurchaseDetails> purchases) { for (final purchase in purchases) { if (purchase.productID != _pendingProductId) { if (purchase.status != PurchaseStatus.pending) { _iap.completePurchase(purchase); } continue; } switch (purchase.status) { case PurchaseStatus.purchased: case PurchaseStatus.restored: _handlePurchased(purchase); case PurchaseStatus.canceled: _iap.completePurchase(purchase); _resolvePending(IAPResult.cancelled); case PurchaseStatus.error: _iap.completePurchase(purchase); _resolvePending(IAPResult.storeError); case PurchaseStatus.pending: break; } } }

The error message "Purchase didn't complete. If you cancelled, just try again." maps to IAPResult.storeError.

Question: On Android, can a completed Google Play purchase arrive on the purchaseStream as PurchaseStatus.error rather than PurchaseStatus.purchased? If so, under what conditions? Or is there another mechanism by which the stream event would be dropped before reaching our handler?

What we've already ruled out:

The didChangeAppLifecycleState cancellation path is guarded with if (Platform.isAndroid) return;

The 30-second timeout did not fire (error appeared quickly)

_pendingProductId mismatch is possible but unclear why it would be null at time of stream delivery

iOS works correctly with the same code

Any and all help highly appreciated! Thanks

Read Entire Article