Checkout Process

Updated 8 July 2026

The checkout process handles order creation, payment processing, and order confirmation. This section covers the complete checkout flow implementation.

Checkout Flow

The checkout process follows these steps:

Fetching Checkout Data

const response = await fetch("/api/checkout"); // Get checkout data from response
const checkoutData = await response.json();
// Returns: { shipping_rates: [], payment_methods: [] }

Updating Checkout Information

await fetch("/api/checkout", { // Update checkout with the given billing address and shipping address  
  method: "PUT",
  body: JSON.stringify({
    billing_address: { first_name: "John", email: "[email protected]", ... }, // Billing address with first name, email and other fields
    shipping_address: { first_name: "John", ... } // Shipping address with first name and other fields
  })
});

Checkout Form Implementation

"use client";

const handleSubmit = async (e) => { // Handle submit with the given event
  e.preventDefault();
  
  // Update checkout
  await fetch("/api/checkout", { // Update checkout with the given billing address and shipping address
    method: "PUT",
    body: JSON.stringify({ billing_address: {...}, shipping_address: {...} })
  });
  
  // Process order
  const response = await fetch("/api/checkout", { // Process order with the given payment method
    method: "POST",
    body: JSON.stringify({ payment_method: "stripe" }) // Payment method with the given payment method
  });
  
  const orderData = await response.json(); // Get order data from response
  if (orderData.id) router.push(`/thank-you/${orderData.id}`); // Redirect to thank-you page with the given order id
};

Processing Order

const response = await fetch("/api/checkout", { // Process order with the given payment method and payment data
  method: "POST",
  body: JSON.stringify({ payment_method: "stripe", payment_data: {} }) // Payment method with the given payment method and payment data
});

const orderData = await response.json(); // Get order data from response
// Returns: { id: 12345, status: "processing" }

Order Confirmation

export default async function ThankYouPage({ params }) {
  const order = await fetch(`/api/order/order-details?id=${params.id}`)
    .then(res => res.json());
  
  return (
    
      Thank You!
      Order #: {order.id} // Display order id
      Total: ${order.total} // Display order total
    
  );
}

Shipping & Payment Methods

// Shipping methods
{shippingRates.map(rate => ( // Display shipping rates with the given rate id
  
     // Display radio button with the given rate id
    {rate.name} - ${rate.price} // Display shipping rate name and price
  
))}

// Payment methods
{paymentMethods.map(method => ( // Display payment methods with the given method id
  
     // Display radio button with the given method id
    {method.title} // Display payment method title
  
))}

Form Validation & Error Handling

const validateCheckout = (formData) => { // Validate checkout with the given form data
  const errors = {};
  if (!formData.billing.email) errors.email = "Email required"; // If email is not provided, set email required error
  if (!formData.shippingMethod) errors.shipping = "Select shipping"; // If shipping method is not provided, set shipping required error
  return errors;
};

try {
  const errors = validateCheckout(formData); // Validate checkout with the given form data
  if (Object.keys(errors).length > 0) return;
  
  const order = await processOrder(formData);
  router.push(`/thank-you/${order.id}`); // Redirect to thank-you page with the given order id    
} catch (error) {
  setError(error.message); // Set error message with the given error message
}

Best Practices