diff --git a/content/docs/android/guides/web-checkout/post-checkout-redirecting.mdx b/content/docs/android/guides/web-checkout/post-checkout-redirecting.mdx index f2f1398..c7c6c0b 100644 --- a/content/docs/android/guides/web-checkout/post-checkout-redirecting.mdx +++ b/content/docs/android/guides/web-checkout/post-checkout-redirecting.mdx @@ -28,7 +28,7 @@ Redirect users to your own custom URL with purchase information: **Query Parameters Included**: - `app_user_id` - The user's identifier from your app - `email` - User's email address -- `stripe_subscription_id` - The Stripe subscription ID +- `stripe_subscription_id` - The Stripe subscription ID, or the Stripe Checkout session ID for one-time purchases - Any custom placement parameters you set **Example**: diff --git a/content/docs/android/guides/web-checkout/using-revenuecat.mdx b/content/docs/android/guides/web-checkout/using-revenuecat.mdx index 70fd6a0..42ce1a0 100644 --- a/content/docs/android/guides/web-checkout/using-revenuecat.mdx +++ b/content/docs/android/guides/web-checkout/using-revenuecat.mdx @@ -19,6 +19,10 @@ If you're using RevenueCat, you'll need to follow [steps 1 to 4 in their guide]( associate the RevenueCat customer with the Stripe subscription IDs returned from redeeming the code. You can do this by extracting the ids from the `RedemptionResult` and sending them to RevenueCat's API by using the `didRedeemLink(result:)` delegate method: + + This flow is for Stripe subscriptions. Stripe one-time purchases can return Stripe Checkout session IDs through the same legacy `stripeSubscriptionIds` field, but those IDs are not Stripe subscription IDs. Handle one-time purchases with Superwall entitlements or your own backend instead of sending those IDs to RevenueCat's Stripe subscription endpoint. + + ```kotlin import com.revenuecat.purchases.Purchases import com.superwall.sdk.Superwall diff --git a/content/docs/expo/guides/web-checkout/post-checkout-redirecting.mdx b/content/docs/expo/guides/web-checkout/post-checkout-redirecting.mdx index 721516e..7ae8610 100644 --- a/content/docs/expo/guides/web-checkout/post-checkout-redirecting.mdx +++ b/content/docs/expo/guides/web-checkout/post-checkout-redirecting.mdx @@ -38,7 +38,7 @@ Redirect users to your own custom URL with purchase information: }, stripe_subscription_id: { type: "string", - description: "Stripe subscription ID.", + description: "Stripe subscription ID, or Stripe Checkout session ID for one-time purchases.", }, custom_parameters: { type: "Record", diff --git a/content/docs/expo/guides/web-checkout/using-revenuecat.mdx b/content/docs/expo/guides/web-checkout/using-revenuecat.mdx index 3c2a2ef..d50298e 100644 --- a/content/docs/expo/guides/web-checkout/using-revenuecat.mdx +++ b/content/docs/expo/guides/web-checkout/using-revenuecat.mdx @@ -19,6 +19,10 @@ If you're using RevenueCat, you'll need to follow [steps 1 to 4 in their guide]( associate the RevenueCat customer with the Stripe subscription IDs returned from redeeming the code. You can do this by extracting the ids from the `RedemptionResult` and sending them to RevenueCat's API by using the `didRedeemLink(result)` delegate method: + + This flow is for Stripe subscriptions. Stripe one-time purchases can return Stripe Checkout session IDs through the same legacy `stripeSubscriptionIds` field, but those IDs are not Stripe subscription IDs. Handle one-time purchases with Superwall entitlements or your own backend instead of sending those IDs to RevenueCat's Stripe subscription endpoint. + + ```typescript import { SuperwallDelegate, RedemptionResult } from 'expo-superwall/compat'; import Purchases from 'react-native-purchases'; diff --git a/content/docs/flutter/guides/web-checkout/post-checkout-redirecting.mdx b/content/docs/flutter/guides/web-checkout/post-checkout-redirecting.mdx index 283e442..0e21f06 100644 --- a/content/docs/flutter/guides/web-checkout/post-checkout-redirecting.mdx +++ b/content/docs/flutter/guides/web-checkout/post-checkout-redirecting.mdx @@ -28,7 +28,7 @@ Redirect users to your own custom URL with purchase information: **Query Parameters Included**: - `app_user_id` - The user's identifier from your app - `email` - User's email address -- `stripe_subscription_id` - The Stripe subscription ID +- `stripe_subscription_id` - The Stripe subscription ID, or the Stripe Checkout session ID for one-time purchases - Any custom placement parameters you set **Example**: diff --git a/content/docs/flutter/guides/web-checkout/using-revenuecat.mdx b/content/docs/flutter/guides/web-checkout/using-revenuecat.mdx index 39c136f..9880fc1 100644 --- a/content/docs/flutter/guides/web-checkout/using-revenuecat.mdx +++ b/content/docs/flutter/guides/web-checkout/using-revenuecat.mdx @@ -19,6 +19,10 @@ If you're using RevenueCat, you'll need to follow [steps 1 to 4 in their guide]( associate the RevenueCat customer with the Stripe subscription IDs returned from redeeming the code. You can do this by extracting the ids from the `RedemptionResult` and sending them to RevenueCat's API by using the `didRedeemLink()` delegate method: + + This flow is for Stripe subscriptions. Stripe one-time purchases can return Stripe Checkout session IDs through the same legacy `stripeSubscriptionIds` field, but those IDs are not Stripe subscription IDs. Handle one-time purchases with Superwall entitlements or your own backend instead of sending those IDs to RevenueCat's Stripe subscription endpoint. + + ```dart import 'package:superwallkit_flutter/superwallkit_flutter.dart'; import 'package:purchases_flutter/purchases_flutter.dart'; diff --git a/content/docs/images/stripe_otp_import.jpg b/content/docs/images/stripe_otp_import.jpg new file mode 100644 index 0000000..6507c4e Binary files /dev/null and b/content/docs/images/stripe_otp_import.jpg differ diff --git a/content/docs/images/stripe_otp_product.jpg b/content/docs/images/stripe_otp_product.jpg new file mode 100644 index 0000000..d085456 Binary files /dev/null and b/content/docs/images/stripe_otp_product.jpg differ diff --git a/content/docs/support/web-checkout/how-to-retrieve-stripe-customer-data-after-web-checkout.mdx b/content/docs/support/web-checkout/how-to-retrieve-stripe-customer-data-after-web-checkout.mdx index 0b8fb8f..317e96d 100644 --- a/content/docs/support/web-checkout/how-to-retrieve-stripe-customer-data-after-web-checkout.mdx +++ b/content/docs/support/web-checkout/how-to-retrieve-stripe-customer-data-after-web-checkout.mdx @@ -22,10 +22,10 @@ func didRedeemLink(result: RedemptionResult) { // Get the customer's email let email = redemptionInfo.purchaserInfo.email - // Get the Stripe customer ID and subscription IDs + // Get the Stripe customer ID and Stripe purchase identifiers if case let .stripe(customerId, subscriptionIds) = redemptionInfo.purchaserInfo.storeIdentifiers { print("Stripe Customer ID: \(customerId)") - print("Subscription IDs: \(subscriptionIds)") + print("Stripe purchase IDs: \(subscriptionIds)") // Send to your backend or analytics sendToBackend( @@ -37,6 +37,10 @@ func didRedeemLink(result: RedemptionResult) { } ``` + + The `subscriptionIds` value keeps its legacy name for compatibility. For Stripe subscriptions, it contains `sub_` IDs. For Stripe one-time purchases, it can contain Stripe Checkout session IDs. + + ### What happens if the user kills the app during checkout? If a user completes the Stripe checkout but terminates the app before returning, the `didRedeemLink(result:)` callback will not fire. However, their purchase is not lost. @@ -47,7 +51,7 @@ If a user completes the Stripe checkout but terminates the app before returning, 2. **Plan management page**: Users can visit `https://{yoursubdomain}.superwall.app/manage`, enter their email, and receive a new redemption link. -3. **Automatic entitlement sync**: The SDK polls for web entitlements when the app enters foreground, so subscription status updates automatically. However, this sync only updates entitlements and does not trigger `didRedeemLink`, meaning you will not receive the Stripe customer ID or email through this path. +3. **Automatic entitlement sync**: The SDK polls for web entitlements when the app enters foreground, so subscription and entitlement status updates automatically. However, this sync only updates access and does not trigger `didRedeemLink`, meaning you will not receive the Stripe customer ID or email through this path. To programmatically receive the Stripe customer ID and email, the user must tap a redemption link (either from the automatic email or the manage page). @@ -55,12 +59,13 @@ To programmatically receive the Stripe customer ID and email, the user must tap ### Stripe metadata -Superwall automatically includes your app user ID in the Stripe checkout session and subscription metadata. The key `_sw_app_user_id` contains the user ID you set via `Superwall.shared.identify(userId:)`. +Superwall automatically includes your app user ID in Stripe checkout metadata. For subscriptions, it is also included in subscription metadata. The key `_sw_app_user_id` contains the user ID you set via `Superwall.shared.identify(userId:)`. -This allows you to correlate Stripe subscriptions with your users directly in Stripe or through webhooks. +This allows you to correlate Stripe purchases with your users directly in Stripe or through webhooks. ## Related - [Post-Checkout Redirecting](/sdk/guides/web-checkout/post-checkout-redirecting) +- [Stripe One-Time Purchases](/web-checkout/web-checkout-stripe-one-time-purchases) - [How do I disable the activation link email for web checkout?](/support/web-checkout/3969573187-how-do-i-disable-the-activation-link-email-for-web-checkout) - [Web Checkout FAQ](/web-checkout/web-checkout-faq) diff --git a/content/docs/web-checkout/index.mdx b/content/docs/web-checkout/index.mdx index 4074e94..c3af4c6 100644 --- a/content/docs/web-checkout/index.mdx +++ b/content/docs/web-checkout/index.mdx @@ -3,7 +3,7 @@ title: "Overview" description: "Let customers purchase products online via Stripe, then link them to your iOS app with one seamless flow. No authentication required." --- -Superwall's web checkout integration makes it easy to set up purchasing funnels for your app via the web. Web checkout is powered by Stripe. Once an online purchase is complete, the customer will be redirected back to your app with a deep link that can be used to unlock content or features in your app via any associated [entitlement](/dashboard/products#entitlements). +Superwall's web checkout integration makes it easy to set up purchasing funnels for your app via the web. Web checkout is powered by Stripe. Once an online purchase is complete, the customer will be redirected back to your app with a deep link that can be used to unlock content or features in your app via any associated [entitlement](/dashboard/products#entitlements). Web checkout supports subscriptions and Stripe one-time purchases. Web checkout requires the Superwall iOS SDK 4.2.0 or later. @@ -35,7 +35,7 @@ Refer to the individual pages below to get started, but for a quick, high-level 8. For Redeem mode: _On the device that they downloaded the app_, they click the redemption link. 9. Your iOS app is opened via a deep link (which means it must be set up with Superwall deep links, [docs here](/sdk/quickstart/in-app-paywall-previews)). 10. In the `SuperwallDelegate`, `willRedeemLink()` is called, and then once it's fetched - `didRedeemLink(result:)` is called with the result of the redemption. -11. Finally, this user's account and details are managed via a link they find in their [email receipt or by visiting a URL manually](/web-checkout/web-checkout-managing-memberships). +11. Finally, this user's account and purchase details are managed via a link they find in their [email receipt or by visiting a URL manually](/web-checkout/web-checkout-managing-memberships). ## Getting setup @@ -44,23 +44,24 @@ Before you start, you'll need to have a Superwall account and a Stripe account. 1. **[Creating an app](/web-checkout/web-checkout-creating-an-app):** First, you'll add a Web Checkout app to an existing project within Superwall. 2. **[Stripe setup](/web-checkout/web-checkout-configuring-stripe-keys-and-settings):** Install the [Superwall Stripe app](https://marketplace.stripe.com/apps/superwall) for automatic configuration. 3. **[Managing products](/web-checkout/web-checkout-adding-a-stripe-product):** Create or import products to add to your web paywalls. +4. **[Stripe one-time purchases](/web-checkout/web-checkout-stripe-one-time-purchases):** Sell lifetime access, credit packs or other one-time products with Stripe. ### Creating paywalls and campaigns -4. **[Presenting paywalls](/web-checkout/web-checkout-creating-campaigns-to-show-paywalls):** Set up a campaign, create some placements and add paywalls to begin showing them to customers. +5. **[Presenting paywalls](/web-checkout/web-checkout-creating-campaigns-to-show-paywalls):** Set up a campaign, create some placements and add paywalls to begin showing them to customers. ### Associating entitlements to your iOS apps -5. **[Linking purchases to your iOS app](/sdk/guides/web-checkout/linking-membership-to-iOS-app):** Once a purchase occurs, the user will be prompted to download your app and click on a redemption link. -6. **[Managing memberships](/web-checkout/web-checkout-managing-memberships):** Users can cancel, update or manage their memberships via Stripe. +6. **[Linking purchases to your iOS app](/sdk/guides/web-checkout/linking-membership-to-iOS-app):** Once a purchase occurs, the user will be prompted to download your app and click on a redemption link. +7. **[Managing purchases](/web-checkout/web-checkout-managing-memberships):** Users can restore purchases, manage subscriptions, update payment methods and view billing history. ### Testing purchases -7. **[Testing purchases](/web-checkout/web-checkout-testing-purchases):** Test your web checkout flow with test purchases. +8. **[Testing purchases](/web-checkout/web-checkout-testing-purchases):** Test your web checkout flow with test purchases. ### App to Web -8. **[App to Web Checkout](/web-checkout/web-checkout-direct-stripe-checkout):** For customers in the United States, you can offer Stripe products directly from your iOS paywalls. +9. **[App to Web Checkout](/web-checkout/web-checkout-direct-stripe-checkout):** For customers in the United States, you can offer Stripe products directly from your iOS paywalls. ## Troubleshooting -If a user has issues accessing their subscription in your app after paying via web checkout, direct them to your plan management page to retrieve their subscription link or manage billing. For example: `http://yourapp.superwall.app/manage` +If a user has issues accessing their purchase in your app after paying via web checkout, direct them to your plan management page to retrieve their redemption link or manage billing. For example: `http://yourapp.superwall.app/manage` diff --git a/content/docs/web-checkout/meta.json b/content/docs/web-checkout/meta.json index 6ddf6de..bcc6fe5 100644 --- a/content/docs/web-checkout/meta.json +++ b/content/docs/web-checkout/meta.json @@ -9,6 +9,7 @@ "web-checkout-creating-an-app", "web-checkout-configuring-stripe-keys-and-settings", "web-checkout-adding-a-stripe-product", + "web-checkout-stripe-one-time-purchases", "web-checkout-creating-campaigns-to-show-paywalls", "---Implementation---", diff --git a/content/docs/web-checkout/web-checkout-adding-a-stripe-product.mdx b/content/docs/web-checkout/web-checkout-adding-a-stripe-product.mdx index 10d0225..b0dd5f3 100644 --- a/content/docs/web-checkout/web-checkout-adding-a-stripe-product.mdx +++ b/content/docs/web-checkout/web-checkout-adding-a-stripe-product.mdx @@ -49,7 +49,7 @@ From there, fill in all of the fields presented to you in Stripe: 2. **Description:** A description of the product, this will show up in checkout. 3. **Image:** An image representing the product, this will show up in checkout. Optional. 4. **Product tax code:** The tax code classification for the product. Refer to your territories tax codes for more information. -5. **Recurring vs One-off:** For subscriptions, choose "Recurring", whereas one time purchases or consumables should be "one-off" products. +5. **Recurring vs One-off:** For subscriptions, choose "Recurring". For lifetime access, credit packs or other consumables, choose "One-off". 6. **Amount:** The price of your product, and what it will renew at if it's recurring. 7. **Billing period:** The billing period for the product, i.e. "Monthly", "Yearly", etc. @@ -65,6 +65,10 @@ Now, when you return to Superwall, select your product from the **Products** dro Be sure to associate the correct entitlement to the product as well. + + For Stripe one-time prices, Superwall shows the period as **None (Lifetime / Consumable)**. Link lifetime products to an entitlement, and usually leave consumable products without one. Learn more in [Stripe One-Time Purchases](/web-checkout/web-checkout-stripe-one-time-purchases). + + ### Adding products to paywalls Adding Stripe products to web paywalls works the exact same way as it does for mobile paywalls. Check out the docs [here](/dashboard/dashboard-creating-paywalls/paywall-editor-products). For a quick overview: diff --git a/content/docs/web-checkout/web-checkout-configuring-stripe-keys-and-settings.mdx b/content/docs/web-checkout/web-checkout-configuring-stripe-keys-and-settings.mdx index 513e8f7..8f2714c 100644 --- a/content/docs/web-checkout/web-checkout-configuring-stripe-keys-and-settings.mdx +++ b/content/docs/web-checkout/web-checkout-configuring-stripe-keys-and-settings.mdx @@ -40,7 +40,7 @@ Configure what happens after a user completes a purchase on the web: When using Redirect mode, you'll need to provide a **Redirect URL** (must start with `https://`). Purchase data will be appended as query parameters: - `app_user_id` - User's app identifier - `email` - User's email address -- `stripe_subscription_id` - Stripe subscription ID +- `stripe_subscription_id` - Stripe subscription ID, or Stripe Checkout session ID for one-time purchases - Any custom placement parameters you've set Learn more about [post-checkout redirecting](/sdk/guides/web-checkout/post-checkout-redirecting). diff --git a/content/docs/web-checkout/web-checkout-direct-stripe-checkout.mdx b/content/docs/web-checkout/web-checkout-direct-stripe-checkout.mdx index f7b3de9..313309f 100644 --- a/content/docs/web-checkout/web-checkout-direct-stripe-checkout.mdx +++ b/content/docs/web-checkout/web-checkout-direct-stripe-checkout.mdx @@ -24,7 +24,7 @@ For customers in the United States, you can offer Stripe products directly from **App Store Review Tip:** If you choose the in-app sheet option, we strongly suggest showing your Stripe purchase experience to Apple during an App Review before testing with users. We recommend adding the following to your App Review notes: - > US users will be able to purchase a subscription using Stripe. These users are filtered using their registered App Store country. All other countries will only be able to purchase a subscription using Apple IAPs. You can test this by switching your device's registered App Store country. + > US users will be able to purchase subscriptions or one-time products using Stripe. These users are filtered using their registered App Store country. All other countries will only be able to purchase using Apple IAPs. You can test this by switching your device's registered App Store country. @@ -35,7 +35,7 @@ For customers in the United States, you can offer Stripe products directly from From there, the flow works the same way as it would for web checkout. Once the payment succeeds, the [Superwall delegate](/sdk/guides/using-superwall-delegate) functions `willRedeemLink()` and `didRedeemLink(result:)` will be called. You can use these functions to handle the deep link in your app if you need to show any specific UI as described in our [Post-Checkout Redirecting](/sdk/guides/web-checkout/post-checkout-redirecting) docs. - Additionally, the subscription status will be updated automatically and the delegate callback `func subscriptionStatusDidChange(from oldValue: SubscriptionStatus, to newValue: SubscriptionStatus)` will be called. If you're using a `PurchaseController`, refer to [the docs here](/sdk/guides/web-checkout/linking-membership-to-iOS-app#using-a-purchasecontroller). + Additionally, entitlement and subscription status will update automatically. For lifetime one-time products, the linked entitlement becomes active without an expiration. For consumables, inspect `CustomerInfo.nonSubscriptions` and grant the purchased quantity in your own system. If you're using a `PurchaseController`, refer to [the docs here](/sdk/guides/web-checkout/linking-membership-to-iOS-app#using-a-purchasecontroller). diff --git a/content/docs/web-checkout/web-checkout-faq.mdx b/content/docs/web-checkout/web-checkout-faq.mdx index 2c5a05a..1c81446 100644 --- a/content/docs/web-checkout/web-checkout-faq.mdx +++ b/content/docs/web-checkout/web-checkout-faq.mdx @@ -3,15 +3,15 @@ title: "Web Checkout FAQ" description: "Frequently asked questions about web checkout." --- -### How does restoring memberships work on iOS when you've purchased via web checkout? +### How does restoring memberships work when you've purchased via web checkout? When the user taps on the restore link in the paywall, we'll do the normal restore flow for on-device subscriptions. However, if you've enabled web checkout and the restored -entitlements don't match the entitlements belonging to the products on the paywall, we'll present an alert asking the user if they'd like to check for subscriptions on the web. This will -take them out of your app to the [plan management screen](/web-checkout/web-checkout-managing-memberships) where they can get a redemption link to restore their subscriptions. +entitlements don't match the entitlements belonging to the products on the paywall, we'll present an alert asking the user if they'd like to check for purchases on the web. This will +take them out of your app to the [plan management screen](/web-checkout/web-checkout-managing-memberships) where they can get a redemption link to restore their purchases. ### Does Superwall email customers after checkout? -Yes. By default, Superwall emails the address used during checkout with instructions and a redemption link to activate the subscription in your iOS app. The email is sent from `Your app name ` with the subject `Your activation link from your app name`. +Yes. By default, Superwall emails the address used during checkout with instructions and a redemption link to activate the purchase in your app. The email is sent from `Your app name ` with the subject `Your activation link from your app name`. ![](/images/web-checkout-redeem-email.png) @@ -62,10 +62,16 @@ Superwall.shared.identify(userId: user.id) This will ensure that the user is associated with the web checkout purchase. -### A user paid on the web and can't access their subscription in the app. What should I do? +### A user paid on the web and can't access their purchase in the app. What should I do? Direct them to your app's plan management page so they can retrieve their redemption link or manage billing. For example: `http://yourapp.superwall.app/manage` +### Can I sell lifetime or consumable products through Stripe? + +Yes. Create a Stripe one-time price, import it into Superwall, and add it to a web paywall. For lifetime access, attach the entitlement the product should unlock. For consumables, usually leave the product without an entitlement and use `CustomerInfo.nonSubscriptions` to credit the user's account after purchase. + +Learn more in [Stripe One-Time Purchases](/web-checkout/web-checkout-stripe-one-time-purchases). + ### When should I use Redirect mode instead of Redeem mode? Use **Redirect mode** when you need to: @@ -88,7 +94,7 @@ When using Redirect mode, the following query parameters are automatically appen **Standard parameters**: - `app_user_id` - The user's identifier from your app (if you called `identify`) - `email` - The user's email address from checkout -- `stripe_subscription_id` - The Stripe subscription ID +- `stripe_subscription_id` - The Stripe subscription ID, or the Stripe Checkout session ID for one-time purchases **Custom parameters**: Any placement parameters you set when creating the web checkout link will also be included. diff --git a/content/docs/web-checkout/web-checkout-managing-memberships.mdx b/content/docs/web-checkout/web-checkout-managing-memberships.mdx index bcd97a1..153a2ad 100644 --- a/content/docs/web-checkout/web-checkout-managing-memberships.mdx +++ b/content/docs/web-checkout/web-checkout-managing-memberships.mdx @@ -1,25 +1,25 @@ --- title: "Restoring & Managing Purchases" -description: "Learn how users can manage their subscriptions from purchases made via the web." +description: "Learn how users can manage and restore purchases made via the web." --- -When users purchase a subscription via the web, they can can access their account details via a plan management page. This url is included in their receipt which is sent to their email upon a successful purchase. To retrieve the link, users must enter in their email that was used during checkout. Otherwise, to offer this link manually you can use the following URL format: +When users purchase through web checkout, they can access their account details via a plan management page. This URL is included in their receipt, which is sent to their email after a successful purchase. To retrieve the link, users must enter the email they used during checkout. Otherwise, to offer this link manually you can use the following URL format: ```plaintext https://{your URL in settings}.superwall.app/manage ``` -By default, after a successful checkout, Superwall emails the address used at checkout with instructions and a redemption link to activate the subscription in your iOS app. The email is sent from `Your app name ` with the subject `Your activation link from your app name`. +By default, after a successful checkout, Superwall emails the address used at checkout with instructions and a redemption link to activate the purchase in your app. The email is sent from `Your app name ` with the subject `Your activation link from your app name`. ![](/images/web-checkout-redeem-email.png) If you want to disable these emails, use the "Disable Superwall Emails" setting in your Stripe app settings — see [how to disable the activation link email](/support/web-checkout/3969573187-how-do-i-disable-the-activation-link-email-for-web-checkout). -When this page is visited, users enter in their email that used during checkout to receive a link to manage their subscription: +When this page is visited, users enter the email they used during checkout to receive a link to manage their purchase: ![](/images/web2app_manage.png) -For the above example, the URL would be `https://caffeinepal.superwall.app/manage`. After entering their email, they will receive a link to manage their subscription, update payment methods, view their billing history, and more: +For the above example, the URL would be `https://caffeinepal.superwall.app/manage`. After entering their email, they will receive a link to restore access, manage subscriptions, update payment methods, view their billing history, and more: ![](/images/web2app_manage_details.png) diff --git a/content/docs/web-checkout/web-checkout-sdk-setup.mdx b/content/docs/web-checkout/web-checkout-sdk-setup.mdx index 273d9b5..6ba6cd7 100644 --- a/content/docs/web-checkout/web-checkout-sdk-setup.mdx +++ b/content/docs/web-checkout/web-checkout-sdk-setup.mdx @@ -18,13 +18,13 @@ You'll also need the Superwall SDK integrated in your app. 1. **[Set up deep links](/sdk/quickstart/in-app-paywall-previews)** — Required for redirecting users back to your app after a web purchase. 2. **[Handle Post-Checkout redirecting](/sdk/guides/web-checkout/post-checkout-redirecting)** — Implement delegate methods to handle purchase redemption when the user returns to your app. -3. **Only if you're using RevenueCat:** [Using RevenueCat](/sdk/guides/web-checkout/using-revenuecat) — Sync web purchases with RevenueCat for subscription management. +3. **Only if you're using RevenueCat:** [Using RevenueCat](/sdk/guides/web-checkout/using-revenuecat) — Sync Stripe subscriptions with RevenueCat. 4. **Only if you're using your own PurchaseController:** [Redeeming In-App](/sdk/guides/web-checkout/linking-membership-to-iOS-app) — Merge web and device entitlements when using a custom PurchaseController. ## Testing 1. **[Testing purchases](/web-checkout/web-checkout-testing-purchases)** — Verify your integration with test mode before going live. -2. **[Managing memberships](/web-checkout/web-checkout-managing-memberships)** — Learn how users cancel, update, or manage their subscriptions via Stripe. +2. **[Managing purchases](/web-checkout/web-checkout-managing-memberships)** — Learn how users restore purchases, manage subscriptions, update payment methods and view billing history. ## Further reading diff --git a/content/docs/web-checkout/web-checkout-stripe-one-time-purchases.mdx b/content/docs/web-checkout/web-checkout-stripe-one-time-purchases.mdx new file mode 100644 index 0000000..554a365 --- /dev/null +++ b/content/docs/web-checkout/web-checkout-stripe-one-time-purchases.mdx @@ -0,0 +1,79 @@ +--- +title: "Stripe One-Time Purchases" +description: "Use Stripe one-time prices for lifetime access or consumable purchases in web checkout." +--- + +Superwall supports Stripe one-time prices in web checkout. Use them when a customer should pay once instead of starting a recurring subscription, such as: + +- Lifetime access to a paid tier. +- Credit packs, tokens, or other consumable quantities. +- One-off digital goods or upgrades. + +Stripe one-time purchases use the same web checkout flow as subscriptions. The difference is the Stripe price type and how you attach entitlements in Superwall. + + + Stripe calls these **one-time** prices in the API and **one-off** prices in parts of the dashboard. + + +## Create the price in Stripe + +Create or open the product in Stripe, then add a price with **One-off** selected instead of **Recurring**. Superwall reads the Stripe price type when you import the product. + +![](/images/stripe_otp_product.jpg) + +After the Stripe price exists, import it from [Creating Products](/web-checkout/web-checkout-adding-a-stripe-product). In Superwall, one-time prices appear with a period of **None (Lifetime / Consumable)**. + +![](/images/stripe_otp_import.jpg) + +## Choose the access behavior + +Superwall uses entitlements to decide whether a one-time product unlocks ongoing access or behaves like a consumable purchase. + +| Purchase type | Entitlement setup | Result | +| --- | --- | --- | +| Lifetime access | Attach the entitlement the product should unlock. | The user gets active, non-expiring access to that entitlement after purchase. | +| Consumable purchase | Leave the product without an entitlement. | The purchase is recorded in `CustomerInfo.nonSubscriptions`, but it does not make the user's subscription status active. | + +For example, a "Premium Lifetime" product should usually be linked to your `pro` entitlement. A "100 Credits" product usually should not be linked to an entitlement; instead, use the transaction record to credit the user's account in your own system. + + + Do not attach an entitlement to a consumable unless buying that consumable should also unlock access permanently. + + +## Checkout behavior + +When a customer purchases a Stripe one-time price, Superwall creates a Stripe Checkout session in payment mode. This means: + +- The customer pays once. +- No Stripe subscription is created. +- Trial fields are ignored for the one-time price. +- Revenue is tracked as a non-renewing purchase. +- The checkout session ID acts as the Stripe purchase identifier for that purchase. + +The rest of the web checkout flow is unchanged. In Redeem mode, customers receive a redemption link and the SDK redeems the purchase in your app. In Redirect mode, Superwall redirects to your URL with purchase data. + +## Read purchase data in the SDK + +Use `CustomerInfo.nonSubscriptions` to inspect one-time purchases. Each transaction includes the product identifier, purchase date, whether it is consumable, whether it has been revoked, and the store that fulfilled it. + +For Stripe one-time purchases, the transaction's `store` value is `stripe`. + +```swift +let customerInfo = Superwall.shared.customerInfo + +for purchase in customerInfo.nonSubscriptions where purchase.store == .stripe { + print("Product: \(purchase.productId)") + print("Consumable: \(purchase.isConsumable)") +} +``` + + + The redemption result still exposes Stripe purchase identifiers through the legacy `stripeSubscriptionIds` name. For one-time purchases, those identifiers can be Stripe Checkout session IDs instead of `sub_` subscription IDs. + + +## Related + +- [Creating Products](/web-checkout/web-checkout-adding-a-stripe-product) +- [App2Web](/web-checkout/web-checkout-direct-stripe-checkout) +- [Restoring & Managing Purchases](/web-checkout/web-checkout-managing-memberships) +- [How do I retrieve Stripe customer data after web checkout?](/support/web-checkout/how-to-retrieve-stripe-customer-data-after-web-checkout) diff --git a/content/docs/web-checkout/web-checkout-web-only.mdx b/content/docs/web-checkout/web-checkout-web-only.mdx index 0921a98..354c1f9 100644 --- a/content/docs/web-checkout/web-checkout-web-only.mdx +++ b/content/docs/web-checkout/web-checkout-web-only.mdx @@ -46,7 +46,7 @@ Your URL will receive the following query parameters after checkout: |-----------|-------------| | `app_user_id` | The user's identifier (if you set one) | | `email` | User's email from checkout | -| `stripe_subscription_id` | The Stripe subscription ID | +| `stripe_subscription_id` | The Stripe subscription ID, or the Stripe Checkout session ID for one-time purchases | | Custom parameters | Any placement parameters you set | **Example redirect:** diff --git a/content/shared/web-checkout/index.mdx b/content/shared/web-checkout/index.mdx index 66460a7..2eebd22 100644 --- a/content/shared/web-checkout/index.mdx +++ b/content/shared/web-checkout/index.mdx @@ -41,7 +41,7 @@ description: "Integrate Web Checkout into your app with the Superwall SDK" 2. [Managing Memberships](/web-checkout/web-checkout-managing-memberships) ## Troubleshooting -If a user has issues accessing their subscription in your app after paying via web checkout, direct them to your plan management page to retrieve their subscription link or manage billing: +If a user has issues accessing their purchase in your app after paying via web checkout, direct them to your plan management page to retrieve their redemption link or manage billing: For example: `http://yourapp.superwall.app/manage` diff --git a/content/shared/web-checkout/post-checkout-redirecting.mdx b/content/shared/web-checkout/post-checkout-redirecting.mdx index 1911b0f..03b4137 100644 --- a/content/shared/web-checkout/post-checkout-redirecting.mdx +++ b/content/shared/web-checkout/post-checkout-redirecting.mdx @@ -28,7 +28,7 @@ Redirect users to your own custom URL with purchase information: **Query Parameters Included**: - `app_user_id` - The user's identifier from your app - `email` - User's email address -- `stripe_subscription_id` - The Stripe subscription ID +- `stripe_subscription_id` - The Stripe subscription ID, or the Stripe Checkout session ID for one-time purchases - Any custom placement parameters you set **Example**: diff --git a/content/shared/web-checkout/using-revenuecat.mdx b/content/shared/web-checkout/using-revenuecat.mdx index f960852..f80daaa 100644 --- a/content/shared/web-checkout/using-revenuecat.mdx +++ b/content/shared/web-checkout/using-revenuecat.mdx @@ -19,6 +19,10 @@ If you're using RevenueCat, you'll need to follow [steps 1 to 4 in their guide]( associate the RevenueCat customer with the Stripe subscription IDs returned from redeeming the code. You can do this by extracting the ids from the `RedemptionResult` and sending them to RevenueCat's API by using the `didRedeemLink(result:)` delegate method: + + This flow is for Stripe subscriptions. Stripe one-time purchases can return Stripe Checkout session IDs through the same legacy `stripeSubscriptionIds` field, but those IDs are not Stripe subscription IDs. Handle one-time purchases with Superwall entitlements or your own backend instead of sending those IDs to RevenueCat's Stripe subscription endpoint. + + ```swift import Foundation import RevenueCat