PayPal Payments Setup

This guide covers configuring PayPal for PWASK, handling one-time and subscription flows, and wiring the webhook to Supabase.

Prerequisites

  • PayPal Business account
  • Supabase project with service role key
  • CLI: pnpm

1) Environment Variables

Add to .env.local (and your hosting env):

PAYPAL_CLIENT_ID=your_paypal_client_id
PAYPAL_SECRET=your_paypal_secret
# Optional: override API base for sandbox/local testing
# PAYPAL_API_BASE_URL=https://api-m.sandbox.paypal.com

# Subscription plan IDs (from PayPal Billing Plans)
PAYPAL_ESSENTIAL_MONTHLY_PLAN_ID=
PAYPAL_ESSENTIAL_YEARLY_PLAN_ID=
PAYPAL_CREATOR_MONTHLY_PLAN_ID=
PAYPAL_CREATOR_YEARLY_PLAN_ID=

Tip: Keep sandbox credentials in dev/preview, live credentials in production.

2) Webhook Configuration

Endpoint: /api/checkout/paypal/webhook

In PayPal Dashboard → App settingsWebhooks, add your deployed URL (e.g., https://yourdomain.com/api/checkout/paypal/webhook). Subscribe to events you need; the app handles:

  • CHECKOUT.ORDER.APPROVED
  • BILLING.SUBSCRIPTION.CREATED
  • BILLING.SUBSCRIPTION.ACTIVATED
  • BILLING.SUBSCRIPTION.CANCELLED
  • PAYMENT.SALE.COMPLETED

3) Pricing & Plans

  • One-time (lifetime) purchases use the standard PayPal Checkout order flow.
  • Subscriptions use PayPal Billing Plans. Set the plan IDs via the env vars above.

4) Checkout Flows

  • One-time: /payment renders the PayPal button for lifetime; /api/checkout/paypal creates an order with intent: CAPTURE.
  • Subscription: for billing=monthly|yearly, the PayPal button redirects users to the subscription approval URL from /api/checkout/paypal.

5) Webhook Behavior

  • Verifies PayPal events and normalizes order/subscription data.
  • Upserts users and profiles in Supabase using the service role key.
  • Logs payments into payments with PayPal IDs (paypal_order_id, paypal_capture_id, paypal_subscription_id).
  • Sends confirmation email via /api/sendmail when a valid email is present.

6) Database & Migration

supabase/migrations/20251030121500_add_payments_table.sql includes PayPal columns and indexes. Ensure migrations are applied:

pnpm supabase db push

7) Testing

  • Sandbox: use PayPal sandbox accounts and PAYPAL_API_BASE_URL pointing to https://api-m.sandbox.paypal.com.
  • Trigger test payments on /payment (lifetime) or with ?billing=monthly|yearly for subscriptions.
  • Check payments table in Supabase and webhook logs.

8) Production Checklist

  • Switch to live PayPal credentials and plan IDs.
  • Ensure webhook endpoint is using HTTPS and reachable externally.
  • Keep SUPABASE_SERVICE_ROLE_KEY server-only.
  • CSP already allows PayPal domains in next.config.ts.

Related Documentation

Related Documentation