149 lines
4.5 KiB
Go
149 lines
4.5 KiB
Go
|
|
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
|
||
|
|
}
|