🚀 Join the waitlist now! waitlist.floot.dev
LogoFlootdocs
Payments

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.

supabase/db_seeds/vault.sql
-- 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.

supabase/.env.local
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.

Terminal
stripe login

You'll be prompted to open a browser window to complete the login process.

Redirect Stripe events to your Supabase local instance.

Terminal
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.

supabase/.env.local
STRIPE_WEBHOOK_SECRET="whsec_..."

Serve the Supabase functions locally to handle Stripe webhooks.

Terminal
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.

Terminal
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.

supabase/.env*
# 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.

.env*
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.