Documentation
¶
Overview ¶
Package order holds the billing domain's order entities and the rules that travel with them: the order and its details, the status state machine, order numbers, the durable order events and their wake-up channels, and the guest checkout data an order carries until the guest's account exists.
Index ¶
- Constants
- func CanCheckout(status uint8) bool
- func CanClose(status uint8) bool
- func CanSettle(status uint8) bool
- func CheckoutTokenHash(token string) string
- func CouponUseStatuses() []uint8
- func EventChannel(orderNo string) string
- func FulfillmentStatusName(status uint8) string
- func GenerateTradeNo() string
- func IsSettled(status uint8) bool
- func IsTerminal(status uint8) bool
- func PaymentStatusName(status uint8) string
- func SettledStatuses() []uint8
- func StatusName(status uint8) string
- type DailyBreakdown
- type DailyReport
- type Details
- type Event
- type Order
- type OrdersTotal
- type OrdersTotalWithDate
- type TemporaryOrderInfo
- type UserCounts
Constants ¶
const ( TypeSubscribe uint8 = 1 TypeRenewal uint8 = 2 TypeResetTraffic uint8 = 3 TypeRecharge uint8 = 4 )
Order types, the values of the Type column.
const ( StatusPending uint8 = 1 StatusPaid uint8 = 2 StatusClosed uint8 = 3 StatusFailed uint8 = 4 StatusFinished uint8 = 5 )
Order statuses, the values of the Status column. An order moves from Pending to Paid when the payment is confirmed and from Paid to Finished once it is fulfilled; Closed and Failed end a Pending order.
const EventTypePaymentPaid = "order.payment_paid"
EventTypePaymentPaid is the type of the event the order repository appends with the Pending -> Paid transition; its CreatedAt is when the order was settled, the reference point of the guest session exchange.
const PaymentSessionStarting = `{"state":"creating"}`
PaymentSessionStarting is a durable fence, not a payment result. A process crash or timeout after this write leaves an unknown attempt to reconcile.
const PaymentWindow = PaymentWindowMinutes * time.Minute
PaymentWindow is PaymentWindowMinutes as a duration.
const PaymentWindowMinutes = 15
PaymentWindowMinutes is how long a pending order waits for its payment before the deferred close task expires it; gateway checkouts are opened for the same window.
const TempOrderCacheKey = "temp_order:%s"
TempOrderCacheKey is the Redis key format of the temporary guest order older releases kept until payment: temp_order:<order no>.
const UnpaidCloseAge = 2 * PaymentWindow
UnpaidCloseAge is the age from which a pending order is treated as abandoned: the expiry close releases an order a gateway that cannot cancel an issued payment page lists as unpaid, and a guest's pending order no longer counts toward the pending-order cap. It doubles the payment window so a payer who opened the gateway page near expiry still finishes.
Variables ¶
This section is empty.
Functions ¶
func CanCheckout ¶ added in v1.21.0
CanCheckout reports whether a payment may be started for an order in status; checkout is only offered while the order waits for payment.
func CanClose ¶ added in v1.21.0
CanClose reports whether an order in status may still be closed: only a pending order can be given up.
func CanSettle ¶ added in v1.21.0
CanSettle reports whether a verified payment may settle an order in status. A pending order becomes paid; a paid order only re-enqueues its activation, which heals a settlement whose queue insertion failed.
func CheckoutTokenHash ¶ added in v1.20.3
CheckoutTokenHash returns the durable representation of the guest checkout capability. Only the caller receives the original high-entropy token.
func CouponUseStatuses ¶ added in v1.21.0
func CouponUseStatuses() []uint8
CouponUseStatuses lists the statuses of orders that count against a coupon's per-user limit: pending orders hold a reservation and settled orders consumed a use.
func EventChannel ¶ added in v1.20.3
EventChannel returns the Redis Pub/Sub channel for one order's durable event stream. The channel is only a wake-up path; consumers still read events from the database by id.
func FulfillmentStatusName ¶ added in v1.21.0
FulfillmentStatusName names the fulfillment side of an order status, as carried by V2 snapshots and order events.
func GenerateTradeNo ¶ added in v1.20.2
func GenerateTradeNo() string
GenerateTradeNo returns a fixed-width numeric trade number: a 14-digit timestamp in the application's time zone followed by 14 uniformly random digits from crypto/rand. crypto/rand cannot fail in practice; the panic matches how the password salt handles the same error.
func IsSettled ¶ added in v1.21.0
IsSettled reports whether the order's payment was collected: it is paid and awaiting fulfillment, or already finished.
func IsTerminal ¶ added in v1.21.0
IsTerminal reports whether no transition leaves status.
func PaymentStatusName ¶ added in v1.21.0
PaymentStatusName names the payment side of an order status, as carried by V2 snapshots and order events.
func SettledStatuses ¶ added in v1.21.0
func SettledStatuses() []uint8
SettledStatuses lists the statuses IsSettled accepts, for queries that select settled orders. Repositories must bind them as integers: a []uint8 is a byte string to database/sql, not a list.
func StatusName ¶ added in v1.21.0
StatusName is the client-facing name of an order status in the V2 API.
Types ¶
type DailyBreakdown ¶ added in v1.15.16
type DailyBreakdown struct {
// Name is the plan name or the payment platform, depending on the group.
Name string
// Id is the grouped plan id; zero for a payment-method group and for
// orders that carry no plan, such as balance top-ups.
Id int64
Orders int64
Amount int64
}
DailyBreakdown is one row of a settled-order breakdown, grouped by plan or by payment method for the daily report.
type DailyReport ¶ added in v1.15.16
type DailyReport struct {
Date time.Time
Orders int64
Amount int64
ByPlan []DailyBreakdown
ByMethod []DailyBreakdown
}
DailyReport totals the orders settled on one day, alongside the plan and payment-method breakdowns.
type Details ¶
type Details struct {
Id int64 `gorm:"primaryKey"`
ParentId int64 `gorm:"type:bigint;default:null;comment:Parent Order Id"`
SubOrders []*Order `gorm:"foreignKey:ParentId;references:Id"`
UserId int64 `gorm:"type:bigint;not null;default:0;comment:User Id"`
OrderNo string `gorm:"type:varchar(255);not null;default:'';unique;comment:Order No"`
Type uint8 `gorm:"type:tinyint(1);not null;default:1;comment:Order Type: 1: Subscribe, 2: Renewal, 3: ResetTraffic, 4: Recharge"`
Quantity int64 `gorm:"type:bigint;not null;default:1;comment:Quantity"`
Price int64 `gorm:"type:int;not null;default:0;comment:Original price"`
Amount int64 `gorm:"type:int;not null;default:0;comment:Order Amount"`
Discount int64 `gorm:"type:int;not null;default:0;comment:Order Discount"`
Coupon string `gorm:"type:varchar(255);default:null;comment:Coupon"`
CouponDiscount int64 `gorm:"type:int;not null;default:0;comment:Coupon Discount"`
PaymentId int64 `gorm:"type:bigint;not null;default:0;comment:Payment Id"`
Payment *payment.Payment `gorm:"foreignKey:PaymentId;references:Id"`
Method string `gorm:"type:varchar(255);not null;default:'';comment:Payment Method"`
FeeAmount int64 `gorm:"type:int;not null;default:0;comment:Fee Amount"`
PaymentAmount int64 `gorm:"type:bigint;not null;default:0;comment:Amount requested by payment gateway in minor units"`
PaymentCurrency string `gorm:"type:varchar(16);not null;default:'';comment:Payment gateway currency"`
TradeNo string `gorm:"type:varchar(255);default:null;comment:Trade No"`
GiftAmount int64 `gorm:"type:int;not null;default:0;comment:User Gift Amount"`
Commission int64 `gorm:"type:int;not null;default:0;comment:Order Commission"`
CommissionRefererId int64 `gorm:"type:bigint;not null;default:0;comment:Referrer credited with the commission"`
Status uint8 `gorm:"type:tinyint(1);not null;default:1;comment:Order Status: 1: Pending, 2: Paid, 3: Failed"`
SubscribeId int64 `gorm:"type:bigint;not null;default:0;comment:Subscribe Id"`
SubscribeToken string `gorm:"type:varchar(255);default:null;comment:Renewal Subscribe Token"`
UserSubscribeId int64 `gorm:"column:user_subscribe_id;type:bigint;not null;default:0;comment:User subscription renewed or reset by the order"`
Subscribe *subscribe.Subscribe `gorm:"foreignKey:SubscribeId;references:Id"`
IsNew bool `gorm:"type:tinyint(1);not null;default:0;comment:Is New Order"`
CreatedAt time.Time `gorm:"<-:create;comment:Create Time"`
UpdatedAt time.Time `gorm:"comment:Update Time"`
}
func (*Details) RefundBasis ¶ added in v1.21.0
RefundBasis is what was paid for the subscription term: the original order plus its paid renewals. Traffic resets buy traffic, not time, and are not refunded. The refund quote and the refund settlement both measure against it.
An order's Amount is what was paid with money (through a gateway or from the wallet balance) and its GiftAmount the gift credit it consumed, at creation and at a balance checkout alike; the two never hold the same unit, so their sum is the value paid and refunding each to its own balance returns exactly that value.
type Event ¶
type Event struct {
ID int64 `gorm:"primaryKey;autoIncrement"`
OrderID int64 `gorm:"type:bigint;not null;index:idx_order_event_order_id_id,priority:1"`
OrderNo string `gorm:"type:varchar(255);not null;index:idx_order_event_order_no_id,priority:1"`
EventType string `gorm:"type:varchar(64);not null"`
Payload string `gorm:"type:text;not null"`
CreatedAt time.Time `gorm:"<-:create"`
PublishedAt *time.Time `gorm:"index:idx_order_event_published_at_id,priority:1"`
}
Event is the durable order event outbox. Redis only distributes these records with low latency; reconnecting clients always recover from this table.
type Order ¶
type Order struct {
Id int64 `gorm:"primaryKey"`
ParentId int64 `gorm:"type:bigint;default:null;comment:Parent Order Id"`
UserId int64 `gorm:"type:bigint;not null;default:0;comment:User Id"`
OrderNo string `gorm:"type:varchar(255);not null;default:'';unique;comment:Order No"`
Type uint8 `gorm:"type:tinyint(1);not null;default:1;comment:Order Type: 1: Subscribe, 2: Renewal, 3: ResetTraffic, 4: Recharge"`
Quantity int64 `gorm:"type:bigint;not null;default:1;comment:Quantity"`
Price int64 `gorm:"type:int;not null;default:0;comment:Original price"`
Amount int64 `gorm:"type:int;not null;default:0;comment:Order Amount"`
GiftAmount int64 `gorm:"type:int;not null;default:0;comment:User Gift Amount"`
Discount int64 `gorm:"type:int;not null;default:0;comment:Discount Amount"`
Coupon string `gorm:"type:varchar(255);default:null;comment:Coupon"`
CouponDiscount int64 `gorm:"type:int;not null;default:0;comment:Coupon Discount Amount"`
CouponReserved bool `gorm:"type:tinyint(1);not null;default:0;comment:Coupon usage reserved while order is pending"`
Commission int64 `gorm:"type:int;not null;default:0;comment:Order Commission"`
CommissionRefererId int64 `gorm:"type:bigint;not null;default:0;comment:Referrer credited with the commission"`
PaymentId int64 `gorm:"type:bigint;not null;default:0;comment:Payment Method Id"`
Method string `gorm:"type:varchar(255);not null;default:'';comment:Payment Method"`
FeeAmount int64 `gorm:"type:int;not null;default:0;comment:Fee Amount"`
PaymentAmount int64 `gorm:"type:bigint;not null;default:0;comment:Amount requested by payment gateway in minor units"`
PaymentCurrency string `gorm:"type:varchar(16);not null;default:'';comment:Payment gateway currency"`
PaymentSession string `gorm:"type:text;default:null;comment:Durable external checkout attempt and payment entry" json:"-"`
TradeNo string `gorm:"type:varchar(255);default:null;comment:Trade No"`
Status uint8 `gorm:"type:tinyint(1);not null;default:1;comment:Order Status: 1: Pending, 2: Paid, 3:Close, 4: Failed, 5:Finished;"`
SubscribeId int64 `gorm:"type:bigint;not null;default:0;comment:Subscribe Id"`
SubscribeToken string `gorm:"type:varchar(255);default:null;comment:Renewal Subscribe Token"`
UserSubscribeId int64 `gorm:"column:user_subscribe_id;type:bigint;not null;default:0;comment:User subscription renewed or reset by the order"`
GuestAuthType string `gorm:"type:varchar(255);not null;default:'';comment:Guest auth type before account activation"`
GuestIdentifier string `gorm:"type:varchar(255);not null;default:'';comment:Guest auth identifier before account activation"`
GuestPasswordHash string `gorm:"type:varchar(255);not null;default:'';comment:Guest password hash before account activation"`
GuestInviteCode string `gorm:"type:varchar(255);not null;default:'';comment:Guest invite code before account activation"`
GuestCheckoutTokenHash string `gorm:"type:char(64);not null;default:'';comment:Hash of guest checkout capability"`
StateVersion int64 `gorm:"type:bigint;not null;default:0;comment:Monotonic version for order state transitions"`
IdempotencyKey string `gorm:"type:varchar(128);uniqueIndex;default:null;comment:V2 create idempotency key"`
IdempotencyHash string `gorm:"type:char(64);default:null;comment:Stable hash of the V2 create request"`
IsNew bool `gorm:"type:tinyint(1);not null;default:0;comment:Is New Order"`
CreatedAt time.Time `gorm:"<-:create;comment:Create Time"`
UpdatedAt time.Time `gorm:"comment:Update Time"`
}
func (*Order) IsPaidRenewal ¶ added in v1.21.0
IsPaidRenewal reports whether the order renews a subscription and its payment was collected.
type OrdersTotal ¶
type OrdersTotalWithDate ¶
type TemporaryOrderInfo ¶ added in v1.20.3
type TemporaryOrderInfo struct {
OrderNo string `json:"order_no"`
CheckoutToken string `json:"checkout_token"`
Identifier string `json:"identifier"`
AuthType string `json:"auth_type"`
// PasswordHash is the one-way encoded password needed to finish a guest
// account after payment. Never place the plaintext password in Redis.
PasswordHash string `json:"password_hash,omitempty"`
// Password is retained only to finish orders created by older releases.
// New orders never populate it and it must never be logged.
Password string `json:"password,omitempty"`
InviteCode string `json:"invite_code,omitempty"`
}
func (*TemporaryOrderInfo) Marshal ¶ added in v1.20.3
func (t *TemporaryOrderInfo) Marshal() ([]byte, error)
func (*TemporaryOrderInfo) Unmarshal ¶ added in v1.20.3
func (t *TemporaryOrderInfo) Unmarshal(data []byte) error
type UserCounts ¶
type UserCounts struct {
NewUsers int64 `gorm:"column:new_users"`
RenewalUsers int64 `gorm:"column:renewal_users"`
}
UserCounts User counts for new and renewal users