# Payments Setup One env value turns payments on. Development runs without it, on the test checkout. Production refuses to build or start without it. ## Config ```jsoc // config.jsoc { // ... stripe: { // Required: a build without it fails. Development sets it empty. secretKey: env!("STRIPE_SECRET_KEY"), // Development only, printed by `stripe listen`. Production registers its // own endpoint and stores the secret (see `payments/webhook`). webhookSecret: env("STRIPE_WEBHOOK_SECRET", ""), }, } ``` Put empty placeholders in `config/env/development.env`, and nothing else: ```text config/env/development.env STRIPE_SECRET_KEY= STRIPE_WEBHOOK_SECRET= ``` `development.env` is committed, so the owner's key goes in their copy, or in the shell environment, which env values read first. An edit to the env file rebuilds the config and hot reloads the app and its open pages, so pay buttons switch from the test checkout to Stripe the moment the key is saved. Live keys go in `config/env/production.env`, which is gitignored. A production build with no `STRIPE_SECRET_KEY` line is a build error, so a deploy without the key never goes out. ## The Client ```ts // app/shared/stripe.ts import Stripe from "stripe"; import { getEnv } from "@elements/app"; import config from "#config"; let client: Stripe | undefined; export function stripeConfigured(): boolean { return config.stripe.secretKey !== ""; } /** True when payments go through the in-app test checkout instead of Stripe. */ export function testCheckout(): boolean { return !stripeConfigured() && getEnv() !== "production"; } export function stripe(): Stripe { client ??= new Stripe(config.stripe.secretKey); return client; } ``` An empty key in production is refused at startup, before the app serves a request. Put the check in `index.ts`, ahead of `app.start`: ```ts // index.ts if (getEnv() === "production" && !stripeConfigured()) { throw new Error("STRIPE_SECRET_KEY is required in production."); } ``` So a running app can always take a payment: through Stripe when the key is set, through the test checkout when it is not. Pay buttons are always shown; there is no "not set up" state to build. ## Telling the Owner The final report names the one step left: create a free Stripe account at dashboard.stripe.com/register (a sandbox works right away, with no business details), open Developers, API keys, copy the secret key (`sk_test_...`), and add it to `config/env/development.env` as `STRIPE_SECRET_KEY=`. Until then the test checkout stands in. Do not build a settings or setup page for this; the env file is the setting. ## Related - `payments/checkout`: the checkout rpc, the test checkout, and fulfillment. - `payments/webhook`: the webhook route and its registration. - `config`: env files and `getEnv()`.