mirror of
https://github.com/rjNemo/rentease.git
synced 2026-06-06 02:36:49 +00:00
74 lines
1.9 KiB
Go
74 lines
1.9 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
|
|
"github.com/stripe/stripe-go/v83"
|
|
"github.com/stripe/stripe-go/v83/webhook"
|
|
)
|
|
|
|
type stripeEventService interface {
|
|
HandlePaymentIntentSucceeded(ctx context.Context, pi *stripe.PaymentIntent) error
|
|
HandleChargeRefunded(ctx context.Context, ch *stripe.Charge) error
|
|
}
|
|
|
|
var constructEvent = webhook.ConstructEvent
|
|
|
|
func handleStripeWebhook(bs stripeEventService, secret string) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
if secret == "" {
|
|
http.Error(w, "stripe webhook secret not configured", http.StatusServiceUnavailable)
|
|
return
|
|
}
|
|
|
|
payload, err := io.ReadAll(r.Body)
|
|
if err != nil {
|
|
http.Error(w, "unable to read request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
sig := r.Header.Get("Stripe-Signature")
|
|
if sig == "" {
|
|
http.Error(w, "missing Stripe-Signature header", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
event, err := constructEvent(payload, sig, secret)
|
|
if err != nil {
|
|
http.Error(w, "invalid webhook signature", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
switch event.Type {
|
|
case stripe.EventTypePaymentIntentSucceeded:
|
|
var pi stripe.PaymentIntent
|
|
if err := json.Unmarshal(event.Data.Raw, &pi); err != nil {
|
|
http.Error(w, "invalid payment intent payload", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := bs.HandlePaymentIntentSucceeded(r.Context(), &pi); err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
case stripe.EventTypeChargeRefunded:
|
|
var ch stripe.Charge
|
|
if err := json.Unmarshal(event.Data.Raw, &ch); err != nil {
|
|
http.Error(w, "invalid charge payload", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := bs.HandleChargeRefunded(r.Context(), &ch); err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
default:
|
|
// Acknowledge events we don't actively process.
|
|
}
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
}
|
|
}
|