Skip to content

Issue: onPurchaseSuccess returns previous purchase objects and delays correct one during plan upgrade (iOS) #3054

@PavanSomarathne

Description

@PavanSomarathne

Environment

  • Library: react-native-iap ^14.4.12
  • Platform: iOS (Sandbox)
  • React Native: 0.81.4
  • StoreKit: using subscription group with Monthly → Yearly upgrade path
  • Implementation: using useIAP() hook with onPurchaseSuccess and finishTransaction called for every previous purchase

Description

When upgrading from a monthly subscription to a yearly subscription (within the same subscription group), the onPurchaseSuccess callback is triggered with old purchase objects first, and the new purchase transaction takes 3–4 minutes to appear in the callback.

Even though I’m calling:

await finishTransaction({ purchase, isConsumable: false });

for each previous transaction returned, useIAP (or the underlying purchase listener) still emits the previous transaction events multiple times before finally emitting the correct upgraded subscription.


Expected behavior

  • After calling requestPurchase for the upgrade:

    • onPurchaseSuccess should emit only the new transaction (the yearly plan).
    • The callback should trigger promptly (within seconds).
    • Previously finished transactions should not re-emit in the listener.

Actual behavior

  • On upgrade:

    • onPurchaseSuccess emits one or more previous (old plan) transactions again.
    • The correct upgraded transaction event arrives after ~3 minutes delay in Sandbox.
    • All old purchases were already acknowledged with finishTransaction.
    • During this time, getActiveSubscriptions() also shows both old and new plans as active.

Steps to reproduce

  1. Subscribe to a monthly plan (Plan A).
  2. Successfully finish transaction for that purchase.
  3. Upgrade to a yearly plan (Plan B) in the same subscription group.
  4. Observe that onPurchaseSuccess fires with the old monthly purchase first.
  5. Wait ~3 minutes for the new yearly purchase to appear.

Code snippet

const { requestPurchase, finishTransaction, useIAP } = useIAP({
  onPurchaseSuccess: async (purchase) => {
    console.log('PURCHASE EVENT', purchase.productId, purchase.transactionId);
    await finishTransaction({ purchase, isConsumable: false });
  },
  onPurchaseError: (err) => console.log('ERROR', err),
});

Notes

  • Verified that all previous transactions are finished immediately after validation.
  • Occurs only when upgrading (not on first purchase or downgrade).
  • Sandbox latency observed consistently (2–3 mins).
  • Appears that StoreKit re-emits prior transactions before new one is processed.

Originally posted by @PavanSomarathne in #3052

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions