Documentation
¶
Overview ¶
contract.go: Wires the subscription plugin into the forge-dashboard contract surface via plugin.ContractContributor.
Package subscription provides a billing/subscription management plugin for authsome.
It delegates all billing logic to the ledger engine (github.com/xraph/ledger) and hooks into authsome lifecycle events (org creation, user signup, member changes) to automate subscription workflows. The plugin provides:
- Dynamic settings for configurable tenant mode, trial periods, and auto-subscription
- REST API routes for plan, subscription, invoice, and entitlement management
- A rich dashboard UI for administrators to manage billing
- User and organization detail section contributions
Index ¶
- Variables
- type CancelCurrentRequest
- type CancelSubscriptionRequest
- type ChangePlanRequest
- type CheckEntitlementRequest
- type CheckoutProvider
- type CheckoutRequest
- type CheckoutResult
- type Config
- type CouponResponse
- type CreateCouponRequest
- type CreatePlanRequest
- type CreateSubscriptionRequest
- type CurrentSubscriptionRequest
- type CurrentSubscriptionResponse
- type DeleteCouponRequest
- type EntitlementResponse
- type EntitlementsResponse
- type FeatureInput
- type GetActiveSubRequest
- type GetInvoiceRequest
- type GetPlanRequest
- type InvoiceIDRequest
- type InvoiceResponse
- type ListCouponsRequest
- type ListCouponsResponse
- type ListEntitlementsRequest
- type ListInvoicesRequest
- type ListInvoicesResponse
- type ListPlansRequest
- type ListPlansResponse
- type ListSubscriptionsRequest
- type ListSubscriptionsResponse
- type MarkInvoicePaidRequest
- type PlanFeatureResponse
- type PlanIDRequest
- type PlanResponse
- type Plugin
- func (p *Plugin) CompleteCheckout(ctx context.Context, req CheckoutRequest) (*lsub.Subscription, error)
- func (p *Plugin) DeclareSettings(m *settings.Manager) error
- func (p *Plugin) Name() string
- func (p *Plugin) OnAfterMemberAdd(ctx context.Context, _ *organization.Member) error
- func (p *Plugin) OnAfterOrgCreate(ctx context.Context, o *organization.Organization) error
- func (p *Plugin) OnAfterOrgDelete(ctx context.Context, orgID id.OrgID) error
- func (p *Plugin) OnAfterSignUp(ctx context.Context, u *user.User, _ *session.Session) error
- func (p *Plugin) OnInit(_ context.Context, engine plugin.Engine) error
- func (p *Plugin) RegisterContract(d *dispatcher.Dispatcher, reg contract.Registry, wreg contract.WardenRegistry, ...) error
- func (p *Plugin) RegisterRoutes(router forge.Router) error
- func (p *Plugin) Service() *Service
- func (p *Plugin) SetCheckoutProvider(cp CheckoutProvider)
- func (p *Plugin) SetLedger(l *ledger.Ledger)
- func (p *Plugin) SetLedgerStore(st ledgerstore.Store)
- type PortalProvider
- type PortalRequest
- type PortalResponse
- type SeatsView
- type Service
- func (s *Service) ActivatePlan(ctx context.Context, planID ledgerid.PlanID) error
- func (s *Service) ArchiveCatalogFeature(ctx context.Context, featureID ledgerid.FeatureID) error
- func (s *Service) ArchivePlan(ctx context.Context, planID ledgerid.PlanID) error
- func (s *Service) CalculateMRR(ctx context.Context, appID string) string
- func (s *Service) CancelSubscription(ctx context.Context, subID ledgerid.SubscriptionID, immediately bool) error
- func (s *Service) ChangePlan(ctx context.Context, subID ledgerid.SubscriptionID, newPlanID ledgerid.PlanID, ...) (*subscription.Subscription, error)
- func (s *Service) CheckEntitlement(ctx context.Context, featureKey string) (*entitlement.Result, error)
- func (s *Service) CountSubscribers(ctx context.Context, planID ledgerid.PlanID, appID string) int
- func (s *Service) CreateCatalogFeature(ctx context.Context, f *feature.Feature) error
- func (s *Service) CreateCoupon(ctx context.Context, c *coupon.Coupon) error
- func (s *Service) CreatePlan(ctx context.Context, p *plan.Plan) error
- func (s *Service) CurrentSubscription(ctx context.Context, tenantID, appID string) (*subscription.Subscription, error)
- func (s *Service) DeleteCatalogFeature(ctx context.Context, featureID ledgerid.FeatureID) error
- func (s *Service) DeleteCoupon(ctx context.Context, couponID ledgerid.CouponID) error
- func (s *Service) GenerateInvoice(ctx context.Context, subID ledgerid.SubscriptionID) (*invoice.Invoice, error)
- func (s *Service) GetActiveSubscription(ctx context.Context, tenantID, appID string) (*subscription.Subscription, error)
- func (s *Service) GetCatalogFeature(ctx context.Context, featureID ledgerid.FeatureID) (*feature.Feature, error)
- func (s *Service) GetCatalogFeatureByKey(ctx context.Context, key, appID string) (*feature.Feature, error)
- func (s *Service) GetCoupon(ctx context.Context, code, appID string) (*coupon.Coupon, error)
- func (s *Service) GetCouponByID(ctx context.Context, couponID ledgerid.CouponID) (*coupon.Coupon, error)
- func (s *Service) GetInvoice(ctx context.Context, invID ledgerid.InvoiceID) (*invoice.Invoice, error)
- func (s *Service) GetPlan(ctx context.Context, planID ledgerid.PlanID) (*plan.Plan, error)
- func (s *Service) GetPlanBySlug(ctx context.Context, slug, appID string) (*plan.Plan, error)
- func (s *Service) GetSubscription(ctx context.Context, subID ledgerid.SubscriptionID) (*subscription.Subscription, error)
- func (s *Service) GetUsageSummary(ctx context.Context, tenantID, appID string) ([]UsageSummary, error)
- func (s *Service) KeepSubscription(ctx context.Context, subID ledgerid.SubscriptionID) (*subscription.Subscription, error)
- func (s *Service) ListAllInvoices(ctx context.Context, appID string) ([]*invoice.Invoice, error)
- func (s *Service) ListCatalogFeatures(ctx context.Context, appID string) ([]*feature.Feature, error)
- func (s *Service) ListCoupons(ctx context.Context, appID string) ([]*coupon.Coupon, error)
- func (s *Service) ListInvoices(ctx context.Context, tenantID, appID string) ([]*invoice.Invoice, error)
- func (s *Service) ListPlans(ctx context.Context, appID string) ([]*plan.Plan, error)
- func (s *Service) ListPlansWithOpts(ctx context.Context, appID string, opts plan.ListOpts) ([]*plan.Plan, error)
- func (s *Service) ListSubscriptions(ctx context.Context, tenantID, appID string, opts subscription.ListOpts) ([]*subscription.Subscription, error)
- func (s *Service) MarkInvoicePaid(ctx context.Context, invID ledgerid.InvoiceID, paymentRef string) error
- func (s *Service) MarkInvoiceVoided(ctx context.Context, invID ledgerid.InvoiceID, reason string) error
- func (s *Service) PauseSubscription(ctx context.Context, subID ledgerid.SubscriptionID) (*subscription.Subscription, error)
- func (s *Service) ResumeSubscription(ctx context.Context, subID ledgerid.SubscriptionID) (*subscription.Subscription, error)
- func (s *Service) SetLedgerStore(st ledgerstore.Store)
- func (s *Service) Subscribe(ctx context.Context, tenantID string, planID ledgerid.PlanID, appID string, ...) (*subscription.Subscription, error)
- func (s *Service) UpdateCatalogFeature(ctx context.Context, f *feature.Feature) error
- func (s *Service) UpdatePlan(ctx context.Context, p *plan.Plan) error
- type SubIDRequest
- type SubscribeRequest
- type SubscriptionMutationResponse
- type SubscriptionResponse
- type SubscriptionView
- type TenantRequest
- type UpdateSubscriptionRequest
- type UsageItemResponse
- type UsageSummary
- type UsageSummaryRequest
- type UsageSummaryResponse
- type VoidInvoiceRequest
Constants ¶
This section is empty.
Variables ¶
var ( // SettingDefaultPlan is the plan slug to auto-assign to new tenants. SettingDefaultPlan = settings.Define("subscription.default_plan", "", settings.WithDisplayName("Default Plan"), settings.WithDescription("Plan slug to auto-assign to new tenants"), settings.WithCategory("Subscription"), settings.WithScopes(settings.ScopeGlobal, settings.ScopeApp), settings.WithInputType(formconfig.FieldText), settings.WithPlaceholder("e.g. free, starter"), settings.WithHelpText("Leave empty to disable auto-subscription"), settings.WithOrder(10), ) // SettingTenantMode controls whether subscriptions are org-level or user-level. SettingTenantMode = settings.Define("subscription.tenant_mode", "organization", settings.WithDisplayName("Tenant Mode"), settings.WithDescription("Whether subscriptions are scoped to organizations or individual users"), settings.WithCategory("Subscription"), settings.WithScopes(settings.ScopeGlobal, settings.ScopeApp), settings.WithInputType(formconfig.FieldSelect), settings.WithOptions( formconfig.SelectOption{Label: "Organization", Value: "organization"}, formconfig.SelectOption{Label: "User", Value: "user"}, ), settings.WithHelpText("Determines whether billing is org-level or user-level"), settings.WithOrder(15), ) // SettingAutoSubscribeOrg controls auto-subscription for new organizations. SettingAutoSubscribeOrg = settings.Define("subscription.auto_subscribe_org", true, settings.WithDisplayName("Auto-Subscribe Organizations"), settings.WithDescription("Automatically create a subscription when an organization is created"), settings.WithCategory("Subscription"), settings.WithScopes(settings.ScopeGlobal, settings.ScopeApp), settings.WithVisibleWhen("subscription.tenant_mode", "organization", "eq"), settings.WithOrder(20), ) // SettingAutoSubscribeUser controls auto-subscription for new users. SettingAutoSubscribeUser = settings.Define("subscription.auto_subscribe_user", false, settings.WithDisplayName("Auto-Subscribe Users"), settings.WithDescription("Automatically create a subscription when a user signs up"), settings.WithCategory("Subscription"), settings.WithScopes(settings.ScopeGlobal, settings.ScopeApp), settings.WithVisibleWhen("subscription.tenant_mode", "user", "eq"), settings.WithOrder(30), ) // SettingTrialDays controls the default trial period for new subscriptions. SettingTrialDays = settings.Define("subscription.trial_days", 14, settings.WithDisplayName("Trial Period (days)"), settings.WithDescription("Number of trial days for new subscriptions (0 = no trial)"), settings.WithCategory("Subscription"), settings.WithScopes(settings.ScopeGlobal, settings.ScopeApp), settings.WithEnforceable(), settings.WithInputType(formconfig.FieldNumber), settings.WithUIValidation(formconfig.Validation{Min: intPtr(0), Max: intPtr(365)}), settings.WithHelpText("Set to 0 to disable trials. Default: 14"), settings.WithOrder(40), ) // SettingSelfServiceUpgrade controls whether tenants can change their own plan. SettingSelfServiceUpgrade = settings.Define("subscription.self_service_upgrade", true, settings.WithDisplayName("Allow Self-Service Plan Changes"), settings.WithDescription("Allow users/orgs to upgrade or downgrade their own plan"), settings.WithCategory("Subscription"), settings.WithScopes(settings.ScopeGlobal, settings.ScopeApp), settings.WithOrder(50), ) // SettingBillingRoles lists the organization member roles that may change // their own organization's plan through the self-service routes. It is // the org-level billing permission: app roles in Warden aren't scoped to // an organization yet, so the grant lives here, where an organization can // override it for itself. SettingBillingRoles = settings.Define("subscription.billing_roles", []string{"owner"}, settings.WithDisplayName("Billing Roles"), settings.WithDescription("Organization roles that can change the organization's plan"), settings.WithCategory("Subscription"), settings.WithScopes(settings.ScopeGlobal, settings.ScopeApp, settings.ScopeOrg), settings.WithInputType(formconfig.FieldTextarea), settings.WithPlaceholder("owner\nadmin"), settings.WithHelpText("One role per line. Members with any other role can see the plan but not change it. Default: owner"), settings.WithOrder(55), ) // SettingGracePeriodDays controls the grace period after billing failure. SettingGracePeriodDays = settings.Define("subscription.grace_period_days", 3, settings.WithDisplayName("Grace Period (days)"), settings.WithDescription("Days after billing failure before restricting access"), settings.WithCategory("Subscription"), settings.WithScopes(settings.ScopeGlobal, settings.ScopeApp), settings.WithInputType(formconfig.FieldNumber), settings.WithUIValidation(formconfig.Validation{Min: intPtr(0), Max: intPtr(30)}), settings.WithHelpText("Set to 0 for immediate restriction. Default: 3"), settings.WithOrder(60), ) )
var ErrCancelDue = errors.New("subscription: the cancellation is already due")
ErrCancelDue is returned by KeepSubscription when the scheduled cancellation's time has already come.
var ErrNoScheduledCancel = errors.New("subscription: no cancellation is scheduled")
ErrNoScheduledCancel is returned by KeepSubscription when the subscription has no cancellation waiting at the end of its period.
Functions ¶
This section is empty.
Types ¶
type CancelCurrentRequest ¶ added in v1.10.0
type CancelCurrentRequest struct {
When string `json:"when,omitempty"`
TenantID string `json:"tenant_id,omitempty"`
}
CancelCurrentRequest cancels at the period end (the default) or now.
type CancelSubscriptionRequest ¶ added in v1.9.0
type ChangePlanRequest ¶ added in v1.9.0
type CheckEntitlementRequest ¶ added in v1.9.0
type CheckoutProvider ¶ added in v1.10.0
type CheckoutProvider interface {
Checkout(ctx context.Context, req CheckoutRequest) (CheckoutResult, error)
}
CheckoutProvider decides whether a self-service plan change has to be paid for before it happens.
When one is configured, every subscribe and every plan or seat change goes through Checkout first. Answer with a URL to send the customer to your payment page; nothing changes until your webhook calls Plugin.CompleteCheckout. Answer with an empty URL when there's nothing to pay (a free plan, a downgrade, fewer seats) and the change is applied straight away. Cancellations and resumes never go through the provider: keep your payment provider in step by listening for the subscription.canceled, subscription.plan_changed and subscription.resumed events.
type CheckoutRequest ¶
type CheckoutRequest struct {
TenantID string
AppID string
// Plan is the plan being moved to.
Plan *plan.Plan
// Current is the tenant's subscription, nil for a new one, and
// CurrentPlan its plan.
Current *lsub.Subscription
CurrentPlan *plan.Plan
// Quantity holds seat counts by feature key, nil to keep the current ones.
Quantity map[string]int64
// ReturnURL and CancelURL are where the client asked to land after
// paying or backing out. Either may be empty.
ReturnURL string
CancelURL string
// UserID is who asked for the change.
UserID id.UserID
}
CheckoutRequest describes one plan change.
type CheckoutResult ¶ added in v1.10.0
type CheckoutResult struct {
// URL is where to send the customer to pay. Empty applies the change now.
URL string
}
CheckoutResult is a CheckoutProvider's answer.
type Config ¶
type Config struct {
// PathPrefix is the HTTP path prefix for billing routes.
// Defaults to "/v1/billing".
PathPrefix string
// DefaultPlanSlug is the plan slug to auto-assign to new tenants.
// If empty, no auto-subscription occurs unless overridden by settings.
DefaultPlanSlug string
// AutoSubscribeOnOrg creates a subscription when an organization is created.
// Only applies when tenant mode is "organization".
AutoSubscribeOnOrg bool
// AutoSubscribeOnUser creates a subscription when a user signs up.
// Only applies when tenant mode is "user".
AutoSubscribeOnUser bool
// TrialDays is the default trial period for new subscriptions.
// 0 means no trial. Can be overridden by settings.
TrialDays int
// AllowSelfService is unused.
//
// Deprecated: self-service is governed by the
// subscription.self_service_upgrade setting (on by default), and who in an
// organization may use it by subscription.billing_roles. This field never
// had an effect and will be removed.
AllowSelfService bool
// DisableRoutes mounts no HTTP routes. Use it when the host serves its
// own billing API on top of the plugin's ledger.
DisableRoutes bool
// Checkout takes payment before a tenant moves onto a paid plan through
// the self-service routes. nil grants the plan directly. A provider that
// also implements PortalProvider backs the billing portal route.
Checkout CheckoutProvider
// DisableAutoSubscribe turns off both the org-create and user-signup
// auto-subscribe hooks, whatever the settings say. Use it when the host
// creates subscriptions itself.
DisableAutoSubscribe bool
}
Config configures the subscription plugin.
type CouponResponse ¶ added in v1.9.0
type CouponResponse struct {
ID string `json:"id"`
Code string `json:"code"`
Name string `json:"name"`
Type string `json:"type"`
Amount string `json:"amount,omitempty"`
Percentage int `json:"percentage,omitempty"`
Currency string `json:"currency"`
MaxRedemptions int `json:"max_redemptions"`
TimesRedeemed int `json:"times_redeemed"`
ValidFrom *string `json:"valid_from,omitempty"`
ValidUntil *string `json:"valid_until,omitempty"`
AppID string `json:"app_id"`
}
type CreateCouponRequest ¶ added in v1.9.0
type CreateCouponRequest struct {
Code string `json:"code"`
Name string `json:"name"`
Type string `json:"type"`
Amount int64 `json:"amount"`
Percentage int `json:"percentage"`
Currency string `json:"currency"`
MaxRedemptions int `json:"max_redemptions"`
ValidFrom *string `json:"valid_from,omitempty"`
ValidUntil *string `json:"valid_until,omitempty"`
AppID string `json:"app_id"`
}
type CreatePlanRequest ¶ added in v1.9.0
type CreatePlanRequest struct {
Name string `json:"name"`
Slug string `json:"slug"`
Description string `json:"description"`
Currency string `json:"currency"`
TrialDays int `json:"trial_days"`
BaseAmount int64 `json:"base_amount"`
Period string `json:"period"`
AppID string `json:"app_id"`
IsAddon bool `json:"is_addon"`
Features []FeatureInput `json:"features,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
}
type CreateSubscriptionRequest ¶ added in v1.9.0
type CurrentSubscriptionRequest ¶ added in v1.10.0
type CurrentSubscriptionRequest struct {
TenantID string `query:"tenant_id,omitempty"`
}
CurrentSubscriptionRequest reads the caller's tenant's subscription.
type CurrentSubscriptionResponse ¶ added in v1.10.0
type CurrentSubscriptionResponse struct {
Subscription *SubscriptionView `json:"subscription"`
CanManage bool `json:"can_manage"`
}
CurrentSubscriptionResponse carries the subscription, null when the tenant has none, and whether the caller may change it.
type DeleteCouponRequest ¶ added in v1.9.0
type DeleteCouponRequest struct {
CouponID string `path:"couponId"`
}
type EntitlementResponse ¶ added in v1.9.0
type EntitlementsResponse ¶ added in v1.10.0
type EntitlementsResponse struct {
Entitlements map[string]EntitlementResponse `json:"entitlements"`
}
EntitlementsResponse maps each feature on the active plan to its check.
type FeatureInput ¶ added in v1.9.0
type GetActiveSubRequest ¶ added in v1.9.0
type GetInvoiceRequest ¶ added in v1.9.0
type GetInvoiceRequest struct {
InvoiceID string `path:"invoiceId"`
}
type GetPlanRequest ¶ added in v1.9.0
type GetPlanRequest struct {
PlanID string `path:"planId"`
}
type InvoiceIDRequest ¶ added in v1.9.0
type InvoiceIDRequest struct {
InvoiceID string `path:"invoiceId"`
}
type InvoiceResponse ¶ added in v1.9.0
type InvoiceResponse struct {
ID string `json:"id"`
TenantID string `json:"tenant_id"`
SubscriptionID string `json:"subscription_id"`
Status string `json:"status"`
Currency string `json:"currency"`
Total string `json:"total"`
PeriodStart string `json:"period_start"`
PeriodEnd string `json:"period_end"`
}
type ListCouponsRequest ¶ added in v1.9.0
type ListCouponsRequest struct {
AppID string `query:"app_id"`
}
type ListCouponsResponse ¶ added in v1.9.0
type ListCouponsResponse struct {
Coupons []CouponResponse `json:"coupons"`
Total int `json:"total"`
}
type ListEntitlementsRequest ¶ added in v1.10.0
type ListEntitlementsRequest struct {
TenantID string `query:"tenant_id,omitempty"`
}
ListEntitlementsRequest reads every entitlement of the caller's tenant.
type ListInvoicesRequest ¶ added in v1.9.0
type ListInvoicesResponse ¶ added in v1.9.0
type ListInvoicesResponse struct {
Invoices []InvoiceResponse `json:"invoices"`
Total int `json:"total"`
}
type ListPlansRequest ¶ added in v1.9.0
type ListPlansRequest struct {
AppID string `query:"app_id"`
// Status filters by plan status. Empty means active. "all", "archived"
// and "draft" are for billing managers.
Status string `query:"status,omitempty"`
// IncludeAddons lists add-on plans as well as base plans.
IncludeAddons bool `query:"include_addons,omitempty"`
}
type ListPlansResponse ¶ added in v1.9.0
type ListPlansResponse struct {
Plans []PlanResponse `json:"plans"`
Total int `json:"total"`
}
type ListSubscriptionsRequest ¶ added in v1.9.0
type ListSubscriptionsResponse ¶ added in v1.9.0
type ListSubscriptionsResponse struct {
Subscriptions []SubscriptionResponse `json:"subscriptions"`
Total int `json:"total"`
}
type MarkInvoicePaidRequest ¶ added in v1.9.0
type PlanFeatureResponse ¶ added in v1.10.0
type PlanFeatureResponse struct {
Key string `json:"key"`
Name string `json:"name"`
Type string `json:"type"`
Limit *int64 `json:"limit"`
Period string `json:"period,omitempty"`
SoftLimit bool `json:"soft_limit"`
}
PlanFeatureResponse is one feature a plan includes. A nil Limit means unlimited.
type PlanIDRequest ¶ added in v1.9.0
type PlanIDRequest struct {
PlanID string `path:"planId"`
}
type PlanResponse ¶ added in v1.9.0
type PlanResponse struct {
ID string `json:"id"`
Name string `json:"name"`
Slug string `json:"slug"`
Description string `json:"description"`
Currency string `json:"currency"`
Status string `json:"status"`
TrialDays int `json:"trial_days"`
BaseAmount string `json:"base_amount,omitempty"`
BillingPeriod string `json:"billing_period,omitempty"`
FeaturesCount int `json:"features_count"`
IsAddon bool `json:"is_addon"`
AppID string `json:"app_id"`
Metadata map[string]string `json:"metadata,omitempty"`
// AmountMinor is the base price in minor units (cents for usd), for
// arithmetic and locale formatting. BaseAmount is the same price
// formatted in major units.
AmountMinor *int64 `json:"amount_minor,omitempty"`
Features []PlanFeatureResponse `json:"features"`
}
type Plugin ¶
type Plugin struct {
// contains filtered or unexported fields
}
Plugin is the subscription management plugin for authsome.
func (*Plugin) CompleteCheckout ¶ added in v1.10.0
func (p *Plugin) CompleteCheckout(ctx context.Context, req CheckoutRequest) (*lsub.Subscription, error)
CompleteCheckout applies a plan change once its payment has landed. Call it from your payment provider's webhook with the CheckoutRequest you got in Checkout (keep what you need from it in the checkout session's metadata).
It is safe to call more than once for the same payment: when the tenant is already on that plan with those seats, it changes nothing and returns the subscription. It moves the tenant's current subscription when there is one, even if a different one was current at checkout, and records the same audit entry and event the self-service routes do.
func (*Plugin) DeclareSettings ¶ added in v1.9.0
DeclareSettings implements plugin.SettingsProvider.
func (*Plugin) OnAfterMemberAdd ¶ added in v1.9.0
OnAfterMemberAdd records seat usage when a member is added to an organization.
func (*Plugin) OnAfterOrgCreate ¶ added in v1.9.0
func (p *Plugin) OnAfterOrgCreate(ctx context.Context, o *organization.Organization) error
OnAfterOrgCreate auto-creates a subscription for new organizations when tenant mode is "organization" and auto-subscribe is enabled.
func (*Plugin) OnAfterOrgDelete ¶ added in v1.9.0
OnAfterOrgDelete cancels every subscription whose tenant is the deleted org so the ledger doesn't keep billing a tenant that no longer exists. Cancellation is best-effort: failures are logged and the hook always returns nil so the org-delete pipeline keeps draining other plugins.
func (*Plugin) OnAfterSignUp ¶ added in v1.9.0
OnAfterSignUp auto-creates a subscription for new users when tenant mode is "user" and auto-subscribe is enabled.
func (*Plugin) RegisterContract ¶ added in v1.9.0
func (p *Plugin) RegisterContract( d *dispatcher.Dispatcher, reg contract.Registry, wreg contract.WardenRegistry, engine plugin.Engine, ) error
func (*Plugin) RegisterRoutes ¶
RegisterRoutes registers billing API routes on a forge.Router.
func (*Plugin) Service ¶ added in v1.9.0
Service returns the subscription service (nil until OnInit completes).
func (*Plugin) SetCheckoutProvider ¶ added in v1.10.0
func (p *Plugin) SetCheckoutProvider(cp CheckoutProvider)
SetCheckoutProvider sets the checkout provider after construction. Call it before the engine starts serving; nil turns checkout off.
func (*Plugin) SetLedger ¶ added in v1.9.0
SetLedger sets the ledger engine directly, bypassing duck-type discovery.
func (*Plugin) SetLedgerStore ¶ added in v1.9.0
func (p *Plugin) SetLedgerStore(st ledgerstore.Store)
SetLedgerStore sets the ledger store directly, bypassing duck-type discovery.
type PortalProvider ¶ added in v1.10.0
type PortalProvider interface {
Portal(ctx context.Context, tenantID, appID, returnURL string) (url string, err error)
}
PortalProvider is optional. A CheckoutProvider that also implements it backs POST /v1/billing/portal: a hosted page where customers update their payment details and see their invoices.
type PortalRequest ¶ added in v1.10.0
type PortalRequest struct {
ReturnURL string `json:"return_url,omitempty"`
TenantID string `json:"tenant_id,omitempty"`
}
PortalRequest opens the billing portal for the caller's tenant.
type PortalResponse ¶ added in v1.10.0
type PortalResponse struct {
URL string `json:"url"`
}
PortalResponse carries the portal URL to send the customer to.
type SeatsView ¶ added in v1.10.0
type SeatsView struct {
FeatureKey string `json:"feature_key"`
Used int64 `json:"used"`
Limit *int64 `json:"limit"`
}
SeatsView reports seat use for a plan with a seat feature. Used counts the organization's members; Limit is the bought quantity, or the plan's limit when none was bought, and nil when unlimited.
type Service ¶ added in v1.9.0
type Service struct {
// contains filtered or unexported fields
}
Service wraps ledger operations with AuthSome context.
func (*Service) ActivatePlan ¶ added in v1.9.0
ActivatePlan transitions a draft plan to active status.
func (*Service) ArchiveCatalogFeature ¶ added in v1.9.0
ArchiveCatalogFeature archives a catalog feature.
func (*Service) ArchivePlan ¶ added in v1.9.0
ArchivePlan archives a plan by ID.
func (*Service) CalculateMRR ¶ added in v1.9.0
CalculateMRR estimates monthly recurring revenue across all active subscriptions.
func (*Service) CancelSubscription ¶ added in v1.9.0
func (s *Service) CancelSubscription(ctx context.Context, subID ledgerid.SubscriptionID, immediately bool) error
CancelSubscription cancels a subscription, now or at the end of its period.
func (*Service) ChangePlan ¶ added in v1.9.0
func (s *Service) ChangePlan(ctx context.Context, subID ledgerid.SubscriptionID, newPlanID ledgerid.PlanID, quantity map[string]int64) (*subscription.Subscription, error)
ChangePlan moves a subscription to another plan through ledger, which refuses a canceled or expired subscription and a plan outside its app. A nil quantity keeps the current seat counts.
func (*Service) CheckEntitlement ¶ added in v1.9.0
func (s *Service) CheckEntitlement(ctx context.Context, featureKey string) (*entitlement.Result, error)
CheckEntitlement checks whether a tenant can use a feature.
func (*Service) CountSubscribers ¶ added in v1.9.0
CountSubscribers counts active subscriptions for a plan.
func (*Service) CreateCatalogFeature ¶ added in v1.9.0
CreateCatalogFeature creates a new catalog feature.
func (*Service) CreateCoupon ¶ added in v1.9.0
CreateCoupon creates a new coupon.
func (*Service) CreatePlan ¶ added in v1.9.0
CreatePlan creates a new billing plan.
func (*Service) CurrentSubscription ¶ added in v1.10.0
func (s *Service) CurrentSubscription(ctx context.Context, tenantID, appID string) (*subscription.Subscription, error)
CurrentSubscription returns the tenant's newest subscription that hasn't ended (active, trialing, past_due or paused), or nil when it has none.
func (*Service) DeleteCatalogFeature ¶ added in v1.9.0
DeleteCatalogFeature deletes a catalog feature.
func (*Service) DeleteCoupon ¶ added in v1.9.0
DeleteCoupon deletes a coupon.
func (*Service) GenerateInvoice ¶ added in v1.9.0
func (s *Service) GenerateInvoice(ctx context.Context, subID ledgerid.SubscriptionID) (*invoice.Invoice, error)
GenerateInvoice generates an invoice for the current billing period.
func (*Service) GetActiveSubscription ¶ added in v1.9.0
func (s *Service) GetActiveSubscription(ctx context.Context, tenantID, appID string) (*subscription.Subscription, error)
GetActiveSubscription retrieves the active subscription for a tenant.
func (*Service) GetCatalogFeature ¶ added in v1.9.0
func (s *Service) GetCatalogFeature(ctx context.Context, featureID ledgerid.FeatureID) (*feature.Feature, error)
GetCatalogFeature retrieves a catalog feature by ID.
func (*Service) GetCatalogFeatureByKey ¶ added in v1.9.0
func (s *Service) GetCatalogFeatureByKey(ctx context.Context, key, appID string) (*feature.Feature, error)
GetCatalogFeatureByKey retrieves a catalog feature by key.
func (*Service) GetCouponByID ¶ added in v1.9.1
func (s *Service) GetCouponByID(ctx context.Context, couponID ledgerid.CouponID) (*coupon.Coupon, error)
GetCouponByID retrieves a coupon by ID.
func (*Service) GetInvoice ¶ added in v1.9.0
func (s *Service) GetInvoice(ctx context.Context, invID ledgerid.InvoiceID) (*invoice.Invoice, error)
GetInvoice retrieves an invoice by ID.
func (*Service) GetPlanBySlug ¶ added in v1.10.0
GetPlanBySlug retrieves a plan by its slug within an app.
func (*Service) GetSubscription ¶ added in v1.9.0
func (s *Service) GetSubscription(ctx context.Context, subID ledgerid.SubscriptionID) (*subscription.Subscription, error)
GetSubscription retrieves a subscription by ID.
func (*Service) GetUsageSummary ¶ added in v1.9.0
func (s *Service) GetUsageSummary(ctx context.Context, tenantID, appID string) ([]UsageSummary, error)
GetUsageSummary returns usage breakdown for the active subscription.
func (*Service) KeepSubscription ¶ added in v1.10.0
func (s *Service) KeepSubscription(ctx context.Context, subID ledgerid.SubscriptionID) (*subscription.Subscription, error)
KeepSubscription takes back a cancellation scheduled for the end of the period, so the subscription renews as usual. A subscription that has already ended can't be kept.
func (*Service) ListAllInvoices ¶ added in v1.9.0
ListAllInvoices lists all invoices for an app.
func (*Service) ListCatalogFeatures ¶ added in v1.9.0
func (s *Service) ListCatalogFeatures(ctx context.Context, appID string) ([]*feature.Feature, error)
ListCatalogFeatures lists all catalog features for an app.
func (*Service) ListCoupons ¶ added in v1.9.0
ListCoupons lists all coupons for an app.
func (*Service) ListInvoices ¶ added in v1.9.0
func (s *Service) ListInvoices(ctx context.Context, tenantID, appID string) ([]*invoice.Invoice, error)
ListInvoices lists invoices for a tenant.
func (*Service) ListPlansWithOpts ¶ added in v1.10.0
func (s *Service) ListPlansWithOpts(ctx context.Context, appID string, opts plan.ListOpts) ([]*plan.Plan, error)
ListPlansWithOpts returns the app's plans filtered by opts.
func (*Service) ListSubscriptions ¶ added in v1.9.0
func (s *Service) ListSubscriptions(ctx context.Context, tenantID, appID string, opts subscription.ListOpts) ([]*subscription.Subscription, error)
ListSubscriptions lists subscriptions for a tenant.
func (*Service) MarkInvoicePaid ¶ added in v1.9.0
func (s *Service) MarkInvoicePaid(ctx context.Context, invID ledgerid.InvoiceID, paymentRef string) error
MarkInvoicePaid marks an invoice as paid.
func (*Service) MarkInvoiceVoided ¶ added in v1.9.0
func (s *Service) MarkInvoiceVoided(ctx context.Context, invID ledgerid.InvoiceID, reason string) error
MarkInvoiceVoided voids an invoice.
func (*Service) PauseSubscription ¶ added in v1.9.0
func (s *Service) PauseSubscription(ctx context.Context, subID ledgerid.SubscriptionID) (*subscription.Subscription, error)
PauseSubscription pauses an active or trialing subscription.
func (*Service) ResumeSubscription ¶ added in v1.9.0
func (s *Service) ResumeSubscription(ctx context.Context, subID ledgerid.SubscriptionID) (*subscription.Subscription, error)
ResumeSubscription resumes a paused subscription. Ledger stretches the period and any running trial by the length of the pause, and leaves a subscription that ended while paused alone.
func (*Service) SetLedgerStore ¶ added in v1.9.0
func (s *Service) SetLedgerStore(st ledgerstore.Store)
SetLedgerStore sets the ledger store directly, bypassing duck-type discovery.
func (*Service) Subscribe ¶ added in v1.9.0
func (s *Service) Subscribe(ctx context.Context, tenantID string, planID ledgerid.PlanID, appID string, quantity map[string]int64) (*subscription.Subscription, error)
Subscribe creates a new subscription for a tenant on a plan. Ledger picks the trial from the plan's trial_days and the first period from the plan's billing period. quantity sets seat counts for the plan's seat features and may be nil.
func (*Service) UpdateCatalogFeature ¶ added in v1.9.0
UpdateCatalogFeature updates a catalog feature.
type SubIDRequest ¶ added in v1.9.0
type SubIDRequest struct {
SubID string `path:"subId"`
}
type SubscribeRequest ¶ added in v1.10.0
type SubscribeRequest struct {
Plan string `json:"plan"`
Seats *int64 `json:"seats,omitempty"`
ReturnURL string `json:"return_url,omitempty"`
CancelURL string `json:"cancel_url,omitempty"`
TenantID string `json:"tenant_id,omitempty"`
}
SubscribeRequest starts a subscription. Plan is a plan slug or ID.
type SubscriptionMutationResponse ¶ added in v1.10.0
type SubscriptionMutationResponse struct {
Subscription *SubscriptionView `json:"subscription,omitempty"`
CheckoutURL string `json:"checkout_url,omitempty"`
}
SubscriptionMutationResponse holds the updated subscription, or a checkout URL when a checkout provider takes payment first. Exactly one is set.
type SubscriptionResponse ¶ added in v1.10.0
type SubscriptionResponse struct {
ID string `json:"id"`
TenantID string `json:"tenant_id"`
PlanID string `json:"plan_id"`
Status string `json:"status"`
CurrentPeriodStart string `json:"current_period_start"`
CurrentPeriodEnd string `json:"current_period_end"`
TrialStart *string `json:"trial_start,omitempty"`
TrialEnd *string `json:"trial_end,omitempty"`
CanceledAt *string `json:"canceled_at,omitempty"`
AppID string `json:"app_id"`
// CancelAt is when a cancellation scheduled for the period end takes
// effect. CanceledAt stays empty until it does.
CancelAt *string `json:"cancel_at,omitempty"`
PausedAt *string `json:"paused_at,omitempty"`
}
type SubscriptionView ¶ added in v1.10.0
type SubscriptionView struct {
ID string `json:"id"`
TenantID string `json:"tenant_id"`
Status string `json:"status"`
Plan PlanResponse `json:"plan"`
CurrentPeriodStart string `json:"current_period_start"`
CurrentPeriodEnd string `json:"current_period_end"`
TrialStart *string `json:"trial_start"`
TrialEnd *string `json:"trial_end"`
// CancelAt is when a cancellation scheduled for the period end takes
// effect; the subscription stays usable until then.
CancelAt *string `json:"cancel_at"`
CanceledAt *string `json:"canceled_at"`
PausedAt *string `json:"paused_at"`
Seats *SeatsView `json:"seats,omitempty"`
AppID string `json:"app_id"`
}
SubscriptionView is the tenant-facing shape of a subscription: everything a plan card needs in one payload, with the plan embedded and every time in RFC 3339 UTC.
type TenantRequest ¶ added in v1.10.0
type TenantRequest struct {
TenantID string `json:"tenant_id,omitempty"`
}
TenantRequest names nothing but an optional tenant override.
type UpdateSubscriptionRequest ¶ added in v1.10.0
type UpdateSubscriptionRequest struct {
Plan string `json:"plan,omitempty"`
Seats *int64 `json:"seats,omitempty"`
ReturnURL string `json:"return_url,omitempty"`
CancelURL string `json:"cancel_url,omitempty"`
TenantID string `json:"tenant_id,omitempty"`
}
UpdateSubscriptionRequest changes the plan, the seat count, or both.
type UsageItemResponse ¶ added in v1.9.0
type UsageSummary ¶ added in v1.9.0
type UsageSummary struct {
FeatureKey string
FeatureName string
FeatureType string
Used int64
Limit int64
Remaining int64
Period string
}
UsageSummary holds feature usage data for display.
type UsageSummaryRequest ¶ added in v1.9.0
type UsageSummaryResponse ¶ added in v1.9.0
type UsageSummaryResponse struct {
Usage []UsageItemResponse `json:"usage"`
}