Skip to content

Stripe Payments

PrintStudio uses Stripe for all payment processing: checkout sessions, payment confirmation, and refunds. The integration lives in packages/core/src/payments/.

Terminal window
STRIPE_SECRET_KEY=sk_live_... # or sk_test_... for development
STRIPE_PUBLISHABLE_KEY=pk_live_... # used by the frontend
STRIPE_WEBHOOK_SECRET=whsec_... # from Stripe dashboard webhook config

Get your keys from the Stripe Dashboard.

  1. Customer configures product and proceeds to checkout
  2. PrintStudio calls stripe.checkout.sessions.create() with line items and a redirect URL
  3. Customer completes payment on Stripe-hosted checkout page
  4. Stripe sends checkout.session.completed to POST /webhooks/stripe
  5. PrintStudio creates the order and begins production
// packages/core/src/payments/ — simplified
const 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 },
});

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:

Terminal window
# Install Stripe CLI: https://stripe.com/docs/stripe-cli
stripe 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 .env
Stripe EventPrintStudio Action
checkout.session.completedMark order paid, create jobs, send confirmation email
payment_intent.payment_failedMark order payment_failed, notify customer
charge.refundedMark order refunded, update job statuses

Refunds are triggered automatically when an order is cancelled:

Terminal window
# 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:

Terminal window
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 cents

Use sk_test_... keys during development. Stripe test card numbers:

CardResult
4242 4242 4242 4242Successful payment
4000 0000 0000 9995Declined (insufficient funds)
4000 0025 0000 3155Requires 3D Secure

Any future expiry date and any 3-digit CVC work in test mode.