Skip to content

E-commerce Platform Mini Program Case

This case showcases a comprehensive e-commerce platform mini program that provides users with a complete online shopping experience, including product browsing, shopping cart, order management, payment processing, and after-sales service.

Project Overview

Project Background

With the rapid development of mobile internet, more and more merchants are seeking lightweight, efficient online sales channels. Traditional e-commerce platforms often have high development costs and complex maintenance requirements. Mini programs, with their "use-as-you-go" characteristics and low development threshold, have become the preferred choice for many small and medium-sized merchants.

Core Features

  • Product Management: Support for multiple product categories, specifications, and inventory management
  • Shopping Cart: Intelligent shopping cart with quantity adjustment and price calculation
  • Order System: Complete order process from creation to completion
  • Payment Integration: Support for multiple payment methods including WeChat Pay, Alipay
  • User Center: Personal information, order history, address management
  • Marketing Tools: Coupons, group buying, flash sales and other promotional activities
  • Customer Service: Online customer service and after-sales support

Technical Architecture

Frontend Architecture

├── pages/                 # Page files
│   ├── index/            # Homepage
│   ├── category/         # Category page
│   ├── product/          # Product detail page
│   ├── cart/             # Shopping cart
│   ├── order/            # Order management
│   └── user/             # User center
├── components/           # Custom components
│   ├── product-card/     # Product card component
│   ├── cart-item/        # Cart item component
│   └── order-item/       # Order item component
├── utils/                # Utility functions
│   ├── request.js        # Network request encapsulation
│   ├── storage.js        # Local storage management
│   └── common.js         # Common utility functions
└── styles/               # Style files
    ├── common.wxss       # Common styles
    └── variables.wxss    # Style variables

Backend Architecture

├── controllers/          # Controller layer
│   ├── product.js        # Product management
│   ├── order.js          # Order processing
│   ├── user.js           # User management
│   └── payment.js        # Payment processing
├── models/               # Data model layer
│   ├── Product.js        # Product model
│   ├── Order.js          # Order model
│   └── User.js           # User model
├── services/             # Business logic layer
│   ├── productService.js # Product service
│   ├── orderService.js   # Order service
│   └── paymentService.js # Payment service
└── middleware/           # Middleware
    ├── auth.js           # Authentication middleware
    └── validation.js     # Data validation middleware

Key Implementation

Product Display

javascript
// pages/index/index.js
Page({
  data: {
    banners: [],
    categories: [],
    hotProducts: [],
    loading: true
  },

  onLoad() {
    this.loadPageData()
  },

  async loadPageData() {
    try {
      wx.showLoading({ title: 'Loading...' })
      
      const [banners, categories, products] = await Promise.all([
        this.getBanners(),
        this.getCategories(),
        this.getHotProducts()
      ])

      this.setData({
        banners: banners.data,
        categories: categories.data,
        hotProducts: products.data,
        loading: false
      })
    } catch (error) {
      console.error('Failed to load page data:', error)
      wx.showToast({
        title: 'Loading failed',
        icon: 'error'
      })
    } finally {
      wx.hideLoading()
    }
  },

  getBanners() {
    return wx.request({
      url: '/api/banners',
      method: 'GET'
    })
  },

  getCategories() {
    return wx.request({
      url: '/api/categories',
      method: 'GET'
    })
  },

  getHotProducts() {
    return wx.request({
      url: '/api/products/hot',
      method: 'GET'
    })
  },

  onProductTap(e) {
    const productId = e.currentTarget.dataset.id
    wx.navigateTo({
      url: `/pages/product/detail?id=${productId}`
    })
  }
})

Shopping Cart Management

javascript
// pages/cart/cart.js
Page({
  data: {
    cartItems: [],
    totalPrice: 0,
    selectedAll: false
  },

  onShow() {
    this.loadCartData()
  },

  async loadCartData() {
    try {
      const res = await wx.request({
        url: '/api/cart',
        method: 'GET'
      })

      this.setData({
        cartItems: res.data.items
      })
      this.calculateTotal()
    } catch (error) {
      console.error('Failed to load cart data:', error)
    }
  },

  onQuantityChange(e) {
    const { index, quantity } = e.detail
    const cartItems = this.data.cartItems
    cartItems[index].quantity = quantity

    this.setData({ cartItems })
    this.calculateTotal()
    this.updateCartItem(cartItems[index])
  },

  async updateCartItem(item) {
    try {
      await wx.request({
        url: `/api/cart/${item.id}`,
        method: 'PUT',
        data: {
          quantity: item.quantity
        }
      })
    } catch (error) {
      console.error('Failed to update cart item:', error)
    }
  },

  calculateTotal() {
    const selectedItems = this.data.cartItems.filter(item => item.selected)
    const totalPrice = selectedItems.reduce((sum, item) => {
      return sum + (item.price * item.quantity)
    }, 0)

    this.setData({
      totalPrice: totalPrice.toFixed(2)
    })
  },

  onCheckout() {
    const selectedItems = this.data.cartItems.filter(item => item.selected)
    
    if (selectedItems.length === 0) {
      wx.showToast({
        title: 'Please select items',
        icon: 'none'
      })
      return
    }

    wx.navigateTo({
      url: '/pages/order/create',
      success: (res) => {
        res.eventChannel.emit('cartItems', selectedItems)
      }
    })
  }
})

Order Processing

javascript
// pages/order/create.js
Page({
  data: {
    orderItems: [],
    address: null,
    totalAmount: 0,
    paymentMethod: 'wechat'
  },

  onLoad() {
    const eventChannel = this.getOpenerEventChannel()
    eventChannel.on('cartItems', (items) => {
      this.setData({
        orderItems: items
      })
      this.calculateAmount()
    })
    
    this.loadDefaultAddress()
  },

  async loadDefaultAddress() {
    try {
      const res = await wx.request({
        url: '/api/user/address/default',
        method: 'GET'
      })

      this.setData({
        address: res.data
      })
    } catch (error) {
      console.error('Failed to load address:', error)
    }
  },

  calculateAmount() {
    const totalAmount = this.data.orderItems.reduce((sum, item) => {
      return sum + (item.price * item.quantity)
    }, 0)

    this.setData({
      totalAmount: totalAmount.toFixed(2)
    })
  },

  async onSubmitOrder() {
    if (!this.data.address) {
      wx.showToast({
        title: 'Please select address',
        icon: 'none'
      })
      return
    }

    try {
      wx.showLoading({ title: 'Creating order...' })

      const orderData = {
        items: this.data.orderItems,
        address: this.data.address,
        totalAmount: this.data.totalAmount,
        paymentMethod: this.data.paymentMethod
      }

      const res = await wx.request({
        url: '/api/orders',
        method: 'POST',
        data: orderData
      })

      const orderId = res.data.orderId
      
      // Proceed to payment
      this.processPayment(orderId)
      
    } catch (error) {
      console.error('Failed to create order:', error)
      wx.showToast({
        title: 'Order creation failed',
        icon: 'error'
      })
    } finally {
      wx.hideLoading()
    }
  },

  async processPayment(orderId) {
    try {
      const res = await wx.request({
        url: '/api/payment/create',
        method: 'POST',
        data: {
          orderId: orderId,
          paymentMethod: this.data.paymentMethod
        }
      })

      const paymentParams = res.data

      wx.requestPayment({
        ...paymentParams,
        success: () => {
          wx.showToast({
            title: 'Payment successful',
            icon: 'success'
          })
          
          setTimeout(() => {
            wx.redirectTo({
              url: `/pages/order/detail?id=${orderId}`
            })
          }, 1500)
        },
        fail: (error) => {
          console.error('Payment failed:', error)
          wx.showToast({
            title: 'Payment failed',
            icon: 'error'
          })
        }
      })
    } catch (error) {
      console.error('Failed to create payment:', error)
    }
  }
})

Performance Optimization

Image Optimization

javascript
// utils/image.js
class ImageOptimizer {
  static getOptimizedUrl(originalUrl, options = {}) {
    const {
      width = 750,
      height = 750,
      quality = 80,
      format = 'webp'
    } = options

    // Add image processing parameters
    const params = new URLSearchParams({
      w: width,
      h: height,
      q: quality,
      f: format
    })

    return `${originalUrl}?${params.toString()}`
  }

  static lazyLoad(selector) {
    const observer = wx.createIntersectionObserver()
    
    observer.relativeToViewport({ bottom: 100 })
    observer.observe(selector, (res) => {
      if (res.intersectionRatio > 0) {
        const img = res.target
        const dataSrc = img.dataset.src
        
        if (dataSrc) {
          img.src = this.getOptimizedUrl(dataSrc)
          observer.unobserve(selector)
        }
      }
    })
  }
}

export default ImageOptimizer

Data Caching

javascript
// utils/cache.js
class DataCache {
  constructor() {
    this.cache = new Map()
    this.expireTime = new Map()
  }

  set(key, data, ttl = 300000) { // Default 5 minutes
    this.cache.set(key, data)
    this.expireTime.set(key, Date.now() + ttl)
  }

  get(key) {
    const expireTime = this.expireTime.get(key)
    if (expireTime && Date.now() > expireTime) {
      this.delete(key)
      return null
    }
    return this.cache.get(key)
  }

  delete(key) {
    this.cache.delete(key)
    this.expireTime.delete(key)
  }

  clear() {
    this.cache.clear()
    this.expireTime.clear()
  }
}

const cache = new DataCache()
export default cache

User Experience Optimization

Loading States

xml
<!-- components/loading/loading.wxml -->
<view class="loading-container" wx:if="{{show}}">
  <view class="loading-spinner">
    <view class="spinner"></view>
  </view>
  <text class="loading-text">{{text}}</text>
</view>
css
/* components/loading/loading.wxss */
.loading-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 40rpx;
}

.loading-spinner {
  width: 60rpx;
  height: 60rpx;
  margin-bottom: 20rpx;
}

.spinner {
  width: 100%;
  height: 100%;
  border: 4rpx solid #f3f3f3;
  border-top: 4rpx solid #007aff;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.loading-text {
  font-size: 28rpx;
  color: #666;
}

Error Handling

javascript
// utils/error-handler.js
class ErrorHandler {
  static handle(error, context = '') {
    console.error(`Error in ${context}:`, error)
    
    let message = 'An error occurred'
    
    if (error.code) {
      switch (error.code) {
        case 'NETWORK_ERROR':
          message = 'Network connection failed'
          break
        case 'AUTH_FAILED':
          message = 'Authentication failed'
          break
        case 'INVALID_PARAMS':
          message = 'Invalid parameters'
          break
        default:
          message = error.message || 'Unknown error'
      }
    }
    
    wx.showToast({
      title: message,
      icon: 'error',
      duration: 2000
    })
  }
  
  static async retry(fn, maxRetries = 3, delay = 1000) {
    for (let i = 0; i < maxRetries; i++) {
      try {
        return await fn()
      } catch (error) {
        if (i === maxRetries - 1) {
          throw error
        }
        
        await new Promise(resolve => setTimeout(resolve, delay))
      }
    }
  }
}

export default ErrorHandler

Security Measures

Data Validation

javascript
// utils/validator.js
class Validator {
  static validateEmail(email) {
    const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
    return regex.test(email)
  }
  
  static validatePhone(phone) {
    const regex = /^1[3-9]\d{9}$/
    return regex.test(phone)
  }
  
  static validatePrice(price) {
    return typeof price === 'number' && price > 0
  }
  
  static sanitizeInput(input) {
    if (typeof input !== 'string') return input
    
    return input
      .replace(/[<>]/g, '')
      .replace(/javascript:/gi, '')
      .trim()
  }
}

export default Validator

API Security

javascript
// utils/request.js
import Validator from './validator'

class ApiClient {
  constructor() {
    this.baseURL = 'https://api.example.com'
    this.token = wx.getStorageSync('token')
  }
  
  async request(options) {
    const {
      url,
      method = 'GET',
      data = {},
      headers = {}
    } = options
    
    // Sanitize input data
    const sanitizedData = this.sanitizeData(data)
    
    // Add authentication header
    if (this.token) {
      headers['Authorization'] = `Bearer ${this.token}`
    }
    
    try {
      const response = await wx.request({
        url: `${this.baseURL}${url}`,
        method,
        data: sanitizedData,
        header: {
          'Content-Type': 'application/json',
          ...headers
        }
      })
      
      return this.handleResponse(response)
    } catch (error) {
      throw this.handleError(error)
    }
  }
  
  sanitizeData(data) {
    if (typeof data !== 'object' || data === null) {
      return data
    }
    
    const sanitized = {}
    for (const [key, value] of Object.entries(data)) {
      sanitized[key] = Validator.sanitizeInput(value)
    }
    
    return sanitized
  }
  
  handleResponse(response) {
    if (response.statusCode >= 200 && response.statusCode < 300) {
      return response.data
    }
    
    throw new Error(`HTTP ${response.statusCode}: ${response.data.message}`)
  }
  
  handleError(error) {
    if (error.statusCode === 401) {
      // Token expired, redirect to login
      wx.removeStorageSync('token')
      wx.redirectTo({
        url: '/pages/login/login'
      })
    }
    
    return error
  }
}

const apiClient = new ApiClient()
export default apiClient

Analytics and Monitoring

User Behavior Tracking

javascript
// utils/analytics.js
class Analytics {
  static track(event, properties = {}) {
    const data = {
      event,
      properties: {
        ...properties,
        timestamp: Date.now(),
        page: getCurrentPages().pop().route
      }
    }
    
    // Send to analytics service
    wx.request({
      url: '/api/analytics/track',
      method: 'POST',
      data
    })
  }
  
  static trackPageView(pageName) {
    this.track('page_view', {
      page_name: pageName
    })
  }
  
  static trackPurchase(orderId, amount, items) {
    this.track('purchase', {
      order_id: orderId,
      amount,
      items: items.length,
      item_details: items
    })
  }
  
  static trackAddToCart(productId, quantity, price) {
    this.track('add_to_cart', {
      product_id: productId,
      quantity,
      price
    })
  }
}

export default Analytics

Performance Monitoring

javascript
// utils/performance.js
class PerformanceMonitor {
  constructor() {
    this.marks = new Map()
    this.measures = new Map()
  }
  
  mark(name) {
    this.marks.set(name, Date.now())
  }
  
  measure(name, startMark, endMark) {
    const startTime = this.marks.get(startMark)
    const endTime = this.marks.get(endMark) || Date.now()
    
    if (startTime) {
      const duration = endTime - startTime
      this.measures.set(name, duration)
      
      // Report to monitoring service
      this.reportMetric(name, duration)
      
      return duration
    }
  }
  
  reportMetric(name, value) {
    wx.request({
      url: '/api/metrics',
      method: 'POST',
      data: {
        metric: name,
        value,
        timestamp: Date.now()
      }
    })
  }
  
  getMeasures() {
    return Object.fromEntries(this.measures)
  }
}

const performanceMonitor = new PerformanceMonitor()
export default performanceMonitor

Deployment and Maintenance

Build Configuration

javascript
// build/config.js
const config = {
  development: {
    apiBaseURL: 'https://dev-api.example.com',
    debug: true,
    analytics: false
  },
  production: {
    apiBaseURL: 'https://api.example.com',
    debug: false,
    analytics: true
  }
}

module.exports = config[process.env.NODE_ENV || 'development']

Version Management

javascript
// utils/version.js
class VersionManager {
  static getCurrentVersion() {
    return wx.getAccountInfoSync().miniProgram.version || '1.0.0'
  }
  
  static async checkForUpdates() {
    const updateManager = wx.getUpdateManager()
    
    updateManager.onCheckForUpdate((res) => {
      if (res.hasUpdate) {
        wx.showModal({
          title: 'Update Available',
          content: 'A new version is available. Update now?',
          success: (res) => {
            if (res.confirm) {
              this.downloadUpdate(updateManager)
            }
          }
        })
      }
    })
  }
  
  static downloadUpdate(updateManager) {
    updateManager.onUpdateReady(() => {
      wx.showModal({
        title: 'Update Ready',
        content: 'Update downloaded. Restart to apply?',
        success: (res) => {
          if (res.confirm) {
            updateManager.applyUpdate()
          }
        }
      })
    })
    
    updateManager.onUpdateFailed(() => {
      wx.showToast({
        title: 'Update failed',
        icon: 'error'
      })
    })
  }
}

export default VersionManager

Project Results

Key Metrics

  • User Engagement: 85% user retention rate after 7 days
  • Conversion Rate: 12% cart-to-purchase conversion rate
  • Performance: Average page load time under 2 seconds
  • User Satisfaction: 4.8/5.0 average rating

Business Impact

  • Revenue Growth: 300% increase in online sales
  • Cost Reduction: 60% reduction in development costs compared to native app
  • Market Expansion: Reached 50,000+ new users within 3 months
  • Operational Efficiency: 40% reduction in customer service workload

Technical Achievements

  • Code Reusability: 80% component reuse across different pages
  • Performance Optimization: 50% improvement in loading speed
  • Error Rate: Less than 0.1% critical error rate
  • Scalability: Successfully handles 10,000+ concurrent users

Lessons Learned

Best Practices

  1. User-Centric Design: Always prioritize user experience over technical complexity
  2. Performance First: Optimize for mobile devices and slow networks
  3. Progressive Enhancement: Build core functionality first, then add advanced features
  4. Data-Driven Decisions: Use analytics to guide feature development
  5. Security by Design: Implement security measures from the beginning

Common Pitfalls

  1. Over-Engineering: Avoid unnecessary complexity in the initial version
  2. Ignoring Performance: Don't sacrifice performance for feature richness
  3. Poor Error Handling: Always provide meaningful error messages
  4. Inadequate Testing: Test on various devices and network conditions
  5. Neglecting Accessibility: Consider users with different abilities

Future Enhancements

Planned Features

  • AI-Powered Recommendations: Personalized product suggestions
  • AR Product Preview: Virtual try-on functionality
  • Voice Search: Voice-activated product search
  • Social Features: User reviews and social sharing
  • Offline Mode: Basic functionality without internet connection

Technical Roadmap

  • Microservices Architecture: Migrate to microservices for better scalability
  • Real-time Features: WebSocket integration for live updates
  • Advanced Analytics: Machine learning for user behavior analysis
  • Multi-platform Support: Expand to other mini program platforms
  • API Gateway: Centralized API management and security

This e-commerce platform mini program case demonstrates how to build a comprehensive, scalable, and user-friendly online shopping experience using mini program technology. The implementation covers all aspects from technical architecture to user experience optimization, providing a solid foundation for similar projects.

Connecting Multiple Platforms, Empowering Innovation