How to Integrate Stripe with NextJS+Supabase Application - Initial Hook up.

July 2, 2024

Integrating Stripe with Next.js can significantly enhance your web application by providing seamless payment solutions. Here's a step-by-step guide to get you started. Note: You need to have an existing Next.js application before proceeding with these steps.

1. Create a Developer Stripe Account

First, you'll need to create a developer account on Stripe. This will allow you to manage products and access API keys.

  • Create items to subscribe to:

  • Get your API keys:

    • Access your API keys from the API keys page.
    • Add these keys to your project's .env.local file:
      NEXT_PUBLIC_STRIPE_KEY=your_public_key
      STRIPE_SECRET_KEY=your_secret_key
      

2. Add Stripe Package to Your Project

To start using Stripe in your Next.js project, install the Stripe package:

npm add stripe

Later, you can initialize Stripe in your code like this:

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
const customer = await stripe.customers.create();

3. Create a Profile Table in Your Database

You'll need a profile table in your database to keep track of user subscription information. This table is different from the user table that stores authentication details.

The table should have the following columns:

user_id, is_subscribed, stripe_customer_id, interval

4. Fill the Profile Table When a User Signs Up

To correlate your users with Stripe customer objects, fill the profile table upon user registration:

  • Use a DB trigger from the auth table:
    • In Supabase, add a DB webhook that triggers when a new user is inserted into the user table. You can do this from the Supabase Hook Dashboard.

    • For local development, use ngrok to expose your local development server to the outside internet:

      ngrok http 3000
      

      This will provide a URL like https://some-random-text.ngrok-free.app which you can use in your webhooks.

    • Create the webhook in your Next.js app:

      • Add the webhook handler in your Next.js application so that your Supabase hooks can reach it:
      export async function POST(request: Request) {
          const { searchParams } = new URL(request.url);
          if (searchParams.get('API_ROUTE_SECRET_KEY') !== process.env.API_ROUTE_SECRET_KEY) {
              return new Response('Unauthorized', { status: 401 });
          }
      
          const supabase = createServiceClient();
          const { data: profileData } = await supabase
              .from('profile')
              .select('id, is_subscribed')
              .eq('id', user_id)
              .single();
      
          if (!profileData) {
              const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
              // ... create a Stripe customer object and insert into the profile table
          }
      
          return Response.json({ message: 'OK' });
      }
      
    • Since Stripe initiated this request, there are not authentication details associated with this request. We need to add a special service role for Supabase to bypass row-level security if this webhook handler is triggered.

      • Create a new function createServiceClient() to bypass row-level security when inserting data into the profile table:

        • Add the service_role key to your .env.local file:
        SUPABASE_SERVICE_KEY=your_service_key
        
      • For additional security. We will secure the HTTP hook to prevent unauthorized access:

        • Generate a secure key in Node.js:
        require('crypto').randomBytes(32).toString('hex');
        
        • Add this key to your .env.local file:
        API_ROUTE_SECRET_KEY=your_generated_key
        
        • In the Supabase database hooks, add this secret to the HTTP parameters.

By following these steps, you can successfully integrate Stripe with your Next.js application, enabling robust payment functionalities and subscription management.