Skip to main content
v2.3.0 is available. Read the upgrade guide for the current capability contracts, AI quota migration, and validation results.

App-owned paywalls in v2.3.0

Payments retains offerings, purchase, restore, and entitlement state. Your app owns benefits, plan presentation, and placement. Reuse those actions through the shared view model rather than creating another RevenueCat client. The sample paywall is a starting point; keep legal links, restore access, large-text support, and accessible tap targets when composing your own screen.
Full technical details in your project at /docs/modules/Payments.md

What You Get

  • ✅ RevenueCat wrapper - Clean abstraction, no RC types leak
  • ✅ Reactive state - AsyncStream for subscription changes
  • ✅ Purchase flows - Buy, restore, cancel with full error handling
  • ✅ Entitlement system - Single “pro” entitlement (expandable)
  • ✅ Paywall UI - Beautiful, themeable subscription screen
  • ✅ Thread-safe - Multi-subscriber support with state replay
Time saved: 16-24 hours of RevenueCat integration, state management, paywall UI, and testing.

Key Components

PaymentsClient Protocol

PaymentsState

Production Setup (From Real Code)

The app entry point builds a PaymentsConfig from the generated AppConfiguration (produced at build time from Config/Secrets.xcconfig), then hands it to CompositionRoot:
CompositionRoot constructs the client with that config. In DEBUG with AUTH_BYPASS set, it swaps in MockPaymentsClient so the run-with-mocks experience (and UI tests) works fully offline with sample offerings:

Configuration Files

Config/Secrets.xcconfig (copy from Config/Secrets.example.xcconfig):
scripts/update-config.sh reads these values and regenerates SwiftAIBoilerplatePro/Generated/Configuration.swift (AppConfiguration). Complete setup: RevenueCat Setup Guide

Subscription Flow

Purchase

Restore

Check Entitlement

Paywall UI

Beautiful paywall included in FeatureSettings (PaywallView). Pass the shared PaymentsClient; the view creates its own PaywallViewModel:

Customization Examples

Add New Subscription Tier

The paywall renders one PlanOptionCard per offering returned by getOfferings(), so adding a tier is mostly a RevenueCat dashboard task — no UI code needed for the option to appear:

Add Usage Limits

Gate free-tier usage on entitlement state. The daily-count check below is a sketch — the boilerplate’s MessageRepository does not ship a todayCount(); supply your own counter (e.g. a @AppStorage tally or a page(...) query you filter by date):

Custom Entitlements

Testing

Sandbox Testing

  1. Create sandbox tester in App Store Connect
  2. Sign in on device with sandbox account
  3. Test purchases - all free in sandbox
  4. Test restore - verify works correctly

Mock Client

PreviewMocks.MockPaymentsClient conforms to the full PaymentsClient protocol and returns sample offerings, so previews and UI tests run with no App Store Connect setup:

Key Files

Dependencies

  • Core - Error handling, logging

Used By

  • FeatureSettings - PaywallView / PaywallViewModel and subscription management
  • App shell - ProfileView reads subscription status
  • Any feature - Entitlement checking via currentState() / states()

Best Practices

  • Show clear pricing
  • Include terms and privacy links
  • Handle cancellation gracefully
  • Provide restore option
  • Test thoroughly in sandbox
  • Check server-side (if possible)
  • Cache locally for offline
  • Update on app launch
  • Observe state changes
  • Make paywall beautiful
  • Highlight value proposition
  • Show feature comparison
  • Easy to dismiss
  • Clear cancellation policy

Learn More

Full Documentation

Complete Payments guide

RevenueCat Setup

Configuration guide

Feature Settings

See paywall UI

Building Guide

Customize subscriptions

Test Coverage

85%+ for the Payments package (payments are critical). The PaymentsTests target runs as part of the full suite (646 tests across 12 package test targets plus the app test suites, one App.xctestplan run). Tests include (PaymentsFlowTests, RevenueCatClientTests, PaymentErrorScenarioTests):
  • Purchase flows
  • Restore purchases
  • Entitlement checking
  • State management
  • Error scenarios
  • Subscription expiry

Build with AI (fast)

You can customize this module in minutes using our ready-to-paste LLM prompts.

Example Prompt

Context: Packages/FeatureSettings/** Prompt: “Add a toggle in Settings to show/hide a discounted annual plan on the paywall. Update tests to verify pricing visibility.” See in project: docs/modules/Payments.md