Skip to main content

Documentation Index

Fetch the complete documentation index at: https://grantmaster.dev/llms.txt

Use this file to discover all available pages before exploring further.

Stripe Payment Setup

Developer guide for configuring Stripe payments in GrantMaster — local development, staging, and production.

Prerequisites

  • A Stripe account (test mode is fine for local dev)
  • Firebase CLI installed (npm install -g firebase-tools)
  • GrantMaster repo cloned and dependencies installed

Architecture Overview

Browser (Stripe.js + Elements)

  ├─ Publishable key (pk_*) — loaded from VITE_STRIPE_PUBLISHABLE_KEY
  │  Used only for Stripe Elements (card inputs, Payment Element)

  └─ Cloud Functions (Firebase)
       ├─ Secret key (sk_*) — stored in STRIPE_SECRET_KEY env/secret
       ├─ Webhook secret (whsec_*) — stored in STRIPE_WEBHOOK_SECRET

       ├─ callableHandlers.ts    — checkout, portal, list invoices/methods
       ├─ paymentMethods.ts      — attach, detach, SetupIntent, set default
       ├─ subscriptionOperations.ts — tier changes, cancel, reactivate
       ├─ subscriptionManagement.ts — seats, usage sync, cost preview
       ├─ paymentSettings.ts     — billing address, tax, invoice footer
       └─ webhookHandlers.ts     — 11 event types, idempotent processing
All sensitive Stripe operations run server-side. The frontend only uses the publishable key for Stripe Elements.

Step 1: Get Your Stripe API Keys

  1. Go to Stripe Dashboard → API keys
  2. Copy your Publishable key (pk_test_... or pk_live_...)
  3. Copy your Secret key (sk_test_... or sk_live_...)
Security: Never commit secret keys to version control. Never expose sk_* keys in frontend code.

Step 2: Configure Environment Variables

Frontend (.env.local)

# Safe to store locally — publishable keys are designed for client-side use
VITE_STRIPE_PUBLISHABLE_KEY=pk_test_your_publishable_key_here

Cloud Functions (functions/.env)

For local emulator development, copy and fill in:
cp functions/.env.example functions/.env
Required variables in functions/.env:
STRIPE_SECRET_KEY=sk_test_your_secret_key_here
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_signing_secret
APP_URL=http://localhost:3000

Production / Staging

Use Firebase Functions secrets (never plain env files in deployed environments):
firebase functions:secrets:set STRIPE_SECRET_KEY
firebase functions:secrets:set STRIPE_WEBHOOK_SECRET

Automated Setup Script

A helper script is available that prompts for keys interactively:
bash scripts/setup-stripe-keys.sh
It accepts environment variables or prompts, validates key formats, stores the secret key in Firebase, and writes the publishable key to .env.local.

Step 3: Create Stripe Products & Prices

GrantMaster uses three subscription tiers. Create these in Stripe Dashboard → Products:
TierMonthly Price IDYearly Price ID
Starter (Potential)price_...price_...
Professionalprice_...price_...
Ultimateprice_...price_...
Each tier also needs seat add-on prices (monthly + yearly). After creating prices, update the IDs in src/config/subscriptionTiers.ts:
stripeMonthlyBasePriceId: 'price_your_id_here',
stripeYearlyBasePriceId: 'price_your_id_here',
stripeMonthlySeatPriceId: 'price_your_id_here',
stripeYearlySeatPriceId: 'price_your_id_here',
And set the corresponding env vars for webhook tier resolution in Cloud Functions:
STRIPE_PRICE_POTENTIAL_MONTHLY=price_...
STRIPE_PRICE_POTENTIAL_YEARLY=price_...
STRIPE_PRICE_PROFESSIONAL_MONTHLY=price_...
STRIPE_PRICE_PROFESSIONAL_YEARLY=price_...
STRIPE_PRICE_ULTIMATE_MONTHLY=price_...
STRIPE_PRICE_ULTIMATE_YEARLY=price_...

Step 4: Configure Webhooks

Production

  1. Go to Stripe Dashboard → Webhooks
  2. Add endpoint: https://<region>-<project-id>.cloudfunctions.net/stripeWebhook
  3. Select these events:
    • checkout.session.completed
    • customer.subscription.created
    • customer.subscription.updated
    • customer.subscription.deleted
    • customer.subscription.trial_will_end
    • customer.updated
    • invoice.payment_succeeded
    • invoice.payment_failed
    • payment_method.attached
    • payment_method.detached
    • charge.dispute.created
  4. Copy the signing secret → store as STRIPE_WEBHOOK_SECRET

Local Development

Use the Stripe CLI to forward webhooks to your emulator:
stripe listen --forward-to http://localhost:5001/<project-id>/<region>/stripeWebhook
The CLI prints a webhook signing secret (whsec_...) — add it to functions/.env.

Step 5: Verify the Integration

Stripe.js Loading

index.html includes <script src="https://js.stripe.com/v3/"></script>. Verify it loads in your browser’s Network tab.

Content Security Policy

firebase.json includes CSP headers allowing:
  • script-src: https://js.stripe.com, https://m.stripe.network
  • connect-src: https://api.stripe.com, https://m.stripe.network
  • frame-src: https://js.stripe.com, https://m.stripe.network

Test Card Numbers

Use Stripe test cards:
Card NumberScenario
4242 4242 4242 4242Successful payment
4000 0000 0000 32203D Secure authentication required
4000 0000 0000 9995Payment declined

Troubleshooting

“STRIPE_SECRET_KEY not configured” — Cloud Functions can’t find the secret key. Check functions/.env (local) or run firebase functions:secrets:access STRIPE_SECRET_KEY (deployed). “Webhook secret not configured” — Set STRIPE_WEBHOOK_SECRET in functions/.env or Firebase secrets. Payment settings return “permission denied” — The verifyOrganizationAccess function checks people/{uid} for org membership. Ensure the user’s people doc has the correct organizationId and an Admin/Super Admin systemRole. Callable functions fail with “failed-precondition” — App Check is enforced in production. In the emulator, App Check is skipped automatically.

File Reference

FilePurpose
src/features/billing/services/stripePaymentService.tsFrontend service — all Stripe operations via Cloud Functions
src/features/billing/services/stripeModuleBilling.tsModule add-on billing service
src/config/subscriptionTiers.tsTier definitions with Stripe price IDs
src/lib/runtimeEnv.tsValidates VITE_STRIPE_PUBLISHABLE_KEY at build time
functions/src/stripe/client.tsStripe client initialization + auth helpers
functions/src/stripe/callableHandlers.tsCheckout, portal, invoices, payment methods
functions/src/stripe/paymentMethods.tsAttach/detach/SetupIntent/default
functions/src/stripe/subscriptionOperations.tsTier changes, cancel, reactivate
functions/src/stripe/subscriptionManagement.tsSeats, usage sync, cost preview
functions/src/stripe/paymentSettings.tsBilling address, tax, invoice footer
functions/src/stripe/webhookHandlers.tsWebhook processing (11 event types)
functions/src/stripe/idempotency.tsWebhook deduplication
functions/src/stripe/stateMachine.tsSubscription state machine
scripts/setup-stripe-keys.shInteractive key setup script