Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion billing/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package billing
import (
"encoding/json"
"fmt"
"log/slog"
"os"
"strconv"
"time"
Expand All @@ -13,6 +14,7 @@ type Billing struct {
VariantIDIndividual int
VariantIDPro int
VariantIDPremium int
Logger *slog.Logger
}
type CheckoutPayload struct {
Data CheckoutData `json:"data"`
Expand Down Expand Up @@ -100,7 +102,7 @@ type BillingRepo interface {
MarkWebhookProcessed(id string, event string) error
}

func NewBilling() (*Billing, error) {
func NewBilling(logger *slog.Logger) (*Billing, error) {
individualID, err := strconv.Atoi(os.Getenv("LEMON_VARIANT_ID_INDIVIDUAL"))
if err != nil {
return nil, fmt.Errorf("invalid INDIVIDUAL ID: %w", err)
Expand All @@ -118,5 +120,6 @@ func NewBilling() (*Billing, error) {
VariantIDIndividual: individualID,
VariantIDPro: proID,
VariantIDPremium: premiumID,
Logger: logger,
}, nil
}
2 changes: 1 addition & 1 deletion billing/repository_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ func NewMockRepo() *MockRepo {

func (m *MockRepo) LogCreditTransaction(tx CreditTransaction) error {
if m.FailLogCreditTransaction {
return errors.New("Mocked LogCreditTransaction failure")
return errors.New("mocked LogCreditTransaction failure")
}
return nil
}
Expand Down
73 changes: 36 additions & 37 deletions billing/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
"strconv"
Expand Down Expand Up @@ -45,13 +44,13 @@ func (b *Billing) RequestCheckoutSession(userEmail string, variantID int) (strin

body, err := json.Marshal(payload)
if err != nil {
log.Printf("json.Marshal failed: %v", err)
b.Logger.Error("json.Marshal failed", "error", err)
return "", err
}

req, err := http.NewRequest("POST", "https://api.lemonsqueezy.com/v1/checkouts", bytes.NewBuffer(body))
if err != nil {
log.Printf("http.NewRequest failed: %v", err)
b.Logger.Error("http.NewRequest failed", "error", err)
return "", err
}

Expand All @@ -64,20 +63,20 @@ func (b *Billing) RequestCheckoutSession(userEmail string, variantID int) (strin
}
res, err := client.Do(req)
if err != nil {
log.Printf("client.Do failed: %v", err)
b.Logger.Error("client.Do failed", "error", err)
return "", err
}
defer res.Body.Close()

if res.StatusCode < 200 || res.StatusCode >= 300 {
bodyBytes, _ := io.ReadAll(res.Body)
log.Printf("LemonSqueezy returned error: %s", string(bodyBytes))
return "", fmt.Errorf("LemonSqueezy API error: %s", res.Status)
b.Logger.Error("LemonSqueezy returned error", "error", string(bodyBytes))
return "", fmt.Errorf("lemonSqueezy API error: %s", res.Status)
}

var result CheckoutResponse
if err := json.NewDecoder(res.Body).Decode(&result); err != nil {
log.Printf("NewDecoder failed: %v", err)
b.Logger.Error("NewDecoder failed", "error", err)
return "", err
}

Expand Down Expand Up @@ -190,7 +189,7 @@ func (b *Billing) VerifyBillingSignature(signature string, body []byte, secret s
func (b *Billing) ApplyCredits(userRepo user.UserRepo, billingRepo BillingRepo, email string, variantID int) error {
user, err := userRepo.GetUserByEmail(email)
if err != nil {
log.Printf("repo.GetUserByEmail failed: %v", err)
b.Logger.Error("repo.GetUserByEmail failed", "error", err)
return err
}

Expand All @@ -213,12 +212,12 @@ func (b *Billing) ApplyCredits(userRepo user.UserRepo, billingRepo BillingRepo,
creditType = "subscription"
reason = "Premium subscription monthly credit grant"
default:
log.Printf("ERROR: unknown variantID: %d", variantID)
b.Logger.Error("ERROR: unknown variantID", "variantID", variantID)
return fmt.Errorf("unknown variant ID: %d", variantID)
}

if err := userRepo.AddCredits(user.ID, credits, creditType); err != nil {
log.Printf("repo.AddCredits failed: %v", err)
b.Logger.Error("repo.AddCredits failed", "error", err)
return err
}

Expand All @@ -229,7 +228,7 @@ func (b *Billing) ApplyCredits(userRepo user.UserRepo, billingRepo BillingRepo,
Reason: reason,
}
if err := billingRepo.LogCreditTransaction(tx); err != nil {
log.Printf("Warning: credit granted but failed to log transaction: %v", err)
b.Logger.Error("Warning: credit granted but failed to log transaction", "error", err)
return err
}

Expand All @@ -239,7 +238,7 @@ func (b *Billing) ApplyCredits(userRepo user.UserRepo, billingRepo BillingRepo,
func (b *Billing) DeductCredits(userRepo user.UserRepo, billingRepo BillingRepo, orderAttrs OrderAttributes) error {
user, err := userRepo.GetUserByEmail(orderAttrs.UserEmail)
if err != nil {
log.Printf("repo.GetUserByEmail failed: %v", err)
b.Logger.Error("repo.GetUserByEmail failed", "error", err)
return err
}

Expand All @@ -264,12 +263,12 @@ func (b *Billing) DeductCredits(userRepo user.UserRepo, billingRepo BillingRepo,
creditType = "subscription"
reason = "Premium subscription monthly credit refund"
default:
log.Printf("ERROR: unknown variantID: %d", variantID)
b.Logger.Error("unknown variantID", "variantID", variantID)
return fmt.Errorf("unknown variant ID: %d", variantID)
}

if err := userRepo.AddCredits(user.ID, -credits, creditType); err != nil {
log.Printf("repo.DeductCredits failed: %v", err)
b.Logger.Error("repo.DeductCredits failed", "error", err)
return err
}

Expand All @@ -280,7 +279,7 @@ func (b *Billing) DeductCredits(userRepo user.UserRepo, billingRepo BillingRepo,
Reason: reason,
}
if err := billingRepo.LogCreditTransaction(tx); err != nil {
log.Printf("Warning: refund deduction succeeded but failed to log transaction: %v", err)
b.Logger.Warn("Refund deduction succeeded but failed to log transaction", "error", err)
return err
}

Expand All @@ -290,7 +289,7 @@ func (b *Billing) DeductCredits(userRepo user.UserRepo, billingRepo BillingRepo,
func (b *Billing) CreateSubscription(userRepo user.UserRepo, subCreatedAttrs SubscriptionAttributes, subscriptionID string) error {
user, err := userRepo.GetUserByEmail(subCreatedAttrs.UserEmail)
if err != nil {
log.Printf("repo.GetUserByEmail failed: %v", err)
b.Logger.Error("repo.GetUserByEmail failed", "error", err)
return err
}

Expand All @@ -301,7 +300,7 @@ func (b *Billing) CreateSubscription(userRepo user.UserRepo, subCreatedAttrs Sub
case b.VariantIDPremium:
tier = "premium"
default:
log.Printf("ERROR: unknown variantID: %d", subCreatedAttrs.VariantID)
b.Logger.Error("unknown variantID", "variantID", subCreatedAttrs.VariantID)
return fmt.Errorf("unknown variant ID: %d", subCreatedAttrs.VariantID)
}

Expand All @@ -314,7 +313,7 @@ func (b *Billing) CreateSubscription(userRepo user.UserRepo, subCreatedAttrs Sub
subCreatedAttrs.EndsAt,
)
if err != nil {
log.Printf("CreateSubscriptionData failed: %v", err)
b.Logger.Error("CreateSubscriptionData failed", "error", err)
return err
}

Expand All @@ -324,7 +323,7 @@ func (b *Billing) CreateSubscription(userRepo user.UserRepo, subCreatedAttrs Sub
func (b *Billing) CancelSubscription(userRepo user.UserRepo, email string) error {
user, err := userRepo.GetUserByEmail(email)
if err != nil {
log.Printf("repo.GetUserByEmail failed: %v", err)
b.Logger.Error("repo.GetUserByEmail failed", "error", err)
return err
}

Expand All @@ -333,7 +332,7 @@ func (b *Billing) CancelSubscription(userRepo user.UserRepo, email string) error
"cancelled",
)
if err != nil {
log.Printf("CancelSubscriptionData failed: %v", err)
b.Logger.Error("CancelSubscriptionData failed", "error", err)
return err
}

Expand All @@ -343,7 +342,7 @@ func (b *Billing) CancelSubscription(userRepo user.UserRepo, email string) error
func (b *Billing) ResumeSubscription(userRepo user.UserRepo, email string) error {
user, err := userRepo.GetUserByEmail(email)
if err != nil {
log.Printf("repo.GetUserByEmail failed: %v", err)
b.Logger.Error("repo.GetUserByEmail failed", "error", err)
return err
}

Expand All @@ -352,7 +351,7 @@ func (b *Billing) ResumeSubscription(userRepo user.UserRepo, email string) error
"active",
)
if err != nil {
log.Printf("CancelSubscriptionData failed: %v", err)
b.Logger.Error("CancelSubscriptionData failed", "error", err)
return err
}

Expand All @@ -362,7 +361,7 @@ func (b *Billing) ResumeSubscription(userRepo user.UserRepo, email string) error
func (b *Billing) ExpireSubscription(userRepo user.UserRepo, billingRepo BillingRepo, email string) error {
user, err := userRepo.GetUserByEmail(email)
if err != nil {
log.Printf("repo.GetUserByEmail failed: %v", err)
b.Logger.Error("repo.GetUserByEmail failed", "error", err)
return err
}

Expand All @@ -371,14 +370,14 @@ func (b *Billing) ExpireSubscription(userRepo user.UserRepo, billingRepo Billing
"expired",
)
if err != nil {
log.Printf("CancelSubscriptionData failed: %v", err)
b.Logger.Error("CancelSubscriptionData failed", "error", err)
return err
}

if user.SubscriptionCredits > 0 {
err = userRepo.AddCredits(user.ID, -user.SubscriptionCredits, "subscription")
if err != nil {
log.Printf("repo.AddCredits failed: %v", err)
b.Logger.Error("repo.AddCredits failed", "error", err)
return err
}

Expand All @@ -389,7 +388,7 @@ func (b *Billing) ExpireSubscription(userRepo user.UserRepo, billingRepo Billing
Reason: "Zeroed out credits on subscription expiration",
}
if err := billingRepo.LogCreditTransaction(tx); err != nil {
log.Printf("Warning: zero-out succeeded but failed to log transaction: %v", err)
b.Logger.Warn("Zero-out succeeded but failed to log transaction", "error", err)
}
}

Expand All @@ -399,7 +398,7 @@ func (b *Billing) ExpireSubscription(userRepo user.UserRepo, billingRepo Billing
func (b *Billing) RenewSubscription(userRepo user.UserRepo, billingRepo BillingRepo, subRenewAttrs SubscriptionRenewAttributes) error {
user, err := userRepo.GetUserByEmail(subRenewAttrs.UserEmail)
if err != nil {
log.Printf("repo.GetUserByEmail failed: %v", err)
b.Logger.Error("repo.GetUserByEmail failed", "error", err)
return err
}

Expand All @@ -419,12 +418,12 @@ func (b *Billing) RenewSubscription(userRepo user.UserRepo, billingRepo BillingR
credits = 20
reason = "Premium subscription monthly credit"
default:
log.Printf("ERROR: unknown user.SubscriptionTier: %s", user.SubscriptionTier)
b.Logger.Error("unknown user.SubscriptionTier", "subscriptionTier", user.SubscriptionTier)
return fmt.Errorf("unknown user.SubscriptionTier: %s", user.SubscriptionTier)
}

if err := userRepo.AddCredits(user.ID, credits, "subscription"); err != nil {
log.Printf("repo.AddCredits failed: %v", err)
b.Logger.Error("repo.AddCredits failed", "error", err)
return err
}

Expand All @@ -435,7 +434,7 @@ func (b *Billing) RenewSubscription(userRepo user.UserRepo, billingRepo BillingR
Reason: reason,
}
if err := billingRepo.LogCreditTransaction(tx); err != nil {
log.Printf("Warning: credit granted but failed to log transaction: %v", err)
b.Logger.Warn("credit granted but failed to log transaction", "error", err)
return err
}

Expand All @@ -445,7 +444,7 @@ func (b *Billing) RenewSubscription(userRepo user.UserRepo, billingRepo BillingR
func (b *Billing) ChangeSubscription(userRepo user.UserRepo, billingRepo BillingRepo, subChangedAttrs SubscriptionAttributes) error {
user, err := userRepo.GetUserByEmail(subChangedAttrs.UserEmail)
if err != nil {
log.Printf("repo.GetUserByEmail failed: %v", err)
b.Logger.Error("repo.GetUserByEmail failed", "error", err)
return err
}

Expand All @@ -468,12 +467,12 @@ func (b *Billing) ChangeSubscription(userRepo user.UserRepo, billingRepo Billing
credits = 10
reason = "Pro upgraded to Premium subscription monthly credit"
default:
log.Printf("ERROR: unknown user.SubscriptionTier: %s", user.SubscriptionTier)
b.Logger.Error("unknown user.SubscriptionTier", "subscriptionTier", user.SubscriptionTier)
return fmt.Errorf("unknown user.SubscriptionTier: %s", user.SubscriptionTier)
}

if err := userRepo.AddCredits(user.ID, credits, "subscription"); err != nil {
log.Printf("repo.AddCredits failed: %v", err)
b.Logger.Error("repo.AddCredits failed", "error", err)
return err
}

Expand All @@ -484,7 +483,7 @@ func (b *Billing) ChangeSubscription(userRepo user.UserRepo, billingRepo Billing
Reason: reason,
}
if err := billingRepo.LogCreditTransaction(tx); err != nil {
log.Printf("Warning: credit granted but failed to log transaction: %v", err)
b.Logger.Warn("credit granted but failed to log transaction", "error", err)
return err
}

Expand All @@ -494,7 +493,7 @@ func (b *Billing) ChangeSubscription(userRepo user.UserRepo, billingRepo Billing
func (b *Billing) UpdateSubscription(userRepo user.UserRepo, subUpdatedAttrs SubscriptionAttributes, subscriptionID string) error {
user, err := userRepo.GetUserByEmail(subUpdatedAttrs.UserEmail)
if err != nil {
log.Printf("repo.GetUserByEmail failed: %v", err)
b.Logger.Error("repo.GetUserByEmail failed", "error", err)
return err
}

Expand All @@ -505,7 +504,7 @@ func (b *Billing) UpdateSubscription(userRepo user.UserRepo, subUpdatedAttrs Sub
case b.VariantIDPremium:
tier = "premium"
default:
log.Printf("ERROR: unknown variantID: %d", subUpdatedAttrs.VariantID)
b.Logger.Error("unknown variantID", "variantID", subUpdatedAttrs.VariantID)
return fmt.Errorf("unknown variant ID: %d", subUpdatedAttrs.VariantID)
}

Expand All @@ -518,7 +517,7 @@ func (b *Billing) UpdateSubscription(userRepo user.UserRepo, subUpdatedAttrs Sub
subUpdatedAttrs.EndsAt,
)
if err != nil {
log.Printf("UpdateSubscriptionData failed: %v", err)
b.Logger.Error("UpdateSubscriptionData failed", "error", err)
return err
}

Expand Down
Loading
Loading