Sub2API Order Statuses: Complete Guide to Payment State Constants
Sub2API defines 13 distinct order status constants in 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
PaymentOrderentity 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 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.
// 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:
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:
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:
// 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:
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– Defines all order status constants and the corePaymentServicestruct that orchestrates payment operations. -
backend/internal/service/payment_order.go– Implements CRUD operations and status transitions forPaymentOrderentities, enforcing valid state changes. -
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– 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.gothat wrap underlyingpaymentpackage 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.
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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →