Payments

Track and manage payments across orders and customers. Support multiple payment methods, process refunds, and query payment history.

Payment Model

class Payment {
  id: string;                    // Unique UUID identifier
  orderId: string;               // Reference to order
  customerId: string;            // Reference to customer
  amount: number;                // Payment amount in cents
  method: PaymentMethod;         // Payment method
  status: PaymentStatus;         // Current status
  referenceNumber: string | null; // External reference (e.g. transaction ID)
  notes: string | null;          // Optional notes
}

type PaymentMethod =
  | "CASH"
  | "BANK_TRANSFER"
  | "CREDIT_CARD"
  | "DEBIT_CARD"
  | "PAYPAL"
  | "OTHER";

type PaymentStatus =
  | "PENDING"
  | "COMPLETED"
  | "FAILED"
  | "REFUNDED"
  | "PARTIALLY_REFUNDED";

Payment Status Workflow

Payment Lifecycle

100%
Loading diagram...

Payment Operations

Create Payment

Create a credit card payment:

import { createPaymentService } from "commercio";

const paymentService = createPaymentService();

// Create a payment for an order
const payment = await paymentService.createPayment({
  orderId: "order-123",
  customerId: "customer-456",
  amount: 99900, // $999.00 in cents
  method: "CREDIT_CARD",
  referenceNumber: "TXN-2025-001",
  notes: "Online checkout payment",
});

console.log(payment.id);              // UUID
console.log(payment.status);          // "PENDING"
console.log(payment.method);          // "CREDIT_CARD"
console.log(payment.referenceNumber); // "TXN-2025-001"

Create a bank transfer payment:

// Create a bank transfer payment
const payment = await paymentService.createPayment({
  orderId: "order-789",
  customerId: "customer-456",
  amount: 249900, // $2,499.00
  method: "BANK_TRANSFER",
  referenceNumber: "WIRE-2025-0042",
});

console.log(payment.method); // "BANK_TRANSFER"
console.log(payment.status); // "PENDING"

Complete Example

import { createServices } from "commercio";

const { paymentService } = createServices();

// 1. Create a payment for an order
const payment = await paymentService.createPayment({
  orderId: "order-123",
  customerId: "customer-456",
  amount: 149900, // $1,499.00
  method: "CREDIT_CARD",
  referenceNumber: "STRIPE-PI-abc123",
  notes: "Website checkout",
});

console.log(payment.status); // "PENDING"

// 2. Complete the payment after gateway confirmation
const completed = await paymentService.completePayment(payment.id);
console.log(completed.status); // "COMPLETED"

// 3. Customer requests partial refund ($200 for a returned item)
const partialRefund = await paymentService.refundPayment(payment.id, {
  amount: 20000, // $200.00
});
console.log(partialRefund.status); // "PARTIALLY_REFUNDED"

// 4. Query all payments for the order
const orderPayments = await paymentService.getPaymentsByOrder("order-123");
console.log(orderPayments.length); // 1

// 5. Query all payments for the customer
const customerPayments = await paymentService.getPaymentsByCustomer("customer-456");
customerPayments.forEach(p => {
  console.log(`${p.method}: $${(p.amount / 100).toFixed(2)} - ${p.status}`);
});
// Output: "CREDIT_CARD: $1499.00 - PARTIALLY_REFUNDED"

// 6. Create a second payment with a different method
const cashPayment = await paymentService.createPayment({
  orderId: "order-789",
  customerId: "customer-456",
  amount: 4999, // $49.99
  method: "CASH",
});

await paymentService.completePayment(cashPayment.id);

// 7. Get updated customer payment history
const allPayments = await paymentService.getPaymentsByCustomer("customer-456");
console.log(allPayments.length); // 2

Best Practices

1. Always Store Reference Numbers

Store external transaction IDs for reconciliation with payment gateways:

// Good: Include reference number from payment gateway
const payment = await paymentService.createPayment({
  orderId: orderId,
  customerId: customerId,
  amount: 9900,
  method: "CREDIT_CARD",
  referenceNumber: stripePaymentIntent.id, // "pi_3abc..."
  notes: `Stripe charge for order ${orderId}`,
});

2. Handle Failed Payments Gracefully

When a payment fails, record the failure and allow retry:

try {
  // Attempt to process payment with gateway
  const gatewayResult = await processWithGateway(paymentDetails);

  if (gatewayResult.success) {
    await paymentService.completePayment(payment.id);
  } else {
    await paymentService.failPayment(payment.id);

    // Create a new payment for retry
    const retryPayment = await paymentService.createPayment({
      orderId: payment.orderId,
      customerId: payment.customerId,
      amount: payment.amount,
      method: payment.method,
      notes: "Retry after failed attempt",
    });
  }
} catch (error) {
  await paymentService.failPayment(payment.id);
  throw error;
}

3. Validate Refund Amounts

Always check that the refund amount does not exceed the original payment:

const payment = await paymentService.getPaymentById(paymentId);

const refundAmount = 5000; // $50.00

if (refundAmount > payment.amount) {
  throw new Error("Refund amount exceeds payment amount");
}

await paymentService.refundPayment(paymentId, {
  amount: refundAmount,
});

4. Use Appropriate Payment Methods

Choose the correct payment method for accurate reporting and reconciliation:

// Online payments
method: "CREDIT_CARD"   // Visa, Mastercard, etc.
method: "DEBIT_CARD"    // Direct debit card payments
method: "PAYPAL"        // PayPal transactions

// Offline payments
method: "CASH"          // In-store cash payments
method: "BANK_TRANSFER" // Wire transfers, ACH

// Custom integrations
method: "OTHER"         // Crypto, gift cards, etc.