Superwall

PurchaseController

An abstract class that defines the contract for a purchase controller.

Deprecated SDK

We strongly recommend migrating to the new Superwall Expo SDK, see our migration guide for details.

Purpose

Abstract class that defines the contract for a purchase controller. This is used for custom purchase handling when you want to manage all subscription-related logic yourself.

Signature

export abstract class PurchaseController {
  abstract purchaseFromAppStore(productId: string): Promise<PurchaseResult>
  abstract purchaseFromGooglePlay(
    productId: string,
    basePlanId?: string,
    offerId?: string
  ): Promise<PurchaseResult>
  abstract restorePurchases(): Promise<RestorationResult>
}

Methods

MethodParametersDescription
purchaseFromAppStoreproductIdPurchase a product from the App Store. Returns a Promise that resolves with the result of the purchase logic.
purchaseFromGooglePlayproductId, basePlanId?, offerId?Purchase a product from Google Play. Returns a Promise that resolves with the result of the purchase logic.
restorePurchases-Restore purchases. Returns a Promise that resolves with the restoration result.

Usage

Implement the PurchaseController class:

import { PurchaseController, PurchaseResult, RestorationResult, PurchaseResultCancelled, PurchaseResultFailed, PurchaseResultPurchased } from "@superwall/react-native-superwall"

class MyPurchaseController extends PurchaseController {
  async purchaseFromAppStore(productId: string): Promise<PurchaseResult> {
    try {
      // Your iOS purchase logic here
      // For example, using RevenueCat:
      const purchase = await Purchases.purchaseProduct(productId)
      
      if (purchase.customerInfo.entitlements.active["pro"]) {
        return new PurchaseResultPurchased()
      } else {
        return new PurchaseResultFailed("Purchase completed but entitlement not active")
      }
    } catch (error) {
      if (error.userCancelled) {
        return new PurchaseResultCancelled()
      }
      return new PurchaseResultFailed(error.message)
    }
  }
  
  async purchaseFromGooglePlay(
    productId: string,
    basePlanId?: string,
    offerId?: string
  ): Promise<PurchaseResult> {
    try {
      // Your Android purchase logic here
      // For example, using RevenueCat:
      const purchase = await Purchases.purchaseProduct(productId)
      
      if (purchase.customerInfo.entitlements.active["pro"]) {
        return new PurchaseResultPurchased()
      } else {
        return new PurchaseResultFailed("Purchase completed but entitlement not active")
      }
    } catch (error) {
      if (error.userCancelled) {
        return new PurchaseResultCancelled()
      }
      return new PurchaseResultFailed(error.message)
    }
  }
  
  async restorePurchases(): Promise<RestorationResult> {
    try {
      // Your restore logic here
      // For example, using RevenueCat:
      const customerInfo = await Purchases.restorePurchases()
      
      if (customerInfo.entitlements.active["pro"]) {
        return RestorationResult.restored()
      } else {
        return RestorationResult.failed("No active subscription found")
      }
    } catch (error) {
      return RestorationResult.failed(error.message)
    }
  }
}

Configure Superwall with your purchase controller:

await Superwall.configure({
  apiKey: "pk_your_api_key",
  purchaseController: new MyPurchaseController()
})

Important Notes

  • When using a PurchaseController, you must call setSubscriptionStatus() whenever the user's entitlements change.
  • The purchase controller is responsible for handling all purchase and restore logic.
  • You can use third-party services like RevenueCat, Stripe, or your own backend to handle purchases.

How is this guide?

Edit on GitHub