billing

package
v0.1.0-alpha.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 8, 2026 License: AGPL-3.0 Imports: 4 Imported by: 0

Documentation

Overview

Package billing holds pricing rules and billing settings (docs/billing.md). Money is always an integer in the currency's smallest unit (IDR has none: 1 = Rp1).

Index

Constants

This section is empty.

Variables

View Source
var CycleMonths = map[string]int{"monthly": 1, "quarterly": 3, "semiannually": 6, "yearly": 12, "biennially": 24, "triennially": 36}

CycleMonths is the length of a cycle.

View Source
var Cycles = []string{"monthly", "quarterly", "yearly"}

Cycles a customer can pay for. Cycles are offered in the store; CycleMonths also knows the longer cycles imported subscriptions may use.

View Source
var PayPalCurrencies = map[string]bool{
	"USD": true, "EUR": true, "GBP": true, "AUD": true, "CAD": true, "SGD": true, "JPY": true,
	"MYR": true, "PHP": true, "THB": true, "HKD": true, "NZD": true, "CHF": true,
}

PayPalCurrencies are the currencies PayPal accepts (IDR is not one of them).

View Source
var ZeroDecimal = map[string]bool{"IDR": true, "JPY": true, "KRW": true, "VND": true}

ZeroDecimal currencies have no minor unit in Ammonode's amounts (amount 1 = one whole unit).

Functions

func Format

func Format(amount int64, currency string) string

Format renders an amount for people, e.g. "Rp30.000" or "$12.50".

func NextDue

func NextDue(t time.Time, cycle string) time.Time

NextDue adds one cycle to t (calendar months, so the 31st becomes the last day of short months).

func PrevDue

func PrevDue(next time.Time, cycle string) time.Time

PrevDue is the start of the period that ends at next (the inverse of NextDue for calendar months; the day is clamped to the shorter month).

func Prorate

func Prorate(oldAmount, newAmount int64, start, end, now time.Time) int64

Prorate is the price difference between two cycle prices for the rest of the period [start, end) from now: positive means the customer pays, negative means a credit.

Types

type Coupon

type Coupon struct {
	Kind      string // percent | fixed
	Value     int64  // 1-100 for percent, an amount for fixed
	Recurring bool   // also applies to every renewal
}

Coupon is a discount code.

func (Coupon) Off

func (c Coupon) Off(amount int64) int64

Off returns the coupon's discount on amount (never more than amount).

type InvoiceDetails

type InvoiceDetails struct {
	CompanyName string `json:"company_name"`
	Address     string `json:"address"` // multi-line
	TaxID       string `json:"tax_id"`
	Footer      string `json:"footer"`
}

InvoiceDetails is the seller block and footer printed on invoices.

type Option

type Option struct {
	Resource     string
	Step         int
	MaxSteps     int
	PriceMonthly int64
	Steps        int
}

Option is a configurable extra; Steps is how many the customer picked.

type PayPalSettings

type PayPalSettings struct {
	Enabled   bool   `json:"enabled"`
	ClientID  string `json:"client_id"`
	Secret    string `json:"secret"`
	Sandbox   bool   `json:"sandbox"`
	WebhookID string `json:"webhook_id"`
}

PayPalSettings configures PayPal Checkout (Orders v2).

type Plan

type Plan struct {
	MemoryMB, CPUPercent, DiskMB int
	PriceMonthly, SetupFee       int64
}

Plan and Option are the priced parts of a product.

type Quote

type Quote struct {
	Recurring  int64 `json:"recurring"` // per cycle (after a recurring coupon)
	SetupFee   int64 `json:"setup_fee"`
	FirstTotal int64 `json:"first_total"` // first invoice, after the coupon
	Discount   int64 `json:"discount"`    // coupon discount on the first invoice
	MemoryMB   int   `json:"memory_mb"`
	CPUPercent int   `json:"cpu_percent"`
	DiskMB     int   `json:"disk_mb"`
}

Quote is the price and resources of a configuration for a cycle.

func ApplyCoupon

func ApplyCoupon(q Quote, c Coupon) Quote

ApplyCoupon discounts the cycle price (not the setup fee) on the first invoice, and on renewals too when the coupon is recurring.

func Price

func Price(p Plan, opts []Option, cycle string, s Settings) (Quote, error)

Price computes a quote: (plan + options) per month × months, minus the cycle discount (rounded half up), plus the setup fee on the first invoice.

type Settings

type Settings struct {
	Currency           string         `json:"currency"`
	Discounts          map[string]int `json:"discounts"` // cycle -> percent off
	RenewDaysBefore    int            `json:"renew_days_before"`
	SuspendAfterDays   int            `json:"suspend_after_days"`
	TerminateAfterDays int            `json:"terminate_after_days"`
	AllowRegistration  bool           `json:"allow_registration"`
	Stripe             StripeSettings `json:"stripe"`
	PayPal             PayPalSettings `json:"paypal"`
	Invoice            InvoiceDetails `json:"invoice"`
}

Settings are the panel's billing settings (stored as JSON under the "billing" key).

func DefaultSettings

func DefaultSettings() Settings

DefaultSettings are used until an admin saves their own.

func (*Settings) Validate

func (s *Settings) Validate() error

Validate normalises and checks settings.

type StripeSettings

type StripeSettings struct {
	Enabled       bool   `json:"enabled"`
	SecretKey     string `json:"secret_key"`
	WebhookSecret string `json:"webhook_secret"`
}

StripeSettings configures Stripe Checkout.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL