Document a concrete Stripe activation checklist

Everything code-side is already live — this is purely the remaining
provisioning steps (test keys -> Coolify -> backend .env -> redeploy ->
end-to-end test -> live keys), so the next person doesn't have to
reconstruct the sequence from scattered comments.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Marco
2026-07-25 16:17:32 +00:00
parent f959ebb998
commit 952b902702
+62
View File
@@ -412,6 +412,68 @@ Stripe API call itself that's faked. That test-confirm route hard-404s
whenever `PAYMENT_TEST_MODE` isn't explicitly true, so it can never become
a reachable "mark any order paid" endpoint in production.
**Activating real Stripe payments — checklist.** Everything code-side is
already live (both `main` branches deployed); this is purely
provisioning. Nothing here is required to *test* the flow today —
`PAYMENT_TEST_MODE` already works end to end with zero Stripe account.
Already done, as of 2026-07-25:
- [x] `PAYMENT_WEBHOOK_SECRET` set in Coolify, matches the backend's copy
in `docker/.env` — needed even in test mode (the test-confirm route
sends it as a header the backend checks).
- [x] `payment-methods` rows configured: Kreditkarte/PayPal →
`provider: 'stripe'`; "Überweisung (Vorkasse)" → `provider: 'manual'`
(untouched by anything below); "Sofortüberweisung" prepared as
`provider: 'stripe'` but `active: false` (needs a logo before switching
on — see the backend's own README).
- [x] Database migration applied to production, confirmed live.
Still needed, in order:
1. **Create a Stripe account** (free). Stay in **test mode** first (toggle
top of the Stripe dashboard) — nothing below moves real money until
step 5.
2. **Copy the test API keys***Entwicklerbereich → API-Schlüssel*:
`sk_test_...` and `pk_test_...`.
3. **Create a webhook endpoint** — *Entwicklerbereich → Webhooks → Endpoint
hinzufügen*, URL `https://einfach-produktiv.mk360.de/api/webhooks/stripe`,
events: at minimum `payment_intent.succeeded` and
`payment_intent.payment_failed`. Copy the signing secret, `whsec_...`.
4. **Set these three in Coolify** (`einfach-produktiv` app → Environment
Variables):
| Variable | Value |
|---|---|
| `STRIPE_SECRET_KEY` | `sk_test_...` |
| `NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY` | `pk_test_...` |
| `STRIPE_WEBHOOK_SECRET` | `whsec_...` |
The moment `STRIPE_SECRET_KEY` is set, `PAYMENT_TEST_MODE` switches off
automatically (see above) — the real Payment Element replaces the mock
buttons. Still 100% safe: Stripe's own test mode only accepts test card
numbers (e.g. `4242 4242 4242 4242`), no real charge is possible.
5. **Set the same `sk_test_...` in the backend** too —
`/home/marco/dev/docker/.env`'s `STRIPE_SECRET_KEY` (used only for
`stripeRefund.ts`, Storno/Gutschrift refunds) — then
`cd ~/dev/docker && docker compose build payload && docker compose up -d payload`
to pick it up.
6. **Redeploy the frontend** so it picks up the new Coolify env vars —
either wait for the next git push (Coolify redeploys on push) or
trigger one directly: `curl -X POST https://coolify.mk360.de/deploy/einfach-produktiv`.
7. **Test end to end**: place a real order with a Stripe test card,
confirm the order flips to `received`, invoice/confirmation email
arrive, product images show, `Orders.paymentStatus` reads `paid`. Try a
declined test card too (e.g. `4000 0000 0000 0002`) and confirm the
order shows "Zahlung fehlgeschlagen" in the admin, not in the
customer's own order history.
8. **Trigger a Storno on a paid test order** in the admin, confirm the
refund job actually calls Stripe (check the PaymentIntent in the Stripe
dashboard) and `Orders.refundStatus` updates.
9. **Go live**: only once ready for real charges — verify the Stripe
account for live payments (business details), switch the dashboard to
**live mode**, repeat steps 26 with the live-mode keys (`sk_live_...`/
`pk_live_...`, a *new* webhook endpoint registered in live mode → new
`whsec_...`) — these replace the test values in both Coolify and
`docker/.env`, not additional variables.
### VAT display
Every price shown storefront-wide says "inkl. X% MwSt." with the *actual*