rentease/internal/server/handle_stripe_webhook_test.go
Ruidy 6ca13cdffd
chore(stripe): upgrade to stripe-go v83
Upgrade Stripe SDK from v79 to v83 across the codebase. Update all
imports to use github.com/stripe/stripe-go/v83 and refactor client usage
to match the new API, including changes to PaymentIntents listing.
Update documentation and plans to reference the new version. Remove
references to the old version from go.mod and go.sum.
2025-10-05 21:09:06 +02:00

150 lines
4.1 KiB
Go

package server
import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
"github.com/labstack/echo/v4"
"github.com/stripe/stripe-go/v83"
"github.com/stripe/stripe-go/v83/webhook"
)
type stubStripeEventService struct {
intentCalled bool
chargeCalled bool
err error
}
func (s *stubStripeEventService) HandlePaymentIntentSucceeded(ctx context.Context, pi *stripe.PaymentIntent) error {
s.intentCalled = true
return s.err
}
func (s *stubStripeEventService) HandleChargeRefunded(ctx context.Context, ch *stripe.Charge) error {
s.chargeCalled = true
return s.err
}
func TestHandleStripeWebhookPaymentIntent(t *testing.T) {
secret := "whsec_test"
payload := map[string]any{
"id": "evt_test",
"type": "payment_intent.succeeded",
"api_version": stripe.APIVersion,
"data": map[string]any{
"object": map[string]any{
"id": "pi_123",
"amount": 10000,
"amount_received": 10000,
"currency": "eur",
"status": "succeeded",
"metadata": map[string]string{"booking_id": "42"},
"payment_method_types": []string{"card"},
},
},
}
payloadBytes, err := json.Marshal(payload)
if err != nil {
t.Fatalf("failed to marshal payload: %v", err)
}
ts := time.Now()
sig := webhook.ComputeSignature(ts, payloadBytes, secret)
sigHeader := fmt.Sprintf("t=%d,v1=%s", ts.Unix(), hex.EncodeToString(sig))
if _, err := webhook.ConstructEvent(payloadBytes, sigHeader, secret); err != nil {
t.Fatalf("signature validation failed in setup: %v", err)
}
e := echo.New()
req := httptest.NewRequest(http.MethodPost, "/webhooks/stripe", strings.NewReader(string(payloadBytes)))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
req.Header.Set("Stripe-Signature", sigHeader)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
service := &stubStripeEventService{}
handler := handleStripeWebhook(service, secret)
if err := handler(c); err != nil {
t.Fatalf("handler returned error: %v", err)
}
if rec.Code != http.StatusOK {
t.Fatalf("expected 200, got %d", rec.Code)
}
if !service.intentCalled {
t.Fatalf("expected payment intent handler to be called")
}
}
func TestHandleStripeWebhookChargeRefunded(t *testing.T) {
secret := "whsec_test"
payload := map[string]any{
"id": "evt_charge",
"type": "charge.refunded",
"api_version": stripe.APIVersion,
"data": map[string]any{
"object": map[string]any{
"id": "ch_123",
"amount": 5000,
"amount_refunded": 5000,
"payment_intent": map[string]any{
"id": "pi_123",
},
},
},
}
payloadBytes, _ := json.Marshal(payload)
ts := time.Now()
sig := webhook.ComputeSignature(ts, payloadBytes, secret)
sigHeader := fmt.Sprintf("t=%d,v1=%s", ts.Unix(), hex.EncodeToString(sig))
if _, err := webhook.ConstructEvent(payloadBytes, sigHeader, secret); err != nil {
t.Fatalf("signature validation failed in setup: %v", err)
}
e := echo.New()
req := httptest.NewRequest(http.MethodPost, "/webhooks/stripe", strings.NewReader(string(payloadBytes)))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
req.Header.Set("Stripe-Signature", sigHeader)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
service := &stubStripeEventService{}
handler := handleStripeWebhook(service, secret)
if err := handler(c); err != nil {
t.Fatalf("handler returned error: %v", err)
}
if !service.chargeCalled {
t.Fatalf("expected charge handler to be called")
}
}
func TestHandleStripeWebhookInvalidSignature(t *testing.T) {
e := echo.New()
req := httptest.NewRequest(http.MethodPost, "/webhooks/stripe", strings.NewReader("{}"))
req.Header.Set("Stripe-Signature", "invalid")
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
handler := handleStripeWebhook(&stubStripeEventService{}, "secret")
err := handler(c)
if err == nil {
t.Fatal("expected error for invalid signature")
}
if httpErr, ok := err.(*echo.HTTPError); !ok || httpErr.Code != http.StatusBadRequest {
t.Fatalf("expected 400 HTTP error, got %v", err)
}
}