Lovable + Stripe Integration: Webhooks, API Keys, PCI Compliance

To connect Stripe to a Lovable app securely, you need to: (1) keep Secret Keys server-side only, (2) verify webhook signatures on every event, (3) use Stripe Checkout or Elements for PCI compliance, and (4) create payment intents on the server. This integration guide covers key management, webhook security, and payment flow patterns.

Setup Time1-2 hours

TL;DR

Stripe integration requires careful key management and webhook verification. Key rules: never expose the Secret Key (sk_*) in client code, always verify webhook signatures, use Stripe Checkout or Elements for PCI compliance, and create payment intents on the server only. Test with Stripe's test mode before going live.

Stripe Key Management

Key TypePrefixWhere to Use
Publishable Keypk_test_ / pk_live_Client-side (safe to expose)
Secret Keysk_test_ / sk_live_Server-side only (NEVER expose)
Webhook Secretwhsec_Server-side only

Part 1: Stripe Environment Variables

Environment configuration
# Client-side (safe)
VITE_STRIPE_PUBLISHABLE_KEY=pk_test_xxx

# Server-side only (NEVER in client code)
STRIPE_SECRET_KEY=sk_test_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxx

Critical: If the Secret Key (sk_*) is ever exposed, rotate it immediately in the Stripe dashboard. An exposed key allows full access to your Stripe account.

Part 2: Stripe Webhook Verification

Verify webhook signatures
import Stripe from 'stripe';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

export async function handleWebhook(request: Request) {
  const body = await request.text();
  const signature = request.headers.get('stripe-signature');

  let event: Stripe.Event;

  try {
    event = stripe.webhooks.constructEvent(
      body,
      signature!,
      process.env.STRIPE_WEBHOOK_SECRET!
    );
  } catch (err) {
    console.error('Webhook signature verification failed');
    return new Response('Invalid signature', { status: 400 });
  }

  // Handle the verified event
  switch (event.type) {
    case 'checkout.session.completed':
      // Fulfill the purchase
      break;
    case 'payment_intent.succeeded':
      // Handle successful payment
      break;
  }

  return new Response('OK', { status: 200 });
}

Part 3: Stripe Payment Flow

Create checkout session (server-side)
// This must run on the server, not the client
export async function createCheckoutSession(userId: string, priceId: string) {
  const session = await stripe.checkout.sessions.create({
    customer_email: userEmail,  // Or use customer ID
    line_items: [{ price: priceId, quantity: 1 }],
    mode: 'subscription',
    success_url: `${process.env.APP_URL}/success?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${process.env.APP_URL}/cancel`,
    metadata: { userId },  // For webhook processing
  });

  return session.url;
}

Security Checklist

Pre-Launch Checklist for Lovable + Stripe

Secret Key only in server-side code

Webhook signature verification implemented

Using Stripe Checkout or Elements (PCI compliance)

Payment intents created server-side only

Test mode used for development

Live keys in production environment only

Webhook endpoint secured (HTTPS)

Idempotency keys used for retries

Is the publishable key safe to expose?

Yes, the publishable key (pk_*) is designed for client-side use. It can only be used to create tokens or confirm payments, not to read data or make charges.

Why verify webhook signatures?

Without verification, attackers could send fake webhook events to your endpoint, potentially granting free access or disrupting your service. Always verify the stripe-signature header before processing any event.

Does Stripe Checkout make my Lovable app PCI compliant?

Using Stripe Checkout or Stripe Elements means card data never touches your server, which covers most PCI DSS scope for small SaaS apps. You still need HTTPS and must not log card data anywhere in your Lovable app.

Integrating Stripe with Lovable?

Scan for key exposure and webhook issues.

Security Blueprints

Lovable + Stripe Integration: Webhooks, API Keys, PCI Compliance