Documentation
¶
Overview ¶
Package checkout implements the user-facing money flows of the billing module: purchase, renewal, traffic reset, recharge, order preview and close. Only the module facade may reach it.
Index ¶
- Constants
- Variables
- type Deps
- type OrderQueue
- type PlanReader
- type Service
- func (s *Service) Close(ctx context.Context, req *dto.CloseOrderRequest) error
- func (s *Service) PreCreateOrder(ctx context.Context, req *dto.PurchaseOrderRequest) (*dto.PreOrderResponse, error)
- func (s *Service) Purchase(ctx context.Context, req *dto.PurchaseOrderRequest) (*dto.PurchaseOrderResponse, error)
- func (s *Service) Recharge(ctx context.Context, req *dto.RechargeOrderRequest) (*dto.RechargeOrderResponse, error)
- func (s *Service) Renewal(ctx context.Context, req *dto.RenewalOrderRequest) (*dto.RenewalOrderResponse, error)
- func (s *Service) ResetTraffic(ctx context.Context, req *dto.ResetTrafficOrderRequest) (*dto.ResetTrafficOrderResponse, error)
- type Store
- type UserSubscriptionReader
Constants ¶
const ( CloseOrderTimeMinutes = 15 // MaxOrderAmount Order amount limits MaxOrderAmount = 2147483647 // int32 max value (2.1 billion) MaxRechargeAmount = 2000000000 // 2 billion, slightly lower for safety MinRechargeAmount = 100 // minimum recharge amount in minor currency units MaxQuantity = 1000 // Maximum quantity per order )
Order lifecycle constants shared with the V2 orchestration layer via the module facade.
Variables ¶
var ErrGatewayUnconfirmed = stderrors.New("gateway could not confirm the order as paid")
ErrGatewayUnconfirmed reports that an EPay order could not be confirmed as paid, so the close was refused and the order intentionally stays pending. Schedulers treat it as an expected outcome, not a per-order failure.
Functions ¶
This section is empty.
Types ¶
type Deps ¶
type Deps struct {
Orders repository.OrderRepo
Coupons repository.CouponRepo
Payments repository.PaymentRepo
Plans PlanReader
UserSubs UserSubscriptionReader
Store Store
Queue OrderQueue
// SingleModel forbids holding more than one blocking subscription;
// read per request because the admin can change it at runtime.
SingleModel func() bool
// CurrencyUnit is the site currency used for gateway verification;
// read per request because the admin can change it at runtime.
CurrencyUnit func() string
}
type OrderQueue ¶
type OrderQueue interface {
EnqueueActivation(ctx context.Context, orderNo string) error
EnqueueDeferredClose(ctx context.Context, orderNo string) error
}
OrderQueue mirrors the facade's order queue port.
type PlanReader ¶
type PlanReader interface {
FindOne(ctx context.Context, id int64) (*subscribeEntity.Subscribe, error)
}
PlanReader is the module's port onto the subscription domain's plan catalogue; the legacy subscribe repository satisfies it structurally.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
func NewService ¶
func (*Service) Close ¶
Close closes a pending order: the billing transaction releases the coupon reservation and refunds the gift deduction, then the reserved plan inventory returns in its own subscription-domain transaction (ADR-001 step 2). Orders whose gateway checkout already collected money are settled instead of closed.
func (*Service) PreCreateOrder ¶
func (s *Service) PreCreateOrder(ctx context.Context, req *dto.PurchaseOrderRequest) (*dto.PreOrderResponse, error)
PreCreateOrder calculates order pricing preview including discounts, coupons, gift amounts, and fees without actually creating an order. It validates subscription plans, coupons, and payment methods to provide accurate pricing information for the frontend order preview.
func (*Service) Purchase ¶
func (s *Service) Purchase(ctx context.Context, req *dto.PurchaseOrderRequest) (*dto.PurchaseOrderResponse, error)
Purchase processes new subscription purchase orders including validation, discount calculation, coupon processing, gift amount deduction, fee calculation, and order creation with database transaction. It handles the complete purchase workflow from user validation to order creation and task scheduling.
func (*Service) Recharge ¶
func (s *Service) Recharge(ctx context.Context, req *dto.RechargeOrderRequest) (*dto.RechargeOrderResponse, error)
Recharge creates a balance recharge order.
func (*Service) Renewal ¶
func (s *Service) Renewal(ctx context.Context, req *dto.RenewalOrderRequest) (*dto.RenewalOrderResponse, error)
Renewal processes subscription renewal orders including discount calculation, coupon validation, gift amount deduction, fee calculation, and order creation
func (*Service) ResetTraffic ¶
func (s *Service) ResetTraffic(ctx context.Context, req *dto.ResetTrafficOrderRequest) (*dto.ResetTrafficOrderResponse, error)
ResetTraffic creates a paid traffic-reset order for an active subscription.
type Store ¶
type Store interface {
InBillingTx(ctx context.Context, fn func(repository.BillingStore) error) error
InSubscriptionTx(ctx context.Context, fn func(repository.SubscriptionStore) error) error
Inbox() repository.InboxRepo
Wallet() repository.WalletRepo
}
Store is the subdomain's persistence surface: billing-scoped transactions, the wallet view, and the inbox + subscription-scoped transaction the inventory lifecycle helpers need. The repository store satisfies it structurally.
type UserSubscriptionReader ¶
type UserSubscriptionReader interface {
HasBlockingSubscription(ctx context.Context, userID int64) (bool, error)
CountQuotaConsumingSubscriptions(ctx context.Context, userID, subscribeID int64) (int64, error)
FindOneUserSubscribe(ctx context.Context, id int64) (*usersub.SubscribeDetails, error)
FindOneSubscribe(ctx context.Context, id int64) (*usersub.Subscribe, error)
}
UserSubscriptionReader is the module's port onto the subscription domain's user subscriptions; the legacy user-subscription repository satisfies it structurally.