v1.71.0
Fixed
-
expoIapProductProviderwas broken against expo-iap 5.x — every product
silently failed to resolve. Five separate API mismatches, none of which any
test exercised (the only existing coverage asserted that the adapter fails
politely when expo-iap is absent):getProducts(skus)no longer exists in expo-iap 5.x; it is
fetchProducts({ skus, type }), an object argument. The old call threw
M.getProducts is not a function. The legacy name is still used as a
fallback so a host pinned to expo-iap ≤4 keeps working.initConnection()was never called. Nothing opens the store connection
implicitly —useIAPdoes it for hook consumers, but an adapter is not a
hook — so every query failed. Now opened once per provider and cleared on
failure, so a first call during a network outage does not poison the
provider for the rest of the session.periodIsowas alwaysnull, because expo-iap 5.x publishes no
subscriptionPeriodISO: iOS splits it intosubscriptionPeriodUnitIOS+
subscriptionPeriodNumberIOS, and Android buries it in the first pricing
phase of the first subscription offer. This was the most damaging one —
deriveProductFieldscomputespricePerDay/pricePerWeek/
pricePerMonth/pricePerYearandsavingsPctfromperiodIsoalone, so
a null did not degrade them, it removed them, and an unknown variable
interpolates to EMPTY rather than to a literal. A per-week-framed paywall
silently lost its headline number.requestPurchasewas sent the wrong shape. 5.x wants
{ request: { ios, android }, type }; the old flat{ request: { sku } }
reached neither platform branch, so StoreKit received an undefined sku.
type("in-app"/"subs") is now derived from the store product.finishTransactionwas never called, so StoreKit re-delivered every
transaction on each launch.
Changed
expoIapProductProvider.purchase()resolves"pending"where it used to
resolve"purchased", whenrequestPurchaseresolvesnull— which is the
normal expo-iap 5.x outcome, because the transaction is delivered to
purchaseUpdatedListenerinstead. Reporting"purchased"there granted
access for a purchase that had not completed and might still fail. Hosts whose
buy button relies ononSuccessfiring on this path must declareonPending
(added below) — that is what it is for.
Added
onPending?: ButtonAction[]onPurchaseButtonAction(type + schema), mirroring
@rocapine/react-native-onboarding-ui's dispatcher. A"pending"result is
unconfirmed, not successful — a Stripe Payment Link purchase always resolves it,
and so now does an expo-iap purchase awaiting its listener.