SDK Configuration
Configure Early
Initialize the SDK as early as possible in your app’s lifecycle:Use Sandbox Keys for Development
Keep sandbox and live keys separate:Entitlement Management
Restore on Every Launch
Always restore entitlements when your app launches to catch purchases made on other devices or missed callbacks:Cache Entitlements Locally
For offline access, cache entitlements to UserDefaults or Keychain:Check Expiration for Subscriptions
Subscriptions have anexpiresAt date. Check it when validating access:
Purchase Flow
Use the Payment Sheet
ZSPaymentSheet provides the best conversion rates because the user stays in your app:
Preloading
The.zsPaymentSheet() modifier automatically preloads the PaymentIntent and WKWebView before presenting the sheet, so the checkout is fully rendered the moment it slides up.
For the standalone ZSPaymentSheet init or UIKit’s present method, you can preload manually:
Show Loading State
For Safari-based checkout, show feedback immediately since it opens an external browser:Handle All Delegate Callbacks
Implement all delegate methods to handle every outcome:Provide a Restore Button
Apple requires a way for users to restore purchases. Add a visible restore option:User Identity
Use Stable Identifiers
Choose a user ID that won’t change:Handle Logged-Out State
If your app supports logged-out usage, decide how to handle purchases:Error Handling
Handle Each Error Type
ZeroSettle uses specific error types for different scenarios:| Error Type | When It’s Thrown |
|---|---|
ZeroSettleIAPError | SDK configuration and general errors |
PaymentSheetError | Payment sheet presentation and payment errors |
StoreKitPurchaseError | StoreKit purchase errors |
CheckoutError | Legacy checkout view errors (deprecated) |
Graceful Degradation
If the SDK fails to initialize or fetch products, fall back gracefully:Testing
Test the Full Flow
Before releasing, test these scenarios on a physical device:| Scenario | Expected Behavior |
|---|---|
| Complete purchase (payment sheet) | Transaction returned, entitlements update |
| Complete purchase (Safari) | Universal link callback, entitlements update |
| Cancel payment sheet | .cancelled error, no entitlement change |
| Cancel Safari checkout | No entitlement change, no error shown |
| Restore purchases | All previous purchases recovered |
| App killed during checkout | Entitlements sync on next launch |
| Network offline | Cached entitlements still work |
| Different device, same account | Entitlements sync via restore |
| StoreKit purchase (hybrid flow) | Transaction synced to ZeroSettle |
Use Sandbox Keys
Test with sandbox keys before going live:Performance
Fetch Products Once
Don’t fetch products on every view appearance. Fetch once and cache:Prefetch Products
Fetch products before the user reaches the paywall:Security
Never Trust Client-Side Entitlements Alone
For critical features, verify entitlements server-side:Keep Secret Keys Server-Side
Only use publishable keys in your app. Secret keys belong on your server:| Key Type | Where to Use |
|---|---|
| Publishable | iOS app |
| Secret | Your backend only |
