Stripe Payments

    This guide helps you set up Stripe payments for local testing and production. A webhook is already configured to handle successful and abandoned payments, refunds and storing transactions in your database.

    Follow the steps below to complete the setup.

    Testing Locally

    Steps

    1. Login to https://dashboard.stripe.com/
    2. Enable Test mode top right corner
    3. Click Developers bottom left corner
    4. Select the API keys tab
    5. Copy your Secret Key (starts with sk_test_)
    6. Paste it in .env.local -> STRIPE_KEY=sk_test_***
    7. Install Stripe CLI Guide
    8. Enter these commands in the command line

    Terminal

    stripe login
    stripe listen --forward-to http://localhost:3000/api/webhooks/stripe
    
    1. Now copy the webhook signing secret (starts with whsec_)
    2. Paste it in .env.local -> STRIPE_WEBHOOK_SECRET=whsec_***
    # These are the required keys for stripe
    STRIPE_KEY=******
    STRIPE_WEBHOOK_SECRET=******
    STRIPE_DASHBOARD_LINK=https://dashboard.stripe.com/test # use https://dashboard.stripe.com/ for deployment
    

    🎉 Local testing settings are now ready!

    Production

    Steps

    1. Login to https://dashboard.stripe.com/
    2. Click Developers bottom left corner
    3. Select the API keys tab
    4. Copy your Secret Key (starts with sk_live_)
    5. Add it to your production environment variables -> STRIPE_KEY=sk_live_***
    6. On the same page select the Webhooks tab
    7. Click + Add Endpoint
    8. Enter Endpoint URL -> https://your_app_domain/api/webhooks/stripe
    9. Click Select events and search and add these events
      • checkout.session.completed (successful payments)
      • checkout.session.expired (abandoned checkout)
      • invoice.paid (invoice payments)
      • charge.refunded (payment refunded/partially-refunded)
      • charge.refund.updated (refund cancelled e.g. canceled from stripe's dashboard/side)
      • customer.subscription.updated (subscription updates)
      • customer.subscription.deleted (subscription cancellation)
      • customer.created (customer creation)
    10. Click Add Events then Add endpoint
    11. Under Signing secret, click Reveal and copy the value
    12. Add it to your production environment variables -> STRIPE_WEBHOOK_SECRET=whsec_***

    🎉 Production settings are now ready!

    Configure your stripe settings

    /src/utils/config.ts

    const config = {
      // Stripe payment configuration.
      stripe: {
        currency: "usd", // Default currency for transactions.
        // choose redirect url for production and development environments
        // for successful or cancelled payments
        redirect: {
          // redirects that happen under /api/stripe/checkout
          orders: {
            successUrl: isProduction
              ? "https://example_domain.com/account/access"
              : "http://localhost:3000/account/access",
            cancelUrl: isProduction
              ? "https://example_domain.com/#pricing"
              : "http://localhost:3000/#pricing",
          },
          // redirects that happen under /api/stripe/subscribe
          subscriptions: {
            successUrl: isProduction
              ? "https://example_domain.com/account/access"
              : "http://localhost:3000/account/access",
            cancelUrl: isProduction
              ? "https://example_domain.com/#pricing"
              : "http://localhost:3000/#pricing",
          },
        },
      },
      //...
    };
    

    Update webhooks logic

    You can skip this step until you decide what you want to do on successful purchases or refunds, you will still test purchases/refunds.

    Stripe webhooks are located under src/app/api/webhooks/stripe/route.ts

    But to keep things clean and readable I have created src/app/api/webhooks/stripe/_helpers/index.ts to include all the logic.

    Typically you would want to handle giving/revoke access to your products here in case of a successful checkout/refund

    Search for TODO in the same file to understand where to add or update your logic.

    Your first test payment walkthrough

    1. Make sure you have a working dashboard
    2. Navigate to /dashboard/products, click New and create a product
    3. Copy the ID of the newly created product using the Copy ID button at the top
    4. Add the product ID to config.ts

    config.ts

    const config = {
      // ...
      products: {
        cta: {
          id: isProduction
            ? "677020c8c7d53caf4573a757" // production product id
            : "677020c8c7d53caf4573a757", // development product id
        },
      },
      // ...
    };
    
    1. If your CTA product is a subscription update the CTAButton component mode to subscription

    /src/components/CTAButton.tsx

    const CTAButton: FC<OmitKeys<ButtonProps, "children">> = ({
      className,
      ...rest
    }) => {
      const productId = config.products.cta.id;
    
      return productId ? (
        <BuyButton
          size="lg"
          mode="subscription" // update here
          className={cn("w-full md:w-64", className)}
          productId={productId}
          aria-label={`Get ${config.app.name}`}
          {...rest}
        >
          <ShipIcon className="mr-2" /> <span>Get {config.app.name}</span>
        </BuyButton>
      ) : (
        <ErrorMessage>CTA Product ID missing from ENV</ErrorMessage>
      );
    };
    
    1. Go to the home page and press the CTA button.

    🎉 Payments are now ready!

    Useful Components