Stripe
Set up Stripe to enable secure payment processing in your Floot app.
Requirements
To set up Stripe for your Floot app, you will need:
- A Stripe account.
- The Stripe CLI installed on your machine (required only if you plan to test payments locally.)
Setup
Secret Key
Store your Stripe secret key securely in Supabase Vault by adding it to supabase/db_seeds/vault.sql
.
Note: This file is git-ignored for your security. The secret is required by the Supabase Stripe Foreign Data Wrapper (FDW).
To find your secret key, go to your Stripe dashboard and copy the Secret Key.
-- Stripe secret key
SELECT vault.create_secret (
'sk_test_...', -- replace with your Stripe secret key
'STRIPE_SECRET_KEY',
'Stripe secret key used in Stripe Foreign Data Wrapper'
);
Add the Stripe secret key to your Supabase local environment file.
STRIPE_SECRET_KEY="sk_test_..."
Webhooks
When building Stripe integrations, we want our application to receive events as they occur in Stripe accounts, so that the backend can execute actions accordingly.
Events Redirection
Stripe webhooks events should be redirected to your Supabase instance, and this is how to do it.
Here are the steps to receive Stripe events locally using the Stripe CLI (required).
Login to your Stripe account using the CLI.
stripe login
You'll be prompted to open a browser window to complete the login process.
Redirect Stripe events to your Supabase local instance.
stripe listen --forward-to localhost:54321/functions/v1/stripe-webhook
You should see a message confirming that the webhook is set up and listening for events.
Ready! Your webhook signing secret is whsec_...
You can now copy the whsec_...
value and add it to your Supabase local environment file.
STRIPE_WEBHOOK_SECRET="whsec_..."
Serve the Supabase functions locally to handle Stripe webhooks.
supabase functions serve --env-file .env.local --import-map ./functions/deno.json --no-verify-jwt
Events & Destination
Go to Stripe Dashboard → Developers
(sidebar) → Webhooks
→ + Add destination
→ select these events:
Event Name |
---|
checkout.session.completed |
customer.created |
customer.deleted |
invoice.paid |
price.created |
price.deleted |
price.updated |
product.created |
product.deleted |
product.updated |
customer.subscription.created |
customer.subscription.deleted |
customer.subscription.updated |
→ Continue
→ Select Webhook endpoint
as the destination type → Continue
Webhook Endpoint
In your Stripe Dashboard, set the Endpoint URL to your Supabase project's Stripe webhook:
https://<project-id>.supabase.co/functions/v1/stripe-webhook
You can find your exact webhook URL in the Supabase dashboard under
https://supabase.com/dashboard/project/<project-id>/functions
→ Details → Endpoint URL.
Tip
If you know your Supabase project ID, simply replace <project-id>
in the URL above.
Webhook Secret
After creating the webhook, you will see a Signing secret. Copy this value and add it to your Supabase environment file: supabase/.env*
.
STRIPE_WEBHOOK_SECRET=
Deployment
Make sure to deploy your Supabase functions after setting everything up.
supabase functions deploy stripe-webhook --no-verify-jwt
Events & Destination
Go to Stripe Dashboard → Developers
(sidebar) → Webhooks
→ + Add destination
→ select these events:
Event Name |
---|
checkout.session.completed |
customer.created |
customer.deleted |
invoice.paid |
price.created |
price.deleted |
price.updated |
product.created |
product.deleted |
product.updated |
customer.subscription.created |
customer.subscription.deleted |
customer.subscription.updated |
→ Continue
→ Select Webhook endpoint
as the destination type → Continue
Webhook Endpoint
In your Stripe Dashboard, set the Endpoint URL to this:
https://<your-domain>:54321/functions/v1/stripe-webhook
Webhook Secret
After creating the webhook, you will see a Signing secret. Copy this value and add it to your Supabase environment file: supabase/.env*
.
STRIPE_WEBHOOK_SECRET=
Deployment
Make sure to deploy your Supabase functions to your self-hosted instance after setting everything up.
App URL Scheme
The app URL scheme enables users to be redirected back to your app via deep links after completing a Stripe payment outside of web platforms. This should match the deep linking scheme configured in your Flutter application.
# Your app URL scheme (e.g. "com.mycompany.app")
APP_URL_SCHEME=
Products & prices
Important
Do not create customers from your Stripe dashboard, let the app take care of it, because it attaches useful metadata to them in the creation process.
Once you've completed the steps above, connect to your Stripe account and create your products and prices. These will automatically sync with your local Supabase instance and appear in your app's paywall.
Here is a guide on how to manage products and prices in Stripe.
Handling business logic
When integrating Stripe with your Floot app, you may want to customize how your backend responds to payment events. Floot provides sensible defaults for handling subscriptions and one-time payments, but you can extend or override this logic to fit your business needs. The following sections explain where and how to implement custom business logic for different payment scenarios.
Subscriptions
Subscription access is managed automatically based on the duration you configure when creating your offering. If you need to implement additional logic, such as awarding credits, coins, or other custom actions for subscribers, handle it in the following file: supabase/functions/stripe-webhook/_events/subscription_events.ts
.
One time payments
To handle one-time payments, edit the file supabase/functions/stripe-webhook/_events/checkout_events.ts
and follow the instructions marked with comments starting with // ! ...
.
Free Trials
Note
Free trials can only be offered for subscriptions; they are not supported for one-time payments.
Free trials are a great way to let users experience your app’s premium features before committing to a subscription. With Floot and Stripe, you can easily offer free trials to your users and control their duration. The following section explains how to enable and manage free trials.
Setup
You have 2 ways of enabling it.
Important
Ensure that webhook events are correctly forwarded to your Supabase instance. Learn more in the Events Redirection section.
This option is recommended because it allows you to keep track of the free trials you are currently offering via your Stripe Dashboard.
Stripe Dashboard → Products section and create a new product or select an existing one.
Under the Pricing section, create a new price or edit an existing one.
In the Metadata section, add a key named trial_days
and set its value to the number of free trial days you want to offer.
For example, to provide a 7-day free trial, enter 7
as the value. This will trigger a price.updated
webhook event,
ensuring the trial period is synced with your Supabase database.
Important
This method assumes you have already set up your products and prices as described in the Products & prices section, so they are available in your Supabase database.
Just run this command in your Supabase SQL editor.
UPDATE prices
SET trial_days = 7
WHERE id = '<your_price_id>';
Note: Changes made using this method will not appear in your Stripe Dashboard. To view the current free trial settings, you will need to check your Supabase database directly.
Allowing Multiple Free Trials per User
By default, each user can only benefit from a free trial once. If you want to allow users to access a trial again, you can remove their trial records from the database, either manually or automatically. For example, you might schedule a cron job to periodically delete trial records that ended more than a period ago.
Example: Deleting trials that ended over a year ago.
DELETE FROM users_trials
WHERE end_date < (NOW() AT TIME ZONE 'UTC') - INTERVAL '1 year';
Stripe on Mobile
By default, the paywall uses Stripe for all platforms except mobile (Android & iOS), where RevenueCat is the standard. However, you can enable Stripe for mobile platforms as well by following the instructions in this section.
To activate Stripe on mobile (iOS and Android), simply enable it in your Flutter environment file.
ENABLE_STRIPE_MOBILE=true
Since payments on mobile are processed through an external webview, ensure your app's URL scheme is properly configured to redirect users back to the app after payment. Refer to the app URL scheme setup in this section.