thread-master/apps/backend/internal/module/billing/domain.go

149 lines
4.5 KiB
Go
Raw Permalink Normal View History

2026-07-15 15:23:59 +00:00
package billing
import (
"context"
"errors"
)
var (
ErrDisabled = errors.New("billing is not configured")
ErrInvalidPlan = errors.New("invalid billing plan")
ErrInvalidRequest = errors.New("invalid billing request")
ErrNotFound = errors.New("billing record not found")
ErrConflict = errors.New("billing request is already being created")
ErrInvalidSignature = errors.New("invalid stripe signature")
ErrCustomerRequired = errors.New("stripe customer is not available")
)
const (
PlanFree = "free"
PlanStarter = "starter"
PlanPro = "pro"
)
type CheckoutAttempt struct {
ID string `bson:"_id"`
UID int64 `bson:"uid"`
RequestID string `bson:"request_id"`
PlanID string `bson:"plan_id"`
PriceID string `bson:"price_id"`
SessionID string `bson:"session_id,omitempty"`
URL string `bson:"url,omitempty"`
ExpiresAt int64 `bson:"expires_at,omitempty"`
Status string `bson:"status"`
PaymentStatus string `bson:"payment_status,omitempty"`
FulfillmentStatus string `bson:"fulfillment_status"`
CustomerID string `bson:"customer_id,omitempty"`
SubscriptionID string `bson:"subscription_id,omitempty"`
Error string `bson:"error,omitempty"`
CreatedAt int64 `bson:"created_at"`
UpdatedAt int64 `bson:"updated_at"`
}
type SubscriptionState struct {
UID int64
PlanID string
PaidPlanID string
Status string
CustomerID string
SubscriptionID string
CurrentPeriodStart int64
CurrentPeriodEnd int64
CancelAtPeriodEnd bool
AdminOverride bool
}
type ProviderCheckout struct {
SessionID string
URL string
ExpiresAt int64
Status string
PaymentStatus string
PriceID string
CustomerID string
SubscriptionID string
}
type CheckoutParams struct {
UID int64
AttemptID string
PlanID string
PriceID string
CustomerID string
SuccessURL string
CancelURL string
IdempotencyKey string
}
type ProviderSubscription struct {
ID string
CustomerID string
Status string
PriceID string
CurrentPeriodStart int64
CurrentPeriodEnd int64
CancelAtPeriodEnd bool
}
type Event struct {
ID string
Type string
Created int64
ObjectID string
SubscriptionID string
CustomerID string
PriceID string
Status string
PeriodStart int64
PeriodEnd int64
CancelAtPeriodEnd bool
}
type EntitlementUpdate struct {
EventID string
EventCreatedAt int64
UID int64
PlanID string
PaidPlanID string
Status string
CustomerID string
SubscriptionID string
CurrentPeriodStart int64
CurrentPeriodEnd int64
CancelAtPeriodEnd bool
}
type PurchaseAudit struct {
ID string `bson:"_id"`
UID int64 `bson:"uid"`
PlanID string `bson:"plan_id"`
StripeEventID string `bson:"stripe_event_id"`
StripeSessionID string `bson:"stripe_session_id,omitempty"`
StripeCustomerID string `bson:"stripe_customer_id,omitempty"`
StripeSubscriptionID string `bson:"stripe_subscription_id,omitempty"`
Status string `bson:"status"`
CreatedAt int64 `bson:"created_at"`
}
type Provider interface {
CreateCheckout(context.Context, CheckoutParams) (*ProviderCheckout, error)
GetCheckout(context.Context, string) (*ProviderCheckout, error)
GetSubscription(context.Context, string) (*ProviderSubscription, error)
CreatePortal(context.Context, string, string) (string, error)
VerifyEvent([]byte, string, string) (*Event, error)
}
type Repository interface {
InsertCheckout(context.Context, *CheckoutAttempt) (bool, error)
GetCheckoutByRequest(context.Context, int64, string) (*CheckoutAttempt, error)
GetCheckout(context.Context, int64, string) (*CheckoutAttempt, error)
GetCheckoutBySession(context.Context, string) (*CheckoutAttempt, error)
UpdateCheckout(context.Context, *CheckoutAttempt) error
GetSubscription(context.Context, int64) (*SubscriptionState, error)
FindUIDByCustomer(context.Context, string) (int64, error)
ApplyEntitlement(context.Context, EntitlementUpdate) (bool, error)
WebhookProcessed(context.Context, string) (bool, error)
MarkWebhookProcessed(context.Context, string, string, int64) error
UpsertPurchase(context.Context, *PurchaseAudit) error
}