PurchaseController

An interface for handling Superwall's subscription-related logic with your own purchase implementation.

This interface is not required. By default, Superwall handles all subscription-related logic automatically using Google Play Billing.

When implementing PurchaseController, you must manually update subscriptionStatus whenever the user's entitlements change.

Purpose

Use this interface only if you want complete control over purchase handling, such as when using RevenueCat or other third-party purchase frameworks.

Signature

interface PurchaseController {
    suspend fun purchase(
        activity: Activity,
        product: StoreProduct,
        basePlanId: String?,
        offerId: String?
    ): PurchaseResult
    
    suspend fun restorePurchases(): RestorationResult
}
// Java uses the callback-based PurchaseControllerJava interface.
public interface PurchaseControllerJava {
    void purchase(
        ProductDetails productDetails,
        String basePlanId,
        String offerId,
        kotlin.jvm.functions.Function1<? super PurchaseResult, kotlin.Unit> completion
    );

    void restorePurchases(
        kotlin.jvm.functions.Function2<? super RestorationResult, ? super Throwable, kotlin.Unit> completion
    );
}

Starting in 2.8.0, Kotlin's PurchaseController.purchase() receives a StoreProduct (instead of the Billing Library's ProductDetails), which also supports custom store products. For Google Play products, access the underlying ProductDetails through product.rawStoreProduct?.underlyingProductDetails. The default implementation of this method routes Google Play products to the older purchase(activity, productDetails, basePlanId, offerId) overload, so existing implementations of that overload keep working unchanged. That older overload is now deprecated; implement the StoreProduct-based method above going forward, and implement it directly if you need to support custom store products.

PurchaseControllerJava remains a callback-based API that receives ProductDetails. It does not support custom store products.

Parameters

Prop

Type

Returns / State

  • purchase() returns a PurchaseResult (.Purchased(), .Failed(errorMessage: String), .Cancelled(), or .Pending())
  • restorePurchases() returns a RestorationResult (.Restored() or .Failed(Throwable?))

When using a PurchaseController, you must also manage subscriptionStatus yourself.

Custom store products

Products configured on a custom store in the Superwall dashboard (e.g. Stripe or your own payment backend) can be attached to paywalls. Their metadata (price, subscription period, trial) is fetched from the Superwall API instead of Google Play, and purchases for them are routed through your PurchaseController, bypassing Google Play Billing entirely.

  • Kotlin PurchaseController implementations can check product.isCustomProduct in purchase() to detect a custom product and fulfill and persist it through their own payment flow. PurchaseControllerJava does not support custom store products.
  • After your billing system grants the entitlement, call Superwall.instance.setSubscriptionStatus(...) to synchronize that entitlement state with Superwall. The SDK does not fulfill or persist custom purchases automatically.
  • StoreProduct.customTransactionId is an SDK-generated identifier you can use as the original transaction identifier in your own analytics.
  • Requires configuring the SDK with a PurchaseController.

Usage

For implementation examples and detailed guidance, see Using RevenueCat.

How is this guide?

On this page