package booking import ( "context" "errors" "log/slog" "math" "strings" "github.com/stripe/stripe-go/v83" "gorm.io/gorm" stripeclient "github.com/rjNemo/rentease/internal/driver/stripe" ) // HandlePaymentIntentSucceeded persists successful Stripe payment intents received via webhook. func (bs Service) HandlePaymentIntentSucceeded(ctx context.Context, pi *stripe.PaymentIntent) error { if pi == nil { return errors.New("payment intent payload is missing") } normalized := stripeclient.NormalizePaymentIntent(pi) if normalized.ID == "" { return errors.New("payment intent missing id") } if normalized.BookingID == nil { bs.logger.Warn("stripe webhook payment missing booking metadata", slog.String("payment_intent", normalized.ID)) return nil } bookingID := uint(*normalized.BookingID) stripeID := normalized.ID status := strings.ToLower(normalized.Status) _, err := bs.store.UpsertStripePayment(&Payment{ BookingID: bookingID, Amount: normalized.Amount, PaymentMethod: mapStripeMethod(normalized.PaymentMethod), StripePaymentID: &stripeID, StripeStatus: &status, }) if err != nil { return err } bs.logger.Info("stripe payment intent processed", slog.String("payment_intent", normalized.ID), slog.Int("booking_id", int(bookingID))) return nil } // HandleChargeRefunded updates an existing Stripe payment when a charge is refunded. func (bs Service) HandleChargeRefunded(ctx context.Context, ch *stripe.Charge) error { if ch == nil { return errors.New("charge payload is missing") } if ch.PaymentIntent == nil || ch.PaymentIntent.ID == "" { bs.logger.Warn("stripe refund missing payment intent", slog.String("charge", ch.ID)) return nil } existing, err := bs.store.FindStripePayment(ch.PaymentIntent.ID) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { bs.logger.Warn("stripe refund received for unknown payment", slog.String("payment_intent", ch.PaymentIntent.ID)) return nil } return err } amount := existing.Amount if ch.AmountRefunded > 0 { net := float64(ch.Amount-ch.AmountRefunded) / 100.0 amount = math.Max(net, 0) } status := "refunded" stripeID := ch.PaymentIntent.ID _, err = bs.store.UpsertStripePayment(&Payment{ BookingID: existing.BookingID, Amount: amount, PaymentMethod: existing.PaymentMethod, StripePaymentID: &stripeID, StripeStatus: &status, }) if err != nil { return err } bs.logger.Info("stripe charge refunded processed", slog.String("charge", ch.ID), slog.String("payment_intent", ch.PaymentIntent.ID)) return nil }