Stripe powers our payment system, offering robust processing, subscription management, and global support.

Stripe Setup

  1. Create a Stripe account or sign in.
  2. Configure your account and add products or subscription plans.
  1. Navigate to Product Catalogue in the Stripe Dashboard.
  2. Click “Create product” and input details. For our credit system, we’ll use one-off payments.
  3. On the product page, create price variations (e.g., credits-small for 50 credits, credits-large for 100 credits).
  4. Select “Create payment link” and configure settings.
  5. Add custom metadata in the payment link settings:
    • Click “Add metadata”
    • Set a key (e.g., “type”) and value (e.g., “credits-large”)

This metadata is crucial for determining the purchase type in your webhook handler.

Webhook Configuration

Stripe Webhook Secret

  1. Go to Developers -> Webhooks in the Stripe Dashboard.
  2. Click “Add endpoint”.
  3. Set the Endpoint URL to https://yourwebsite.com/api/payments/stripe.
  4. Select events to listen for (at minimum, choose “checkout.session.completed”).
  5. Copy the Signing secret and add it to your .env file as STRIPE_WEBHOOK_SECRET.

Also add your Stripe secret key to .env as STRIPE_SECRET_KEY. Find this under Developers -> API Keys.

Webhook Handling

The API route at app/api/payments/stripe/route.ts manages Stripe payments and subscriptions:

  1. Verifies request legitimacy using STRIPE_WEBHOOK_SECRET.
  2. Processes the “checkout.session.completed” event.
  3. Retrieves product information and determines purchase type from metadata.
  4. Matches user email with the profiles table:
    • For matching users, updates the purchase column in profiles.
    • For non-matching users, records the purchase in purchases.
    • Performs specific actions based on metadata (e.g., adding user credits).

Database Setup

The purchases table should already exist if you followed the Quick Setup guide and ran the Supabase migrations using the CLI:

npx supabase db push

If you haven’t done this yet, please go back to the Quick Setup guide first. Alternatively, you can manually create the table by running the SQL from this file in your Supabase SQL editor: supabase/migrations/20240000000007_purchases.sql

Make sure RLS is turned on. We don’t need to add any rules as we’ll be using the service key for to interact with this table.

Purchase Type Determination

The webhook handler identifies the purchase type in this order:

  1. Checks session.metadata.type (set in payment link).
  2. If not found, checks product.metadata.type.
  3. If still not found, infers from the product name (premium, core, or enterprise).

This prioritization allows precise control over purchase types via payment link metadata.

User Profile Updates

After a successful purchase, the webhook handler:

  1. Records the purchase in the purchases table.
  2. Updates the user’s profile in the profiles table with the new purchase type.

Customize the updateUserProfile function in @/lib/hooks/userData to handle various purchase or subscription types based on metadata.

Paywall Implementation

Demo apps include a credit-based paywall system that uses cached queries for better performance. Here’s how it works:

app/(apps)/audio/(app)/app/page.tsx
import {
  getSession,
  getUserCredits,
  getUserRecordings,
} from "@/lib/db/cached-queries";

export default async function Page() {
  const user = await getSession();

  let credits;
  let recordings;

  if (user) {
    if (toolConfig.paywall) {
      credits = await getUserCredits(user.id);

      if (credits < toolConfig.credits) {
        return <PaymentModal />;
      }
    }
    // ... rest of the code

The paywall logic:

  1. Check if the demo app is paywalled (defined in toolConfig.ts).
  2. Uses cached queries to efficiently verify user credit balance:
    • If sufficient, grant access.
    • If insufficient, display the PaymentModal.

The cached queries system helps reduce database load and improve performance compared to direct Supabase queries.

Payment Flow Implementation

  1. Create a UI element linking to your Stripe payment URL.
  2. Stripe sends a webhook to your endpoint upon purchase completion.
  3. Your webhook handler processes the payment, using metadata to determine the purchase type.
  4. Update the user’s profile in your database with purchase information.
  5. Grant access to premium features based on the updated profile.

This flow, combined with payment link metadata, enables easy management of product tiers and database updates for purchases.