forked from Nixius/authelia
1
0
Fork 0
ATLAS/docker/ss-atlas/internal/stripe/client.go

122 lines
4.1 KiB
Go

package stripe
import (
"log"
"time"
"git.nixc.us/a250/ss-atlas/internal/config"
stripego "github.com/stripe/stripe-go/v84"
portalsession "github.com/stripe/stripe-go/v84/billingportal/session"
checkoutsession "github.com/stripe/stripe-go/v84/checkout/session"
"github.com/stripe/stripe-go/v84/subscription"
)
type SubscriptionStatus struct {
Label string // "Active", "Cancels soon", etc.
Badge string // "badge-active", "badge-inactive", etc.
CancelAt string // empty or formatted date
}
type Client struct {
cfg *config.Config
}
func New(cfg *config.Config) *Client {
stripego.Key = cfg.StripeSecretKey
return &Client{cfg: cfg}
}
func (c *Client) CreateCheckoutSession(email string) (*stripego.CheckoutSession, error) {
params := &stripego.CheckoutSessionParams{
Mode: stripego.String(string(stripego.CheckoutSessionModeSubscription)),
LineItems: []*stripego.CheckoutSessionLineItemParams{
{
Price: stripego.String(c.cfg.StripePriceID),
Quantity: stripego.Int64(1),
},
},
CustomerEmail: stripego.String(email),
SuccessURL: stripego.String(c.cfg.AppURL + "/success?session_id={CHECKOUT_SESSION_ID}"),
CancelURL: stripego.String(c.cfg.AppURL + "/"),
}
return checkoutsession.New(params)
}
// CreateCheckoutForCustomer creates a new subscription checkout for an existing
// Stripe customer (e.g. resubscribe after expiry). The new sub is linked to the
// same customer record so payment methods and history are preserved.
func (c *Client) CreateCheckoutForCustomer(customerID string) (*stripego.CheckoutSession, error) {
params := &stripego.CheckoutSessionParams{
Mode: stripego.String(string(stripego.CheckoutSessionModeSubscription)),
LineItems: []*stripego.CheckoutSessionLineItemParams{
{
Price: stripego.String(c.cfg.StripePriceID),
Quantity: stripego.Int64(1),
},
},
Customer: stripego.String(customerID),
SuccessURL: stripego.String(c.cfg.AppURL + "/success?session_id={CHECKOUT_SESSION_ID}"),
CancelURL: stripego.String(c.cfg.AppURL + "/dashboard"),
}
return checkoutsession.New(params)
}
func (c *Client) CreatePortalSession(customerID string) (*stripego.BillingPortalSession, error) {
params := &stripego.BillingPortalSessionParams{
Customer: stripego.String(customerID),
ReturnURL: stripego.String(c.cfg.AppURL + "/dashboard"),
}
return portalsession.New(params)
}
func (c *Client) GetCheckoutSession(sessionID string) (*stripego.CheckoutSession, error) {
params := &stripego.CheckoutSessionParams{}
params.AddExpand("customer")
params.AddExpand("subscription")
return checkoutsession.Get(sessionID, params)
}
func (c *Client) GetSubscription(subID string) (*stripego.Subscription, error) {
return subscription.Get(subID, nil)
}
func (c *Client) GetCustomerSubscriptionStatus(customerID string) *SubscriptionStatus {
if customerID == "" {
return &SubscriptionStatus{Label: "Active", Badge: "badge-active"}
}
params := &stripego.SubscriptionListParams{
Customer: stripego.String(customerID),
Status: stripego.String(string(stripego.SubscriptionStatusActive)),
}
iter := subscription.List(params)
if iter.Next() {
sub := iter.Subscription()
log.Printf("stripe: customer=%s sub=%s cancel_at_period_end=%v cancel_at=%d",
customerID, sub.ID, sub.CancelAtPeriodEnd, sub.CancelAt)
if sub.CancelAtPeriodEnd || sub.CancelAt > 0 {
// Prefer explicit cancel_at; fall back to current_period_end from the first item
endTs := sub.CancelAt
if endTs == 0 && sub.Items != nil && len(sub.Items.Data) > 0 {
endTs = sub.Items.Data[0].CurrentPeriodEnd
}
var cancelAt string
if endTs > 0 {
cancelAt = time.Unix(endTs, 0).Format("Jan 2, 2006")
}
return &SubscriptionStatus{
Label: "Expiring",
Badge: "badge-inactive",
CancelAt: cancelAt,
}
}
return &SubscriptionStatus{Label: "Active", Badge: "badge-active"}
}
log.Printf("stripe: no active subscription found for customer=%s", customerID)
// No active subscription; user was a customer so subscription has expired
return &SubscriptionStatus{Label: "Expired", Badge: "badge-inactive"}
}
func (c *Client) WebhookSecret() string {
return c.cfg.StripeWebhookSecret
}