Welcome to the Jose Madrid Salsa developer docs — explore features, APIs, and deployment guides.
Jose Madrid SalsaJMS Docs

Checkout Flow

Multi-step checkout with address collection, shipping calculation, tax estimation, discount codes, gift certificates, and multi-provider payment

Checkout

The checkout page is a single client component that handles address collection, real-time shipping and tax calculation, discount code validation, gift certificate application, and payment processing across multiple providers.

Architecture

page.tsx
layout.tsx
route.ts
PaymentMethodSelector.tsx
PayPalProvider.tsx
PayPalButton.tsx
VenmoButton.tsx
CashAppButton.tsx

Checkout Flow

Cart Review

The checkout page reads items from the Zustand cart store. If the cart is empty, the user is redirected to the products page.

Customer Information

The form collects:

  • First name, last name, email, phone
  • Shipping address (line1, line2, city, state, postal code)
  • Order notes (optional)

Shipping Calculation

When the address fields are complete, the page calls POST /api/checkout/calculate-shipping which invokes calculateShipping() from lib/shipping-calculator.ts. The API returns multiple shipping options sorted by cost. The user selects their preferred option.

Tax Calculation

After shipping is determined, the page calls POST /api/checkout/calculate-tax which invokes calculateTax() from lib/tax-calculator.ts via the Stripe Tax API. Tax is calculated based on the shipping address jurisdiction.

Discount Code (Optional)

Users can enter a discount code, validated via POST /api/checkout/validate-discount. Supported types: PERCENTAGE, FIXED_AMOUNT, and FREE_SHIPPING.

Gift Certificate (Optional)

Users can apply a gift certificate code via POST /api/checkout/apply-gift-certificate, which deducts from the certificate balance.

Payment

The user selects a payment method from the PaymentMethodSelector component. Providers are lazy-loaded to minimize bundle size:

MethodProviderBundle Strategy
Card, Apple Pay, Google PayStripeAlways loaded (default)
PayPalPayPaldynamic() import, SSR disabled
VenmoPayPaldynamic() import, SSR disabled
Cash AppSquaredynamic() import, SSR disabled

Order Creation and Completion

On submit, the page calls POST /api/checkout/create-session to create the order and payment intent, then POST /api/checkout/complete to finalize after payment confirmation.

Order Completion

The /api/checkout/complete endpoint:

  1. Validates the order ID and payment intent ID with Zod
  2. Confirms payment status with the provider via getProvider('STRIPE').confirmPayment()
  3. In a single Prisma transaction:
    • Updates order status to CONFIRMED and payment status to PAID
    • Deducts reserved inventory for each line item via deductReservedInventoryInTx()
  4. Fires inventory alerts for any low-stock products
  5. Returns the completed order for the success page redirect

If payment confirmation fails, reserved inventory is released via releaseInventory() to prevent stock being permanently locked.

Payment Method Selector

The PaymentMethodSelector component renders available payment methods as selectable cards. The default methods are:

const DEFAULT_METHODS = [
  { id: 'card', label: 'Credit / Debit Card', icon: CreditCard },
  { id: 'apple_pay', label: 'Apple Pay', icon: Apple },
  { id: 'google_pay', label: 'Google Pay', icon: Smartphone },
  { id: 'paypal', label: 'PayPal', icon: PaypalIcon },
  { id: 'venmo', label: 'Venmo', icon: VenmoIcon },
  { id: 'cashapp', label: 'Cash App', icon: CashAppIcon },
]

Stripe Elements

For card payments, the checkout page wraps the form in Stripe's <Elements> provider and uses:

  • <CardElement> for card number, expiry, and CVC
  • <ExpressCheckoutElement> for Apple Pay and Google Pay
  • <LinkAuthenticationElement> for Stripe Link autofill

How is this guide?

Edit on GitHub

Last updated on

On this page