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
15 changes: 8 additions & 7 deletions billing/checkout/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/stripe/stripe-go/v79"

"github.com/raystack/frontier/billing"
billingerrors "github.com/raystack/frontier/billing/errors"
"github.com/raystack/frontier/internal/metrics"

"github.com/raystack/frontier/pkg/metadata"
Expand Down Expand Up @@ -350,7 +351,7 @@ func (s *Service) Create(ctx context.Context, ch Checkout) (Checkout, error) {
PaymentMethodCollection: stripe.String(string(stripe.PaymentLinkPaymentMethodCollectionIfRequired)),
})
if err != nil {
return Checkout{}, fmt.Errorf("failed to create subscription at billing provider: %w", err)
return Checkout{}, fmt.Errorf("failed to create subscription at billing provider: %w", billingerrors.TranslateStripeError(err))
}

return s.repository.Create(ctx, Checkout{
Expand Down Expand Up @@ -481,7 +482,7 @@ func (s *Service) Create(ctx context.Context, ch Checkout) (Checkout, error) {
},
})
if err != nil {
return Checkout{}, fmt.Errorf("failed to buy product at billing provider: %w", err)
return Checkout{}, fmt.Errorf("failed to buy product at billing provider: %w", billingerrors.TranslateStripeError(err))
}

return s.repository.Create(ctx, Checkout{
Expand Down Expand Up @@ -559,7 +560,7 @@ func (s *Service) SyncWithProvider(ctx context.Context, customerID string) error
},
})
if err != nil {
errs = append(errs, fmt.Errorf("failed to get checkout session from billing provider: %w", err))
errs = append(errs, fmt.Errorf("failed to get checkout session from billing provider: %w", billingerrors.TranslateStripeError(err)))
continue
}
if ch.PaymentStatus != string(checkoutSession.PaymentStatus) {
Expand Down Expand Up @@ -735,7 +736,7 @@ func (s *Service) ensureSubscription(ctx context.Context, ch Checkout) (string,
},
})
if err != nil {
return "", fmt.Errorf("failed to get subscription from billing provider: %w", err)
return "", fmt.Errorf("failed to get subscription from billing provider: %w", billingerrors.TranslateStripeError(err))
}

// create subscription
Expand Down Expand Up @@ -802,7 +803,7 @@ func (s *Service) CreateSessionForPaymentMethod(ctx context.Context, ch Checkout
},
})
if err != nil {
return Checkout{}, fmt.Errorf("failed to create checkout at billing provider: %w", err)
return Checkout{}, fmt.Errorf("failed to create checkout at billing provider: %w", billingerrors.TranslateStripeError(err))
}

return s.repository.Create(ctx, Checkout{
Expand Down Expand Up @@ -844,7 +845,7 @@ func (s *Service) CreateSessionForCustomerPortal(ctx context.Context, ch Checkou
session, err := s.stripeClient.BillingPortalSessions.New(sessionParams)

if err != nil {
return Checkout{}, fmt.Errorf("failed to create session for customer portal: %w", err)
return Checkout{}, fmt.Errorf("failed to create session for customer portal: %w", billingerrors.TranslateStripeError(err))
}

return Checkout{
Expand Down Expand Up @@ -989,7 +990,7 @@ func (s *Service) Apply(ctx context.Context, ch Checkout) (*subscription.Subscri
Coupon: couponID,
})
if err != nil {
return nil, nil, fmt.Errorf("failed to create subscription at billing provider: %w", err)
return nil, nil, fmt.Errorf("failed to create subscription at billing provider: %w", billingerrors.TranslateStripeError(err))
}

// register subscription in frontier
Expand Down
43 changes: 17 additions & 26 deletions billing/customer/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package customer

import (
"context"
"errors"
"fmt"
"log/slog"
"math/rand"
Expand All @@ -14,6 +15,7 @@ import (
"github.com/stripe/stripe-go/v79"

"github.com/raystack/frontier/billing"
billingerrors "github.com/raystack/frontier/billing/errors"
"github.com/raystack/frontier/internal/metrics"

"slices"
Expand Down Expand Up @@ -134,14 +136,11 @@ func (s *Service) RegisterToProvider(ctx context.Context, customer Customer) (*s
TestClock: customer.StripeTestClockID,
})
if err != nil {
if stripeErr, ok := err.(*stripe.Error); ok {
switch stripeErr.Code {
case stripe.ErrorCodeParameterMissing:
// stripe error
return nil, fmt.Errorf("missing parameter while registering to biller: %s", stripeErr.Error())
}
var stripeErr *stripe.Error
if errors.As(err, &stripeErr) && stripeErr.Code == stripe.ErrorCodeParameterMissing {
return nil, fmt.Errorf("missing parameter while registering to biller: %s: %w", stripeErr.Msg, err)
}
return nil, fmt.Errorf("failed to register in billing provider: %w", err)
return nil, fmt.Errorf("failed to register in billing provider: %w", billingerrors.TranslateStripeError(err))
}

return stripeCustomer, nil
Expand Down Expand Up @@ -194,14 +193,11 @@ func (s *Service) Update(ctx context.Context, customer Customer) (Customer, erro
},
})
if err != nil {
if stripeErr, ok := err.(*stripe.Error); ok {
switch stripeErr.Code {
case stripe.ErrorCodeParameterMissing:
// stripe error
return Customer{}, fmt.Errorf("missing parameter while registering to biller: %s", stripeErr.Error())
}
var stripeErr *stripe.Error
if errors.As(err, &stripeErr) && stripeErr.Code == stripe.ErrorCodeParameterMissing {
return Customer{}, fmt.Errorf("missing parameter while registering to biller: %s: %w", stripeErr.Msg, err)
}
return Customer{}, fmt.Errorf("failed to register in billing provider: %w", err)
return Customer{}, fmt.Errorf("failed to register in billing provider: %w", billingerrors.TranslateStripeError(err))
}
customer.ProviderID = stripeCustomer.ID
return s.repository.UpdateByID(ctx, customer)
Expand Down Expand Up @@ -286,17 +282,9 @@ func (s *Service) Delete(ctx context.Context, id string) error {
Context: ctx,
},
}); err != nil {
var throw = true
// Try to safely cast a generic error to a stripe.Error so that we can get at
// some additional Stripe-specific information about what went wrong.
if stripeErr, ok := err.(*stripe.Error); ok {
// The Code field will contain a basic identifier for the failure.
if stripeErr.Code == stripe.ErrorCodeResourceMissing {
// it's ok if the customer is already deleted
throw = false
}
}
if throw {
err = billingerrors.TranslateStripeError(err)
// it's ok if the customer is already deleted
if !errors.Is(err, billingerrors.ErrProviderResourceMissing) {
return fmt.Errorf("failed to delete customer from billing provider: %w", err)
}
}
Expand Down Expand Up @@ -352,6 +340,9 @@ func (s *Service) ListPaymentMethods(ctx context.Context, id string) ([]PaymentM

paymentMethods = append(paymentMethods, pm)
}
if err := stripePaymentMethodItr.Err(); err != nil {
Comment thread
whoAbhishekSah marked this conversation as resolved.
return nil, fmt.Errorf("failed to list payment methods from billing provider: %w", billingerrors.TranslateStripeError(err))
}
return paymentMethods, nil
}

Expand Down Expand Up @@ -432,7 +423,7 @@ func (s *Service) SyncWithProvider(ctx context.Context, customr Customer) error
},
})
if err != nil {
return fmt.Errorf("failed to get customer from billing provider: %w", err)
return fmt.Errorf("failed to get customer from billing provider: %w", billingerrors.TranslateStripeError(err))
}

var shouldUpdate bool
Expand Down
17 changes: 11 additions & 6 deletions billing/invoice/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/stripe/stripe-go/v79"

"github.com/raystack/frontier/billing"
billingerrors "github.com/raystack/frontier/billing/errors"
"github.com/raystack/frontier/internal/metrics"

"github.com/raystack/frontier/billing/customer"
Expand Down Expand Up @@ -287,7 +288,7 @@ func (s *Service) SyncWithProvider(ctx context.Context, customr customer.Custome
return errors.Join(errs...)
}
if err := stripeInvoices.Err(); err != nil {
return fmt.Errorf("failed to list invoices: %w", err)
return fmt.Errorf("failed to list invoices: %w", billingerrors.TranslateStripeError(err))
}
return nil
}
Expand Down Expand Up @@ -361,7 +362,7 @@ func (s *Service) GetUpcoming(ctx context.Context, customerID string) (Invoice,
s.log.DebugContext(ctx, "no upcoming invoice", "error", stripeErr)
return Invoice{}, nil
}
return Invoice{}, fmt.Errorf("failed to get upcoming invoice: %w", err)
return Invoice{}, fmt.Errorf("failed to get upcoming invoice: %w", billingerrors.TranslateStripeError(err))
}

return stripeInvoiceToInvoice(customerID, stripeInvoice), nil
Expand Down Expand Up @@ -693,7 +694,7 @@ func (s *Service) CreateInProvider(ctx context.Context, custmr customer.Customer
},
})
if err != nil {
return nil, fmt.Errorf("failed to create invoice: %w", err)
return nil, fmt.Errorf("failed to create invoice: %w", billingerrors.TranslateStripeError(err))
}

// create line item for the invoice
Expand Down Expand Up @@ -726,19 +727,23 @@ func (s *Service) CreateInProvider(ctx context.Context, custmr customer.Customer
Period: itemPeriod,
})
if err != nil {
return nil, fmt.Errorf("failed to create invoice item: %w", err)
return nil, fmt.Errorf("failed to create invoice item: %w", billingerrors.TranslateStripeError(err))
}
}

// fetch updated stripe invoice
return s.stripeClient.Invoices.Get(stripeInvoice.ID, &stripe.InvoiceParams{
updatedInvoice, err := s.stripeClient.Invoices.Get(stripeInvoice.ID, &stripe.InvoiceParams{
Params: stripe.Params{
Context: ctx,
},
Expand: []*string{
new("lines"),
},
})
if err != nil {
return nil, fmt.Errorf("failed to get invoice from billing provider: %w", billingerrors.TranslateStripeError(err))
}
return updatedInvoice, nil
}

// Reconcile checks all paid invoices and reconciles them with the system.
Expand Down Expand Up @@ -835,7 +840,7 @@ func (s *Service) reconcileCreditInvoice(ctx context.Context, inv Invoice) error
func (s *Service) TriggerSyncByProviderID(ctx context.Context, id string) error {
stripeInvoice, err := s.stripeClient.Invoices.Get(id, &stripe.InvoiceParams{})
if err != nil {
return err
return fmt.Errorf("failed to get invoice from billing provider: %w", billingerrors.TranslateStripeError(err))
}

customrs, err := s.customerService.List(ctx, customer.Filter{
Expand Down
11 changes: 6 additions & 5 deletions billing/product/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"slices"

"github.com/google/uuid"
billingerrors "github.com/raystack/frontier/billing/errors"
"github.com/raystack/frontier/pkg/utils"
"github.com/stripe/stripe-go/v79/client"
)
Expand Down Expand Up @@ -85,7 +86,7 @@ func (s *Service) Create(ctx context.Context, product Product) (Product, error)
},
})
if err != nil {
return Product{}, err
return Product{}, fmt.Errorf("failed to create product at billing provider: %w", billingerrors.TranslateStripeError(err))
}

productOb, err := s.productRepository.Create(ctx, product)
Expand Down Expand Up @@ -213,7 +214,7 @@ func (s *Service) Update(ctx context.Context, product Product) (Product, error)
},
})
if err != nil {
return Product{}, err
return Product{}, fmt.Errorf("failed to update product at billing provider: %w", billingerrors.TranslateStripeError(err))
}

// check feature updates in product
Expand Down Expand Up @@ -405,7 +406,7 @@ func (s *Service) setPriceActive(ctx context.Context, price Price, active bool)
Params: stripe.Params{Context: ctx},
Active: new(active),
}); err != nil {
return err
return fmt.Errorf("failed to update price at billing provider: %w", billingerrors.TranslateStripeError(err))
}
}
if active {
Expand Down Expand Up @@ -481,7 +482,7 @@ func (s *Service) CreatePrice(ctx context.Context, price Price) (Price, error) {
}
stripePrice, err := s.stripeClient.Prices.New(providerParams)
if err != nil {
return Price{}, err
return Price{}, fmt.Errorf("failed to create price at billing provider: %w", billingerrors.TranslateStripeError(err))
}

price.ProviderID = stripePrice.ID
Expand Down Expand Up @@ -533,7 +534,7 @@ func (s *Service) UpdatePrice(ctx context.Context, price Price) (Price, error) {
},
})
if err != nil {
return Price{}, err
return Price{}, fmt.Errorf("failed to update price at billing provider: %w", billingerrors.TranslateStripeError(err))
}

return s.priceRepository.UpdateByID(ctx, existingPrice)
Expand Down
21 changes: 11 additions & 10 deletions billing/subscription/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/raystack/frontier/billing/credit"

"github.com/raystack/frontier/billing"
billingerrors "github.com/raystack/frontier/billing/errors"

"github.com/raystack/frontier/billing/product"
"github.com/raystack/frontier/pkg/utils"
Expand Down Expand Up @@ -330,7 +331,7 @@ func (s *Service) Cancel(ctx context.Context, id string, immediate bool) (Subscr
Prorate: new(true),
})
if err != nil {
return Subscription{}, fmt.Errorf("failed to cancel subscription at billing provider: %w", err)
return Subscription{}, fmt.Errorf("failed to cancel subscription at billing provider: %w", billingerrors.TranslateStripeError(err))
}
sub.State = string(stripeSubscription.Status)
if stripeSubscription.CanceledAt > 0 {
Expand Down Expand Up @@ -359,7 +360,7 @@ func (s *Service) Cancel(ctx context.Context, id string, immediate bool) (Subscr
EndBehavior: stripe.String(string(stripe.SubscriptionScheduleEndBehaviorCancel)),
})
if err != nil {
return sub, fmt.Errorf("failed to cancel subscription schedule at billing provider: %w", err)
return sub, fmt.Errorf("failed to cancel subscription schedule at billing provider: %w", billingerrors.TranslateStripeError(err))
}
sub.Phase.PlanID = ""
sub.Phase.Reason = SubscriptionCancel.String()
Expand All @@ -381,8 +382,8 @@ func (s *Service) createOrGetSchedule(ctx context.Context, sub Subscription) (*s
},
})
if err != nil {
// check if it's a subscription not found err
if stripeErr, ok := err.(*stripe.Error); ok && stripeErr.Code == stripe.ErrorCodeResourceMissing {
err = billingerrors.TranslateStripeError(err)
if errors.Is(err, billingerrors.ErrProviderResourceMissing) {
return nil, nil, ErrSubscriptionOnProviderNotFound
}
return nil, nil, fmt.Errorf("failed to get subscription from billing provider: %w", err)
Expand All @@ -398,7 +399,7 @@ func (s *Service) createOrGetSchedule(ctx context.Context, sub Subscription) (*s
},
})
if err != nil {
return nil, nil, fmt.Errorf("failed to get subscription schedule from billing provider: %w", err)
return nil, nil, fmt.Errorf("failed to get subscription schedule from billing provider: %w", billingerrors.TranslateStripeError(err))
}
stripeSubscription.Schedule = schedule
}
Expand All @@ -421,7 +422,7 @@ func (s *Service) createOrGetSchedule(ctx context.Context, sub Subscription) (*s
},
})
if err != nil {
return nil, nil, fmt.Errorf("failed to create subscription schedule at billing provider: %w", err)
return nil, nil, fmt.Errorf("failed to create subscription schedule at billing provider: %w", billingerrors.TranslateStripeError(err))
}
}
return stripeSubscription, stripeSubscription.Schedule, nil
Expand Down Expand Up @@ -483,7 +484,7 @@ func (s *Service) UpdateProductQuantity(ctx context.Context, orgID string, curre
PendingInvoiceItemInterval: getPendingInvoiceItemInterval(currentPlan),
})
if err != nil {
return fmt.Errorf("failed to update subscription quantity at billing provider: %w", err)
return fmt.Errorf("failed to update subscription quantity at billing provider: %w", billingerrors.TranslateStripeError(err))
}
}
}
Expand Down Expand Up @@ -561,7 +562,7 @@ func (s *Service) UpdateProductQuantity(ctx context.Context, orgID string, curre
Phases: updatedPhases,
})
if err != nil {
return fmt.Errorf("failed to update subscription schedule at billing provider: %w", err)
return fmt.Errorf("failed to update subscription schedule at billing provider: %w", billingerrors.TranslateStripeError(err))
}
}

Expand Down Expand Up @@ -773,7 +774,7 @@ func (s *Service) ChangePlan(ctx context.Context, id string, changeRequest Chang
},
})
if err != nil {
return change, fmt.Errorf("failed to update subscription schedule at billing provider: %w", err)
return change, fmt.Errorf("failed to update subscription schedule at billing provider: %w", billingerrors.TranslateStripeError(err))
}

// update subscription with new phase
Expand Down Expand Up @@ -968,7 +969,7 @@ func (s *Service) CancelUpcomingPhase(ctx context.Context, sub Subscription) err
},
})
if err != nil {
return fmt.Errorf("failed to update subscription schedule at billing provider: %w", err)
return fmt.Errorf("failed to update subscription schedule at billing provider: %w", billingerrors.TranslateStripeError(err))
}

sub.Phase.Reason = ""
Expand Down
Loading