Skip to content

Stripe (Payments)

Set up Stripe to accept payments through hosted Checkout sessions.

Prerequisites

  • A Stripe account (test mode for development, live mode for production)
  • Your deployment URL for webhook configuration

How it works

tripplan.ing uses Stripe hosted Checkout — attendees are redirected to a Stripe-hosted page to enter payment details. No card fields are rendered on your site. After payment, Stripe sends a webhook to confirm the transaction and the payment record is updated automatically.

Create a Stripe account

Sign up at stripe.com. New accounts start in test mode, which lets you simulate payments without real charges.

Get your API keys

  1. In the Stripe dashboard, navigate to DevelopersAPI Keys
  2. Copy the Secret key — this is the value for STRIPE_SECRET_KEY

TIP

Start with test keys (sk_test_...) during development. Switch to live keys (sk_live_...) only when deploying to production.

The publishable key is not needed — tripplan.ing uses server-side Checkout sessions exclusively.

Create a webhook endpoint

  1. In the Stripe dashboard, navigate to DevelopersWebhooks
  2. Click Add endpoint
  3. Set the endpoint URL to https://<your-domain>/api/stripe/webhook
  4. Subscribe to the event: checkout.session.completed
  5. Click Add endpoint
  6. Copy the Signing secret — this is the value for STRIPE_WEBHOOK_SECRET

Only checkout.session.completed is required. tripplan.ing does not listen for other Stripe events.

WARNING

Each deployment environment (development, production) needs its own webhook endpoint pointing to its own URL. Create separate endpoints for each.

Configure tripplan.ing

Map your Stripe credentials to environment variables:

Stripe valueEnvironment variableExample
Secret keySTRIPE_SECRET_KEYsk_test_abc123...
Webhook signing secretSTRIPE_WEBHOOK_SECRETwhsec_abc123...

For local development, add these to .dev.vars:

bash
STRIPE_SECRET_KEY=sk_test_abc123...
STRIPE_WEBHOOK_SECRET=whsec_abc123...

For production, set these as GitHub Environment secrets (see Environment & Secrets).

Per-event overrides

Events can use different Stripe accounts by setting per-event credentials in /admin/settings:

Event settingOverridesPurpose
stripeSecretKeySTRIPE_SECRET_KEYUse a separate Stripe account for this event
stripeWebhookSecretSTRIPE_WEBHOOK_SECRETWebhook secret for the per-event Stripe account

The fallback chain is: per-event setting → global environment variable. If an event has no override, it uses the global credentials.

When using a per-event Stripe account, create a separate webhook endpoint in that Stripe account pointing to the same https://<domain>/api/stripe/webhook URL.

Test mode vs live mode

Test modeLive mode
Key prefixsk_test_...sk_live_...
Real chargesNoYes
Test cards4242 4242 4242 4242Real card numbers
Webhook eventsSimulatedReal
Use forDevelopment, stagingProduction

Use test keys in your development environment and live keys in production. Never mix test and live keys in the same environment.

Verify it works

  1. Start the dev server with make dev
  2. Create an event with at least one add-on in /admin/add-ons
  3. Visit /pay on the event subdomain
  4. Select an item and click "Pay"
  5. On the Stripe checkout page, use test card 4242 4242 4242 4242 with any future expiry and any CVC
  6. After redirect, check /admin/payments — the payment should show as completed

If the payment shows as completed in Stripe but pending in the admin, the webhook was not delivered — see troubleshooting below.

Troubleshooting

SymptomFix
Checkout page doesn't openVerify STRIPE_SECRET_KEY is set and valid; check server logs for API errors
Checkout works but payment stays pendingWebhook not delivered — verify endpoint URL and signing secret in Stripe dashboard
"No signatures found matching the expected signature"STRIPE_WEBHOOK_SECRET doesn't match the endpoint; regenerate and update
"Invalid API Key provided"Key is expired or from wrong mode (test vs live); copy a fresh key from Stripe
Webhook endpoint shows errors in StripeCheck the error details in DevelopersWebhooksEndpointAttempts
Per-event override not workingConfirm the override values are saved in /admin/settings; the event falls back to global if empty

Released under the MIT License.