A container registry that uses the AT Protocol for manifest storage and S3 for blob storage. atcr.io
docker container atproto go
at main 83 lines 3.8 kB view raw
1package billing 2 3// Config holds appview billing/Stripe configuration. 4// Parsed from the appview config YAML's billing section. 5type Config struct { 6 // Stripe secret key (sk_test_... or sk_live_...). 7 // Can also be set via STRIPE_SECRET_KEY env var (takes precedence over config). 8 // Billing is enabled automatically when this key is set (requires -tags billing build). 9 StripeSecretKey string `yaml:"stripe_secret_key" comment:"Stripe secret key. Can also be set via STRIPE_SECRET_KEY env var (takes precedence). Billing is enabled automatically when set."` 10 11 // Stripe webhook signing secret (whsec_...). 12 // Can also be set via STRIPE_WEBHOOK_SECRET env var (takes precedence over config). 13 WebhookSecret string `yaml:"webhook_secret" comment:"Stripe webhook signing secret. Can also be set via STRIPE_WEBHOOK_SECRET env var (takes precedence)."` 14 15 // Currency code for Stripe checkout (e.g. "usd"). 16 Currency string `yaml:"currency" comment:"ISO 4217 currency code (e.g. \"usd\")."` 17 18 // URL to redirect after successful checkout. {base_url} is replaced at runtime. 19 SuccessURL string `yaml:"success_url" comment:"Redirect URL after successful checkout. Use {base_url} placeholder."` 20 21 // URL to redirect after cancelled checkout. {base_url} is replaced at runtime. 22 CancelURL string `yaml:"cancel_url" comment:"Redirect URL after cancelled checkout. Use {base_url} placeholder."` 23 24 // Subscription tiers with Stripe price IDs. 25 Tiers []BillingTierConfig `yaml:"tiers" comment:"Subscription tiers ordered by rank (lowest to highest)."` 26 27 // Whether hold owners get a supporter badge on their profile. 28 OwnerBadge bool `yaml:"owner_badge" comment:"Show supporter badge on hold owner profiles."` 29} 30 31// BillingTierConfig represents a single tier with optional Stripe pricing. 32type BillingTierConfig struct { 33 // Tier name (matches hold quota tier names for rank mapping). 34 Name string `yaml:"name" comment:"Tier name. Position in list determines rank (0-based)."` 35 36 // Short description shown on the plan card. 37 Description string `yaml:"description,omitempty" comment:"Short description shown on the plan card."` 38 39 // List of features included in this tier (rendered as bullet points). 40 Features []string `yaml:"features,omitempty" comment:"List of features included in this tier."` 41 42 // Stripe price ID for monthly billing. Empty = free tier. 43 StripePriceMonthly string `yaml:"stripe_price_monthly,omitempty" comment:"Stripe price ID for monthly billing. Empty = free tier."` 44 45 // Stripe price ID for yearly billing. 46 StripePriceYearly string `yaml:"stripe_price_yearly,omitempty" comment:"Stripe price ID for yearly billing."` 47 48 // Maximum number of webhooks for this tier (-1 = unlimited). 49 MaxWebhooks int `yaml:"max_webhooks" comment:"Maximum webhooks for this tier (-1 = unlimited)."` 50 51 // Whether all webhook trigger types are available (not just first-scan). 52 WebhookAllTriggers bool `yaml:"webhook_all_triggers" comment:"Allow all webhook trigger types (not just first-scan)."` 53 54 // Whether this tier earns a supporter badge on user profiles. 55 SupporterBadge bool `yaml:"supporter_badge" comment:"Show supporter badge on user profiles for subscribers at this tier."` 56} 57 58// GetTierByPriceID finds the tier that contains the given Stripe price ID. 59// Returns the tier name and rank, or empty string and -1 if not found. 60func (c *Config) GetTierByPriceID(priceID string) (string, int) { 61 if c == nil || priceID == "" { 62 return "", -1 63 } 64 for i, tier := range c.Tiers { 65 if tier.StripePriceMonthly == priceID || tier.StripePriceYearly == priceID { 66 return tier.Name, i 67 } 68 } 69 return "", -1 70} 71 72// TierRank returns the 0-based rank of a tier by name, or -1 if not found. 73func (c *Config) TierRank(name string) int { 74 if c == nil { 75 return -1 76 } 77 for i, tier := range c.Tiers { 78 if tier.Name == name { 79 return i 80 } 81 } 82 return -1 83}