mirror of
https://github.com/rjNemo/rentease.git
synced 2026-06-06 02:36:49 +00:00
93 lines
2.5 KiB
Go
93 lines
2.5 KiB
Go
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
|
|
}
|