e-commerce

安装量: 46
排名: #16230

安装

npx skills add https://github.com/miles990/claude-software-skills --skill e-commerce

E-Commerce Development Overview

Building e-commerce applications with shopping carts, payment processing, inventory management, and order fulfillment.

Shopping Cart Cart State Management interface CartItem { productId: string; variantId?: string; quantity: number; price: number; name: string; image: string; }

interface Cart { id: string; items: CartItem[]; subtotal: number; tax: number; shipping: number; total: number; discountCode?: string; discountAmount: number; }

// Zustand cart store import { create } from 'zustand'; import { persist } from 'zustand/middleware';

interface CartStore { cart: Cart; addItem: (item: Omit, quantity?: number) => void; updateQuantity: (productId: string, quantity: number) => void; removeItem: (productId: string) => void; clearCart: () => void; applyDiscount: (code: string) => Promise; }

const useCartStore = create()( persist( (set, get) => ({ cart: createEmptyCart(),

  addItem: (item, quantity = 1) => {
    set((state) => {
      const existingIndex = state.cart.items.findIndex(
        (i) => i.productId === item.productId && i.variantId === item.variantId
      );

      const newItems = [...state.cart.items];
      if (existingIndex >= 0) {
        newItems[existingIndex].quantity += quantity;
      } else {
        newItems.push({ ...item, quantity });
      }

      return { cart: recalculateCart({ ...state.cart, items: newItems }) };
    });
  },

  updateQuantity: (productId, quantity) => {
    set((state) => {
      if (quantity <= 0) {
        return {
          cart: recalculateCart({
            ...state.cart,
            items: state.cart.items.filter((i) => i.productId !== productId),
          }),
        };
      }

      const newItems = state.cart.items.map((item) =>
        item.productId === productId ? { ...item, quantity } : item
      );

      return { cart: recalculateCart({ ...state.cart, items: newItems }) };
    });
  },

  removeItem: (productId) => {
    set((state) => ({
      cart: recalculateCart({
        ...state.cart,
        items: state.cart.items.filter((i) => i.productId !== productId),
      }),
    }));
  },

  clearCart: () => set({ cart: createEmptyCart() }),

  applyDiscount: async (code) => {
    const discount = await validateDiscountCode(code);
    set((state) => ({
      cart: recalculateCart({
        ...state.cart,
        discountCode: code,
        discountAmount: discount.amount,
      }),
    }));
  },
}),
{ name: 'cart-storage' }

) );

function recalculateCart(cart: Cart): Cart { const subtotal = cart.items.reduce( (sum, item) => sum + item.price * item.quantity, 0 ); const tax = subtotal * 0.1; // 10% tax const shipping = subtotal > 100 ? 0 : 9.99; const total = subtotal + tax + shipping - cart.discountAmount;

return { ...cart, subtotal, tax, shipping, total }; }

Payment Processing Stripe Integration import Stripe from 'stripe';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, { apiVersion: '2023-10-16', });

// Create checkout session async function createCheckoutSession(cart: Cart, customerId?: string) { const session = await stripe.checkout.sessions.create({ mode: 'payment', customer: customerId, line_items: cart.items.map((item) => ({ price_data: { currency: 'usd', product_data: { name: item.name, images: [item.image], }, unit_amount: Math.round(item.price * 100), }, quantity: item.quantity, })), discounts: cart.discountCode ? [{ coupon: cart.discountCode }] : undefined, shipping_address_collection: { allowed_countries: ['US', 'CA', 'GB'], }, success_url: ${process.env.APP_URL}/checkout/success?session_id={CHECKOUT_SESSION_ID}, cancel_url: ${process.env.APP_URL}/cart, metadata: { cartId: cart.id, }, });

return session; }

// Create payment intent (for custom checkout) async function createPaymentIntent(amount: number, customerId?: string) { const paymentIntent = await stripe.paymentIntents.create({ amount: Math.round(amount * 100), currency: 'usd', customer: customerId, automatic_payment_methods: { enabled: true }, });

return { clientSecret: paymentIntent.client_secret, paymentIntentId: paymentIntent.id, }; }

// Webhook handler async function handleStripeWebhook(body: string, signature: string) { const event = stripe.webhooks.constructEvent( body, signature, process.env.STRIPE_WEBHOOK_SECRET! );

switch (event.type) { case 'checkout.session.completed': { const session = event.data.object as Stripe.Checkout.Session; await fulfillOrder(session); break; }

case 'payment_intent.succeeded': {
  const paymentIntent = event.data.object as Stripe.PaymentIntent;
  await handlePaymentSuccess(paymentIntent);
  break;
}

case 'payment_intent.payment_failed': {
  const paymentIntent = event.data.object as Stripe.PaymentIntent;
  await handlePaymentFailure(paymentIntent);
  break;
}

} }

React Stripe Elements import { loadStripe } from '@stripe/stripe-js'; import { Elements, PaymentElement, useStripe, useElements, } from '@stripe/react-stripe-js';

const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_KEY!);

function CheckoutForm({ clientSecret }: { clientSecret: string }) { const stripe = useStripe(); const elements = useElements(); const [error, setError] = useState(null); const [processing, setProcessing] = useState(false);

const handleSubmit = async (e: React.FormEvent) => { e.preventDefault();

if (!stripe || !elements) return;

setProcessing(true);
setError(null);

const { error: submitError } = await stripe.confirmPayment({
  elements,
  confirmParams: {
    return_url: `${window.location.origin}/checkout/success`,
  },
});

if (submitError) {
  setError(submitError.message || 'Payment failed');
  setProcessing(false);
}

};

return (

{error &&
{error}
} ); }

function CheckoutPage() { const [clientSecret, setClientSecret] = useState('');

useEffect(() => { fetch('/api/create-payment-intent', { method: 'POST', body: JSON.stringify({ amount: cart.total }), }) .then((res) => res.json()) .then((data) => setClientSecret(data.clientSecret)); }, []);

if (!clientSecret) return ;

return ( ); }

Inventory Management interface Product { id: string; name: string; sku: string; price: number; inventory: number; lowStockThreshold: number; variants: ProductVariant[]; }

interface ProductVariant { id: string; name: string; sku: string; price: number; inventory: number; attributes: Record; }

// Inventory operations with optimistic locking async function reserveInventory(items: CartItem[]): Promise { return prisma.$transaction(async (tx) => { for (const item of items) { const product = await tx.product.findUnique({ where: { id: item.productId }, select: { inventory: true, version: true }, });

  if (!product || product.inventory < item.quantity) {
    throw new Error(`Insufficient inventory for ${item.name}`);
  }

  // Optimistic locking with version check
  const updated = await tx.product.updateMany({
    where: {
      id: item.productId,
      version: product.version,
      inventory: { gte: item.quantity },
    },
    data: {
      inventory: { decrement: item.quantity },
      version: { increment: 1 },
    },
  });

  if (updated.count === 0) {
    throw new Error(`Concurrent modification for ${item.name}`);
  }
}

return true;

}); }

// Release inventory (on order cancellation) async function releaseInventory(orderId: string) { const order = await prisma.order.findUnique({ where: { id: orderId }, include: { items: true }, });

await prisma.$transaction( order.items.map((item) => prisma.product.update({ where: { id: item.productId }, data: { inventory: { increment: item.quantity } }, }) ) ); }

// Low stock alerts async function checkLowStock() { const lowStockProducts = await prisma.product.findMany({ where: { inventory: { lte: prisma.product.fields.lowStockThreshold }, }, });

for (const product of lowStockProducts) { await sendLowStockAlert(product); } }

Order Management enum OrderStatus { PENDING = 'pending', PAID = 'paid', PROCESSING = 'processing', SHIPPED = 'shipped', DELIVERED = 'delivered', CANCELLED = 'cancelled', REFUNDED = 'refunded', }

interface Order { id: string; userId: string; status: OrderStatus; items: OrderItem[]; subtotal: number; tax: number; shipping: number; total: number; shippingAddress: Address; billingAddress: Address; paymentIntentId: string; trackingNumber?: string; createdAt: Date; updatedAt: Date; }

// Create order from checkout session async function fulfillOrder(session: Stripe.Checkout.Session) { const order = await prisma.order.create({ data: { userId: session.client_reference_id!, status: OrderStatus.PAID, paymentIntentId: session.payment_intent as string, subtotal: session.amount_subtotal! / 100, total: session.amount_total! / 100, shippingAddress: JSON.parse(session.metadata!.shippingAddress), items: { create: JSON.parse(session.metadata!.items), }, }, });

// Reserve inventory await reserveInventory(order.items);

// Send confirmation email await sendOrderConfirmation(order);

// Notify fulfillment system await notifyFulfillment(order);

return order; }

// Order status updates async function updateOrderStatus(orderId: string, status: OrderStatus) { const order = await prisma.order.update({ where: { id: orderId }, data: { status }, });

// Send notification await sendOrderStatusUpdate(order);

return order; }

Product Catalog // Product search with filters async function searchProducts(params: { query?: string; category?: string; minPrice?: number; maxPrice?: number; sortBy?: 'price' | 'name' | 'createdAt'; sortOrder?: 'asc' | 'desc'; page?: number; limit?: number; }) { const { query, category, minPrice, maxPrice, sortBy = 'createdAt', sortOrder = 'desc', page = 1, limit = 20, } = params;

const where: Prisma.ProductWhereInput = { status: 'active', ...(query && { OR: [ { name: { contains: query, mode: 'insensitive' } }, { description: { contains: query, mode: 'insensitive' } }, ], }), ...(category && { categoryId: category }), ...(minPrice && { price: { gte: minPrice } }), ...(maxPrice && { price: { lte: maxPrice } }), };

const [products, total] = await Promise.all([ prisma.product.findMany({ where, orderBy: { [sortBy]: sortOrder }, skip: (page - 1) * limit, take: limit, include: { category: true, images: true, variants: true, }, }), prisma.product.count({ where }), ]);

return { products, pagination: { page, limit, total, totalPages: Math.ceil(total / limit), }, }; }

Related Skills [[payment-processing]] - Payment systems [[backend]] - API development [[database]] - Data modeling

返回排行榜