Stripe Payments
Implementing secure payments and paywalls with Stripe
Stripe powers our payment system, offering robust processing, subscription management, and global support.
Stripe Setup
- Create a Stripe account or sign in.
- Configure your account and add products or subscription plans.
Product and Payment Link Creation
- Navigate to
Product Catalogue
in the Stripe Dashboard. - Click “Create product” and input details. For our credit system, we’ll use one-off payments.
- On the product page, create price variations (e.g., credits-small for 50 credits, credits-large for 100 credits).
- Select “Create payment link” and configure settings.
- 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
- Go to
Developers -> Webhooks
in the Stripe Dashboard. - Click “Add endpoint”.
- Set the Endpoint URL to
https://yourwebsite.com/api/payments/stripe
. - Select events to listen for (at minimum, choose “checkout.session.completed”).
- Copy the Signing secret and add it to your
.env
file asSTRIPE_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:
- Verifies request legitimacy using
STRIPE_WEBHOOK_SECRET
. - Processes the “checkout.session.completed” event.
- Retrieves product information and determines purchase type from metadata.
- Matches user email with the
profiles
table:- For matching users, updates the
purchase
column inprofiles
. - For non-matching users, records the purchase in
purchases
. - Performs specific actions based on metadata (e.g., adding user credits).
- For matching users, updates the
Storing webhook data
We’ll store all webhook data coming from LemonSqueezy in our own database as well.
Copy-paste the following your Supabase SQL editor:
Then, turn on RLS. 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:
- Checks
session.metadata.type
(set in payment link). - If not found, checks
product.metadata.type
. - 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:
- Records the purchase in the
purchases
table. - 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. Modify app/api/payments/stripe/route.ts
to add credits after successful purchases.
Adjust the code to manage access based on specific purchase
column values
for handling lifetime access or subscriptions.
Paywall Logic Flow
- Check if the demo app is paywalled (defined in
toolConfig.ts
). - Verify user credit balance:
- If sufficient, grant access.
- If insufficient, display the
PaymentModal
.
Payment Flow Implementation
- Create a UI element linking to your Stripe payment URL.
- Stripe sends a webhook to your endpoint upon purchase completion.
- Your webhook handler processes the payment, using metadata to determine the purchase type.
- Update the user’s profile in your database with purchase information.
- 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.