Skip to main content
This guide explains how to create orders, retrieve order history, and understand the order lifecycle.

Order Creation Flow

1

Authenticate User

User must be logged in with valid authentication cookies.
2

Select Products

Choose products with quantities to purchase.
3

Create Order

Submit order with product list. The system validates stock availability and calculates totals.
4

Pay Order

Process payment using TRX tokens (see Payment Processing).

Creating an Order

Create a new order with selected products and quantities.

Endpoint

POST /api/orders
Requires authentication. Users can only have one pending order at a time.

Request Body

{
  "products": [
    {
      "productId": "507f1f77bcf86cd799439011",
      "quantity": 2,
      "color": "Black"
    },
    {
      "productId": "507f1f77bcf86cd799439012",
      "quantity": 1,
      "color": "White"
    }
  ]
}

Request Fields

  • products (array, required): List of products to order
    • productId (string, required): MongoDB ObjectId of the product
    • quantity (number, required): Quantity to purchase (minimum 1)
    • color (string, optional): Product color variant

Response

{
  "success": true,
  "message": "Order created successfully",
  "order": {
    "_id": "507f1f77bcf86cd799439013",
    "orderId": "#TRX-1001",
    "products": [
      {
        "productId": "507f1f77bcf86cd799439011",
        "name": "Wireless Headphones",
        "price": 29.99,
        "quantity": 2,
        "color": "Black"
      },
      {
        "productId": "507f1f77bcf86cd799439012",
        "name": "Phone Case",
        "price": 14.99,
        "quantity": 1,
        "color": "White"
      }
    ],
    "subtotal": 74.97,
    "networkFee": -0.01,
    "total": 74.96,
    "status": "pending",
    "merchantAddress": "TYwXGhKhqPTbLvRPFdvZnXqcqN4kVy7ABC",
    "createdAt": "2024-01-20T14:30:00.000Z"
  }
}

Implementation Example

const response = await fetch('http://localhost:3000/api/orders', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  credentials: 'include',
  body: JSON.stringify({
    products: [
      {
        productId: '507f1f77bcf86cd799439011',
        quantity: 2,
        color: 'Black'
      },
      {
        productId: '507f1f77bcf86cd799439012',
        quantity: 1,
        color: 'White'
      }
    ]
  })
});

const data = await response.json();
console.log('Order created:', data.order);

Order Calculation Logic

The order total is calculated automatically from src/api/orders/createOrder.js:28:
let subtotal = 0;
const orderProducts = [];

for (const item of products) {
  const product = await Product.findById(item.productId);
  if (!product) {
    return res.status(404).json({ error: `Product ${item.productId} not found` });
  }
  if (product.stock < item.quantity) {
    return res.status(400).json({ error: `Insufficient stock for ${product.name}` });
  }
  subtotal += product.price * item.quantity;
  orderProducts.push({
    productId: product._id,
    name: product.name,
    price: product.price,
    quantity: item.quantity,
    color: item.color || null
  });
}
const networkFee = -0.01;
const total = subtotal + networkFee;

Retrieving Orders

Get a list of all orders for the authenticated user.

Endpoint

GET /api/orders

Query Parameters

  • status (optional): Filter by order status (pending, completed, refunded, failed, cancelled)
  • limit (optional): Number of orders per page (default: 10)
  • page (optional): Page number (default: 1)

Response

{
  "success": true,
  "orders": [
    {
      "_id": "507f1f77bcf86cd799439013",
      "orderId": "#TRX-1001",
      "products": [
        {
          "productId": "507f1f77bcf86cd799439011",
          "name": "Wireless Headphones",
          "price": 29.99,
          "quantity": 2,
          "color": "Black"
        }
      ],
      "subtotal": 59.98,
      "networkFee": -0.01,
      "total": 59.97,
      "status": "completed",
      "transactionHash": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0",
      "walletAddress": "TYwXGhKhqPTbLvRPFdvZnXqcqN4kVy7ABC",
      "merchantAddress": "TXYZMerchantAddressHere123456789",
      "createdAt": "2024-01-20T14:30:00.000Z",
      "updatedAt": "2024-01-20T14:35:00.000Z"
    }
  ],
  "stats": {
    "total": 15,
    "pending": 1,
    "completed": 10,
    "refunded": 2,
    "failed": 1,
    "cancelled": 1
  },
  "pagination": {
    "total": 15,
    "page": 1,
    "pages": 2
  }
}

Implementation Example

const response = await fetch(
  'http://localhost:3000/api/orders?limit=20&page=1',
  {
    credentials: 'include'
  }
);

const data = await response.json();
console.log('Total orders:', data.stats.total);
console.log('Orders:', data.orders);

Get Order by ID

Retrieve details of a specific order.

Endpoint

GET /api/orders/:id

Response

{
  "success": true,
  "order": {
    "_id": "507f1f77bcf86cd799439013",
    "orderId": "#TRX-1001",
    "userId": "507f1f77bcf86cd799439010",
    "products": [
      {
        "productId": "507f1f77bcf86cd799439011",
        "name": "Wireless Headphones",
        "price": 29.99,
        "quantity": 2,
        "color": "Black"
      }
    ],
    "subtotal": 59.98,
    "networkFee": -0.01,
    "total": 59.97,
    "status": "completed",
    "paymentMethod": "TRC-20",
    "transactionHash": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0",
    "walletAddress": "TYwXGhKhqPTbLvRPFdvZnXqcqN4kVy7ABC",
    "merchantAddress": "TXYZMerchantAddressHere123456789",
    "createdAt": "2024-01-20T14:30:00.000Z",
    "updatedAt": "2024-01-20T14:35:00.000Z"
  }
}

Order Status Lifecycle

Orders progress through different statuses as defined in src/models/Order.js:45:
1

pending

Order is created but payment has not been sent. User can proceed to payment.
2

completed

Payment confirmed on blockchain. Product stock is reduced. This is a final state.
3

refunded

Order was refunded by admin. Product stock is restored. This is a final state.
4

failed

Payment transaction failed. This is a final state.
5

cancelled

Order was cancelled before payment. This is a final state.

Order Constraints

Important constraints from src/api/orders/createOrder.js:14:
  • Users can only have one pending order at a time
  • Stock availability is validated before order creation
  • Orders cannot be modified after creation
  • Payment must be completed to finalize the order

Order Model Schema

From src/models/Order.js:3, each order contains:
{
  orderId: String,              // Auto-generated (e.g., "#TRX-1001")
  userId: ObjectId,             // Reference to User
  products: [{
    productId: ObjectId,        // Reference to Product
    name: String,               // Product name (snapshot)
    price: Number,              // Product price (snapshot)
    quantity: Number,           // Quantity ordered
    color: String               // Optional color variant
  }],
  subtotal: Number,             // Sum of (price × quantity)
  networkFee: Number,           // TRON network fee (-0.01)
  discount: Number,             // Discount amount (default: 0)
  total: Number,                // subtotal + networkFee + discount
  status: String,               // Order status
  paymentMethod: String,        // Payment method (default: "TRC-20")
  transactionHash: String,      // Blockchain transaction hash
  walletAddress: String,        // Customer wallet address
  merchantAddress: String,      // Merchant wallet address
  createdAt: Date,
  updatedAt: Date
}

Next Steps

After creating an order:

Payment Processing

Learn how to process TRX payments for orders

Real-time Notifications

Receive instant notifications when payments are confirmed

Build docs developers (and LLMs) love