2
0
Files
Royal-Pop-Accessory/Backend/internal/httpx/payment_state.go
T
2026-06-23 18:50:37 +01:00

106 lines
2.7 KiB
Go

package httpx
import (
"strings"
"sync"
"time"
)
type paymentIntentVerification struct {
PaymentIntentID string `json:"paymentIntentId"`
WebhookState string `json:"webhookState"`
WebhookEventID string `json:"webhookEventId,omitempty"`
WebhookEventType string `json:"webhookEventType,omitempty"`
Message string `json:"message"`
Verified bool `json:"verified"`
UpdatedAt time.Time `json:"updatedAt"`
CreatedAt time.Time `json:"createdAt"`
}
type paymentIntentStateStore struct {
mu sync.RWMutex
records map[string]paymentIntentVerification
}
func newPaymentIntentStateStore() *paymentIntentStateStore {
return &paymentIntentStateStore{records: make(map[string]paymentIntentVerification)}
}
func (s *paymentIntentStateStore) upsertCreated(paymentIntentID string) {
if strings.TrimSpace(paymentIntentID) == "" {
return
}
now := time.Now().UTC()
s.mu.Lock()
defer s.mu.Unlock()
record, exists := s.records[paymentIntentID]
if !exists {
record = paymentIntentVerification{
PaymentIntentID: paymentIntentID,
CreatedAt: now,
}
}
record.WebhookState = "awaiting_webhook"
record.Message = "Waiting for Stripe webhook verification."
record.Verified = false
record.UpdatedAt = now
s.records[paymentIntentID] = record
}
func (s *paymentIntentStateStore) applyWebhook(result *stripeWebhookResult) {
if result == nil || strings.TrimSpace(result.PaymentIntentID) == "" {
return
}
now := time.Now().UTC()
s.mu.Lock()
defer s.mu.Unlock()
record, exists := s.records[result.PaymentIntentID]
if !exists {
record = paymentIntentVerification{
PaymentIntentID: result.PaymentIntentID,
CreatedAt: now,
}
}
record.WebhookEventID = result.EventID
record.WebhookEventType = result.EventType
record.Message = result.Message
record.Verified = result.Verified
record.UpdatedAt = now
switch result.OrderState {
case "paid_verified_local_only", "paid_unrecorded":
record.WebhookState = "succeeded"
case "payment_failed_verified_local_only", "payment_failed_unrecorded":
record.WebhookState = "failed"
case "processing_verified_local_only", "processing_unrecorded":
record.WebhookState = "processing"
case "canceled_verified_local_only", "canceled_unrecorded":
record.WebhookState = "canceled"
case "ignored":
record.WebhookState = "ignored"
default:
record.WebhookState = "awaiting_webhook"
}
s.records[result.PaymentIntentID] = record
}
func (s *paymentIntentStateStore) get(paymentIntentID string) (paymentIntentVerification, bool) {
s.mu.RLock()
defer s.mu.RUnlock()
record, exists := s.records[paymentIntentID]
return record, exists
}
var paymentIntentStates = newPaymentIntentStateStore()