Cart to Order Flow
This guide walks you through implementing the complete shopping cart to order conversion process.
Overview
The cart-to-order flow involves several steps:
- Add items to cart
- Validate cart contents
- Calculate totals and fees
- Process payment
- Create order
- Update inventory
- Send notifications
Step-by-Step Implementation
1. Add Items to Cart
// Add product to cart
const addToCart = async (productId: string, quantity: number) => {
await convex.mutation(api.customers.cart.addToCart, {
productId,
quantity,
customerId: "user_123"
});
};
2. Validate Cart for Checkout
// Validate cart before checkout
const validation = await convex.query(api.customers.cartToOrder.validateCartForCheckout, {
customerId: "user_123"
});
if (!validation.isValid) {
console.error("Cart validation failed:", validation.errors);
return;
}
3. Create Payment Intent
// Create Stripe payment intent
const paymentIntent = await convex.mutation(api.customers.payments.createPaymentIntent, {
amount: validation.totalAmount,
currency: "AED",
customerId: "user_123"
});
4. Process Payment
// Use Stripe client to confirm payment
const { error } = await stripe.confirmPayment({
clientSecret: paymentIntent.clientSecret,
elements,
confirmParams: {
return_url: "https://yourapp.com/return"
}
});
5. Create Order from Cart
// Convert cart to order after successful payment
const order = await convex.mutation(api.customers.cartToOrder.createOrderFromCart, {
customerId: "user_123",
paymentIntentId: paymentIntent.id,
shippingAddress: {
street: "123 Main St",
city: "Dubai",
emirate: "Dubai",
postalCode: "12345"
}
});
Complete Flow Example
const completeCheckout = async () => {
try {
// 1. Validate cart
const validation = await convex.query(api.customers.cartToOrder.validateCartForCheckout, {
customerId: currentUser.id
});
if (!validation.isValid) {
throw new Error(`Cart validation failed: ${validation.errors.join(", ")}`);
}
// 2. Create payment intent
const paymentIntent = await convex.mutation(api.customers.payments.createPaymentIntent, {
amount: validation.totalAmount,
currency: "AED",
customerId: currentUser.id
});
// 3. Process payment with Stripe
const { error } = await stripe.confirmPayment({
clientSecret: paymentIntent.clientSecret,
elements,
confirmParams: {
return_url: `${window.location.origin}/checkout/success`
}
});
if (error) {
throw new Error(`Payment failed: ${error.message}`);
}
// 4. Create order
const order = await convex.mutation(api.customers.cartToOrder.createOrderFromCart, {
customerId: currentUser.id,
paymentIntentId: paymentIntent.id,
shippingAddress: shippingAddress
});
// 5. Clear cart
await convex.mutation(api.customers.cart.clearCart, {
customerId: currentUser.id
});
return order;
} catch (error) {
console.error("Checkout failed:", error);
throw error;
}
};
Error Handling
Common Validation Errors
- Out of stock: Product no longer available
- Price changes: Product price updated
- Invalid quantities: Quantity exceeds available stock
- Store unavailable: Store is not accepting orders
Payment Errors
- Insufficient funds: Card declined
- Invalid card: Card details incorrect
- Network error: Payment processing failed
Best Practices
- Always validate cart before payment
- Handle errors gracefully with user-friendly messages
- Clear cart only after successful order creation
- Send confirmations via email and push notifications
- Update inventory immediately after order creation
The cart-to-order flow is designed to be atomic - either all steps succeed or none do, ensuring data consistency.