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()