Full technical details in your project at
/docs/modules/Payments.mdWhat 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
Key Components
PaymentsClient Protocol
PaymentsState
Production Setup (From Real Code)
The app entry point builds aPaymentsConfig 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 fromConfig/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 onePlanOptionCard 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’sMessageRepository 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
- Create sandbox tester in App Store Connect
- Sign in on device with sandbox account
- Test purchases - all free in sandbox
- 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/PaywallViewModeland subscription management - App shell -
ProfileViewreads subscription status - Any feature - Entitlement checking via
currentState()/states()
Best Practices
Purchase Flow
Purchase Flow
- Show clear pricing
- Include terms and privacy links
- Handle cancellation gracefully
- Provide restore option
- Test thoroughly in sandbox
Entitlements
Entitlements
- Check server-side (if possible)
- Cache locally for offline
- Update on app launch
- Observe state changes
UX
UX
- 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). ThePaymentsTests
target runs as part of the full suite (~598 tests across 12 package test targets
plus the app test suites, one Boilerplate.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