# Sub2API Order Statuses: Complete Guide to Payment State Constants

> Explore the 13 Sub2API order status constants for payment state management. Understand every possible payment lifecycle stage from creation to completion, refund, or failure.

- Repository: [Wesley Liddick/sub2api](https://github.com/Wei-Shaw/sub2api)
- Tags: api-reference
- Published: 2026-08-23

---

**Sub2API defines 13 distinct order status constants in [`backend/internal/service/payment_service.go`](https://github.com/Wei-Shaw/sub2api/blob/main/backend/internal/service/payment_service.go) that represent every possible state a payment order can occupy, from initial creation through completion, refund, or failure.**

The payment system in the Wei-Shaw/sub2api repository uses these statuses to drive workflow transitions, enforce business rules, and generate financial reports. Each constant wraps an underlying value from the core `payment` package and is used throughout the backend services to maintain consistent state management.

## Complete List of Sub2API Order Statuses

The 13 order statuses are organized into three functional categories: standard payment flow, refund processing, and terminal states.

### Standard Payment Lifecycle

These statuses track the happy path and interruption points for active payment orders:

- **OrderStatusPending** – The order has been created but not yet paid. This is the initial state assigned when a new `PaymentOrder` entity is persisted.

- **OrderStatusPaid** – Payment has succeeded and funds have been captured. The order is now considered funded and ready for fulfillment.

- **OrderStatusRecharging** – The order is being renewed or extended, typically indicating a subscription renewal process is in progress.

- **OrderStatusCompleted** – The order has been fully processed, delivered, and finalized. This is a terminal success state for the core payment workflow.

- **OrderStatusExpired** – The order timed out without receiving payment. This occurs when the payment window closes before user completion.

- **OrderStatusCancelled** – The user or an administrator explicitly cancelled the order before payment completion.

- **OrderStatusFailed** – An unrecoverable error occurred during the payment processing phase, such as a declined card or processor timeout.

### Refund Processing States

When orders require returns or chargebacks, these statuses track the refund lifecycle:

- **OrderStatusRefundRequested** – A refund has been requested but not yet processed. This marks the beginning of the return workflow.

- **OrderStatusRefunding** – Refund processing is currently in progress on the payment processor side.

- **OrderStatusRefundPending** – The refund is pending external confirmation, such as waiting for bank settlement or admin approval.

- **OrderStatusPartiallyRefunded** – Only a portion of the order amount has been returned to the customer.

- **OrderStatusRefunded** – The order has been fully refunded and the transaction is reversed.

- **OrderStatusRefundFailed** – Refund processing failed due to processor errors, expired tokens, or insufficient funds in the merchant account.

## Where Order Statuses Are Defined

All order status constants are declared in **[`backend/internal/service/payment_service.go`](https://github.com/Wei-Shaw/sub2api/blob/main/backend/internal/service/payment_service.go)** at lines 24-36. These constants act as thin wrappers around the core `payment` package's `OrderStatus` values, providing type safety and consistent reference points across the service layer.

```go
// From backend/internal/service/payment_service.go (lines 24-36)
const (
    OrderStatusPending            = payment.OrderStatusPending
    OrderStatusPaid               = payment.OrderStatusPaid
    OrderStatusRecharging         = payment.OrderStatusRecharging
    OrderStatusCompleted          = payment.OrderStatusCompleted
    OrderStatusExpired            = payment.OrderStatusExpired
    OrderStatusCancelled          = payment.OrderStatusCancelled
    OrderStatusFailed             = payment.OrderStatusFailed
    OrderStatusRefundRequested    = payment.OrderStatusRefundRequested
    OrderStatusRefunding          = payment.OrderStatusRefunding
    OrderStatusRefundPending      = payment.OrderStatusRefundPending
    OrderStatusPartiallyRefunded  = payment.OrderStatusPartiallyRefunded
    OrderStatusRefunded           = payment.OrderStatusRefunded
    OrderStatusRefundFailed       = payment.OrderStatusRefundFailed
)

```

## How Order Statuses Drive the Payment Workflow

The Sub2API payment system uses these constants to enforce valid state transitions using the Ent database framework. Status checks prevent illegal operations, such as refunding an unpaid order.

### Creating a New Order

When initializing a payment order, the system explicitly sets the status to `OrderStatusPending`:

```go
order := &dbent.PaymentOrder{
    UserID:  userID,
    Amount:  9.99,
    Status:  OrderStatusPending, // <-- set to pending on creation
}

```

### Transitioning from Pending to Paid

The payment service validates the current status before updating to prevent race conditions:

```go
if err := s.entClient.PaymentOrder.Update().
    Where(paymentorder.IDEQ(order.ID), paymentorder.StatusEQ(OrderStatusPending)).
    SetStatus(OrderStatusPaid).
    Exec(ctx); err != nil {
    // handle error
}

```

### Initiating a Refund

Refund workflows begin by transitioning completed orders to `OrderStatusRefundRequested`:

```go
// Request a refund for a completed order
_, err := s.entClient.PaymentOrder.Update().
    Where(paymentorder.IDEQ(order.ID), paymentorder.StatusEQ(OrderStatusCompleted)).
    SetStatus(OrderStatusRefundRequested).
    Exec(ctx)

```

### Querying Refundable Orders

The system identifies eligible orders for refund processing by checking against multiple valid states:

```go
refundables, _ := s.entClient.PaymentOrder.Query().
    Where(
        paymentorder.StatusIn(
            OrderStatusCompleted,
            OrderStatusRefundRequested,
            OrderStatusRefundPending,
            OrderStatusRefundFailed,
        ),
    ).All(ctx)

```

## Key Implementation Files

The order status constants are referenced across four primary service files:

- **[`backend/internal/service/payment_service.go`](https://github.com/Wei-Shaw/sub2api/blob/main/backend/internal/service/payment_service.go)** – Defines all order status constants and the core `PaymentService` struct that orchestrates payment operations.

- **[`backend/internal/service/payment_order.go`](https://github.com/Wei-Shaw/sub2api/blob/main/backend/internal/service/payment_order.go)** – Implements CRUD operations and status transitions for `PaymentOrder` entities, enforcing valid state changes.

- **[`backend/internal/service/payment_refund.go`](https://github.com/Wei-Shaw/sub2api/blob/main/backend/internal/service/payment_refund.go)** – Handles the complete refund workflow, utilizing the six refund-specific status constants to track return progress.

- **[`backend/internal/service/payment_order_lifecycle.go`](https://github.com/Wei-Shaw/sub2api/blob/main/backend/internal/service/payment_order_lifecycle.go)** – Orchestrates automated state changes such as expiration handling and cancellation logic based on time-based triggers.

## Summary

- Sub2API defines **13 order status constants** in [`backend/internal/service/payment_service.go`](https://github.com/Wei-Shaw/sub2api/blob/main/backend/internal/service/payment_service.go) that wrap underlying `payment` package values.
- Statuses are grouped into standard payment flow (Pending, Paid, Completed), refund processing (RefundRequested, Refunding, Refunded), and terminal states (Expired, Failed, Cancelled).
- The system uses the Ent framework to enforce valid status transitions and prevent illegal operations like double-charging or refunding unpaid orders.
- Refund workflows involve six distinct statuses to track requests, processing, partial returns, and failures.
- Order status management is distributed across four specialized service files handling creation, lifecycle, refunds, and general service orchestration.

## Frequently Asked Questions

### What is the initial status when a payment order is created in Sub2API?

New payment orders are created with **OrderStatusPending** as defined in the `PaymentOrder` entity initialization. This status indicates the order exists in the database but no funds have been captured yet.

### How does Sub2API handle different refund states?

The system uses a six-state refund workflow: `OrderStatusRefundRequested` marks the intent, `OrderStatusRefunding` indicates active processor communication, `OrderStatusRefundPending` waits for external confirmation, and `OrderStatusRefunded` confirms completion. Partial refunds use `OrderStatusPartiallyRefunded`, while `OrderStatusRefundFailed` captures processing errors.

### What happens when a payment order expires?

Orders that exceed the payment window without completion transition to **OrderStatusExpired**. This terminal state prevents further payment attempts and is typically handled by the automated cleanup routines in [`payment_order_lifecycle.go`](https://github.com/Wei-Shaw/sub2api/blob/main/payment_order_lifecycle.go).

### Can an order be cancelled after payment in Sub2API?

No, the status constants distinguish between **OrderStatusCancelled** (pre-payment) and refund states (post-payment). Once an order reaches `OrderStatusPaid` or `OrderStatusCompleted`, cancellation is no longer valid; instead, the system must initiate a refund workflow through `OrderStatusRefundRequested`.