Skip to content

2.8.0 - #447

Open
ianrumac wants to merge 28 commits into
mainfrom
develop
Open

2.8.0#447
ianrumac wants to merge 28 commits into
mainfrom
develop

Conversation

@ianrumac

Copy link
Copy Markdown
Collaborator

2.8.0

Enhancements

  • Updates Google Play Billing Library from 8.0.0 to 9.1.0. See the Play Billing Library 9 migration guide for the full list of changes.
  • Updates the RevenueCat SDK used by the sample apps from 9.2.0 to 10.14.1 for Billing 9 compatibility.
  • Adds support for custom store products. Products configured on a custom store in the Superwall dashboard (e.g. Stripe or your own payment backend) can now be attached to paywalls: their metadata (price, subscription period, trial) is fetched from the Superwall API instead of Google Play and templated into the paywall like any other product. Purchases are routed through your PurchaseController, bypassing Google Play Billing entirely — check product.isCustomProduct to fulfill them via your own payment flow, and grant their entitlements with Superwall.instance.setSubscriptionStatus(...) on success. Requires configuring the SDK with a PurchaseController.
  • Adds a unified PurchaseController.purchase(activity, product: StoreProduct, basePlanId, offerId) method that handles both Google Play and custom store products. For Play products, the underlying ProductDetails are available via product.rawStoreProduct.
  • Custom purchases produce full transaction analytics (transaction_start/transaction_complete, subscriptionStart/freeTrialStart) with an SDK-generated transaction identifier exposed as StoreProduct.customTransactionId, and free-trial eligibility for custom products is derived from the customer's entitlement history.
  • Renames TestStoreProduct to ApiStoreProduct, now shared between test mode and custom store products.

Breaking Changes

  • Removes the deprecated SuperwallBillingFlowParams.Builder.setSkuDetails(SkuDetails). Billing Library 9 removes SkuDetails entirely, so this method can no longer exist. Use setProductDetailsParamsList(...) with ProductDetails instead.
  • Removes the unused internal com.superwall.sdk.billing.SWProduct, which wrapped the now-removed SkuDetails.
  • Internal purchase-history queries now resolve current purchases via QueryPurchasesParams — Billing Library 9 removes the purchase-history APIs (queryPurchaseHistoryAsync, QueryPurchaseHistoryParams).
  • Impact: if your app still calls the removed Billing Library APIs (SkuDetails, SkuDetailsParams, querySkuDetailsAsync, queryPurchaseHistoryAsync, BillingClient.SkuType, or the no-arg enablePendingPurchases()), it will no longer compile once it picks up Billing 9 through this SDK. Migrate those call sites to the ProductDetails APIs before upgrading; the migration guide has a mapping of every removed API to its replacement.
  • Please test your billing and purchasing flows before shipping this upgrade. Because the Billing Library is resolved to a single version across your app, upgrading Superwall also upgrades Billing for everything else that depends on it. If you use Google Play Billing directly, or another subscription provider such as RevenueCat, Adapty or Qonversion, make sure that provider's SDK supports Billing 9 and run through purchase, restore and subscription-status flows end to end.

⚠️ Minimum SDK version raised to 23

Google Play Billing Library 9 requires Android 6.0 (API 23), so the SDK's minSdk is now 23 (previously 21). If your app's minSdk is below 23, you'll need to raise it to pick up this release — devices on Android 5.x will no longer receive app updates that include this SDK version.

Deprecations

  • Deprecates PurchaseController.purchase(activity, productDetails, basePlanId, offerId) in favor of the StoreProduct-based method above. Existing implementations keep working unchanged — the new method's default implementation routes Google Play purchases to the deprecated one — but purchasing custom store products requires implementing the new method.

ianrumac and others added 25 commits July 24, 2026 15:15
Bumps the billing client from 8.0.0 to 9.1.0 and RevenueCat (test app) to
10.14.1.

Billing 9 removes the SkuDetails APIs, so this drops the deprecated
SuperwallBillingFlowParams.Builder.setSkuDetails and the unused internal
SWProduct wrapper, and switches buildQueryPurchaseHistoryParams over to
QueryPurchasesParams.

See https://developer.android.com/google/play/billing/migrate-gpblv9
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add custom store products, new purchase controller method
Update Google Play Billing Library to 9.1.0
…input

When reroute_back_button is enabled in Paywall settings, a system back
press previously did nothing unless the host app set the
PaywallOptions.onBackPressed callback — otherwise the paywall dismissed
as if the setting were off.

Back presses the app callback doesn't consume are now injected into the
webview as the paywall-js back_button_input message. The paywall either
navigates its flow back one page or posts the existing close message,
which dismisses through the standard manual-close path (Declined /
ManualClose), so back-at-root behaves exactly like a native dismissal.

The press/consume decision is extracted into backPressBehavior() and
unit tested; the JS bridge payload is covered in PaywallViewTest.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vi3SWn6yXT5kTBj7NEb3m
…lity probe

Multi-page flow paywalls were closing entirely on system back instead of
navigating back a page. Forwarding is now the default for every paywall,
not just those with reroute_back_button enabled — that setting now only
controls whether the PaywallOptions.onBackPressed app callback gets
first refusal.

Because published paywalls pin their built runtime, blindly forwarding
would strand users on paywalls whose runtime lacks the back_button_input
consumer. The SDK therefore probes the webview for
window.paywall.supportsBackButtonInput first; when absent (older
runtime, still loading, crashed webview) it falls back to the native
dismiss, preserving today's behavior exactly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vi3SWn6yXT5kTBj7NEb3m
…is ENABLED

Forwarding by default changes implied behavior for existing multi-page
paywalls, so gate it behind the existing per-paywall dashboard setting
while the default story is decided (possibly a new setting). DISABLED
and unset paywalls dismiss on back exactly as before. The capability
probe stays: even ENABLED paywalls on older runtimes keep the native
dismiss.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vi3SWn6yXT5kTBj7NEb3m
Team decision: this ships as an accepted breaking change. Every system
back press the app callback doesn't consume is forwarded into the
paywall as back_button_input — the paywall navigates its flow back one
page or posts close (Declined/ManualClose) at the root. The
reroute_back_button setting now only controls whether the
PaywallOptions.onBackPressed callback is consulted first. Native
dismissal remains only when no PaywallView is attached to the activity.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vi3SWn6yXT5kTBj7NEb3m
The message's arrival is the signal — only presses are ever sent, so
the boolean carried no information. Matches the simplified paywall-js
schema.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vi3SWn6yXT5kTBj7NEb3m
The Unreleased section this entry was written under became 2.7.23 on
develop; the change ships with 2.8.0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vi3SWn6yXT5kTBj7NEb3m
Adds PaywallMessage.BackButtonPressed and handles it via the standard
pass()/accept64 pipeline instead of a hand-rolled evaluate in
PaywallView, reusing the established main-thread dispatch, error
logging, and encoding. Removes BackButtonInputEvent and reverts the
gameControllerJson rename it motivated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vi3SWn6yXT5kTBj7NEb3m
Forward system back presses into the paywall as `back_button_input`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants