summaryrefslogtreecommitdiff
path: root/internal/billing/stripe.go
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--internal/billing/stripe.go71
1 files changed, 40 insertions, 31 deletions
diff --git a/internal/billing/stripe.go b/internal/billing/stripe.go
index 032eb02..ea4b7ea 100644
--- a/internal/billing/stripe.go
+++ b/internal/billing/stripe.go
@@ -29,6 +29,35 @@ func (s *Service) CreateCheckout(ctx context.Context, input CheckoutInput) (Chec
if err != nil {
return CheckoutResult{}, err
}
+ params := s.checkoutSessionParams(orderID, input)
+ customerID, err := s.ensureStripeCustomer(ctx, input.TenantID)
+ if err != nil {
+ return CheckoutResult{}, s.failCheckoutCreation(ctx, orderID, err)
+ }
+ if customerID != "" {
+ params.Customer = stripe.String(customerID)
+ } else {
+ params.CustomerCreation = stripe.String(string(stripe.CheckoutSessionCustomerCreationAlways))
+ if strings.TrimSpace(input.CustomerEmail) != "" {
+ params.CustomerEmail = stripe.String(strings.TrimSpace(input.CustomerEmail))
+ }
+ }
+ session, err := s.createStripeCheckout(ctx, params)
+ if err != nil {
+ return CheckoutResult{}, s.failCheckoutCreation(ctx, orderID, fmt.Errorf("create Stripe Checkout Session: %w", err))
+ }
+ if session == nil || session.ID == "" || session.URL == "" {
+ return CheckoutResult{}, s.failCheckoutCreation(ctx, orderID, errors.New("Stripe returned an incomplete Checkout Session"))
+ }
+ if _, err := s.db.Exec(ctx, `
+ UPDATE topup_orders SET stripe_session_id = $2, checkout_url = $3
+ WHERE id = $1`, orderID, session.ID, session.URL); err != nil {
+ return CheckoutResult{}, s.failCheckoutCreation(ctx, orderID, fmt.Errorf("persist Stripe Checkout Session: %w", err))
+ }
+ return CheckoutResult{OrderID: orderID, SessionID: session.ID, URL: session.URL}, nil
+}
+
+func (s *Service) checkoutSessionParams(orderID string, input CheckoutInput) *stripe.CheckoutSessionCreateParams {
params := &stripe.CheckoutSessionCreateParams{
Mode: stripe.String("payment"),
ClientReferenceID: stripe.String(orderID),
@@ -58,43 +87,23 @@ func (s *Service) CreateCheckout(ctx context.Context, input CheckoutInput) (Chec
},
}},
}
- customerID, err := s.ensureStripeCustomer(ctx, input.TenantID)
- if err != nil {
- if _, updateErr := s.db.Exec(ctx, `UPDATE topup_orders SET status = 'failed' WHERE id = $1 AND status = 'pending'`, orderID); updateErr != nil {
- return CheckoutResult{}, errors.Join(err, fmt.Errorf("mark top-up order failed: %w", updateErr))
- }
- return CheckoutResult{}, err
- }
- if customerID != "" {
- params.Customer = stripe.String(customerID)
- } else {
- params.CustomerCreation = stripe.String(string(stripe.CheckoutSessionCustomerCreationAlways))
- if strings.TrimSpace(input.CustomerEmail) != "" {
- params.CustomerEmail = stripe.String(strings.TrimSpace(input.CustomerEmail))
- }
- }
if s.stripeAutomaticTax {
params.AutomaticTax = &stripe.CheckoutSessionCreateAutomaticTaxParams{Enabled: stripe.Bool(true)}
params.TaxIDCollection = &stripe.CheckoutSessionCreateTaxIDCollectionParams{Enabled: stripe.Bool(true)}
params.LineItems[0].PriceData.ProductData.TaxCode = stripe.String(s.stripeProductTaxCode)
}
params.SetIdempotencyKey("aigw_topup_" + orderID)
- session, err := s.createStripeCheckout(ctx, params)
- if err != nil {
- if _, updateErr := s.db.Exec(ctx, `UPDATE topup_orders SET status = 'failed' WHERE id = $1 AND status = 'pending'`, orderID); updateErr != nil {
- return CheckoutResult{}, errors.Join(fmt.Errorf("create Stripe Checkout Session: %w", err), fmt.Errorf("mark top-up order failed: %w", updateErr))
- }
- return CheckoutResult{}, fmt.Errorf("create Stripe Checkout Session: %w", err)
- }
- if session.ID == "" || session.URL == "" {
- return CheckoutResult{}, errors.New("Stripe returned an incomplete Checkout Session")
- }
- if _, err := s.db.Exec(ctx, `
- UPDATE topup_orders SET stripe_session_id = $2, checkout_url = $3
- WHERE id = $1`, orderID, session.ID, session.URL); err != nil {
- return CheckoutResult{}, fmt.Errorf("persist Stripe Checkout Session: %w", err)
- }
- return CheckoutResult{OrderID: orderID, SessionID: session.ID, URL: session.URL}, nil
+ return params
+}
+
+func (s *Service) failCheckoutCreation(ctx context.Context, orderID string, cause error) error {
+ _, updateErr := s.db.Exec(ctx, `UPDATE topup_orders
+ SET status='failed', reconciliation_status='unknown', reconciliation_error=$2
+ WHERE id=$1 AND status='pending'`, orderID, truncateError(cause))
+ if updateErr != nil {
+ return errors.Join(cause, fmt.Errorf("mark top-up order failed: %w", updateErr))
+ }
+ return cause
}
func checkoutReturnURL(raw, orderID string, includeStripeSession bool) string {