Stripe Payments
PrintStudio uses Stripe for all payment processing: checkout sessions, payment confirmation, and refunds. The integration lives in packages/core/src/payments/.
Required Keys
Section titled “Required Keys”STRIPE_SECRET_KEY=sk_live_... # or sk_test_... for developmentSTRIPE_PUBLISHABLE_KEY=pk_live_... # used by the frontendSTRIPE_WEBHOOK_SECRET=whsec_... # from Stripe dashboard webhook configGet your keys from the Stripe Dashboard.
Checkout Flow
Section titled “Checkout Flow”- Customer configures product and proceeds to checkout
- PrintStudio calls
stripe.checkout.sessions.create()with line items and a redirect URL - Customer completes payment on Stripe-hosted checkout page
- Stripe sends
checkout.session.completedtoPOST /webhooks/stripe - PrintStudio creates the order and begins production
// packages/core/src/payments/ — simplifiedconst session = await stripe.checkout.sessions.create({ mode: "payment", line_items: lineItems.map(item => ({ price_data: { currency: "usd", product_data: { name: item.skuName }, unit_amount: Math.round(item.unitPrice * 100), }, quantity: item.quantity, })), success_url: `${siteUrl}/orders/{id}/confirmation`, cancel_url: `${siteUrl}/cart`, metadata: { orderId: order.id },});Webhook Setup
Section titled “Webhook Setup”Stripe must be able to reach your API’s webhook endpoint. For production, configure the endpoint in the Stripe Dashboard:
- URL:
https://your-api.example.com/webhooks/stripe - Events:
checkout.session.completed,payment_intent.payment_failed,charge.refunded
For local development, use the Stripe CLI to forward webhooks:
# Install Stripe CLI: https://stripe.com/docs/stripe-clistripe listen --forward-to localhost:8787/webhooks/stripe
# The CLI prints your webhook signing secret:# > Ready! Your webhook signing secret is whsec_...# Set this as STRIPE_WEBHOOK_SECRET in .envHandled Events
Section titled “Handled Events”| Stripe Event | PrintStudio Action |
|---|---|
checkout.session.completed | Mark order paid, create jobs, send confirmation email |
payment_intent.payment_failed | Mark order payment_failed, notify customer |
charge.refunded | Mark order refunded, update job statuses |
Refunds
Section titled “Refunds”Refunds are triggered automatically when an order is cancelled:
# Cancel an order (triggers Stripe refund if paid)curl -X POST http://localhost:8787/api/orders/{id}/cancel \ -H "Content-Type: application/json" \ -H "X-API-Key: your-api-key" \ -d '{ "reason": "Operator: material out of stock" }'Or trigger a manual refund directly:
curl -X POST http://localhost:8787/api/orders/{id}/refund \ -H "Content-Type: application/json" \ -H "X-API-Key: your-admin-key" \ -d '{ "amount": 4926, "reason": "duplicate" }'# amount is in centsTest Mode
Section titled “Test Mode”Use sk_test_... keys during development. Stripe test card numbers:
| Card | Result |
|---|---|
4242 4242 4242 4242 | Successful payment |
4000 0000 0000 9995 | Declined (insufficient funds) |
4000 0025 0000 3155 | Requires 3D Secure |
Any future expiry date and any 3-digit CVC work in test mode.