Chockfull
This commit is contained in:
@@ -145,7 +145,7 @@ func (h *StripeHandler) VerifyCheckoutSession(w http.ResponseWriter, r *http.Req
|
||||
return
|
||||
}
|
||||
|
||||
if s.ClientReferenceID != userID {
|
||||
if s.ClientReferenceID != "" && s.ClientReferenceID != userID {
|
||||
writeError(w, http.StatusForbidden, "FORBIDDEN", "Session does not belong to this user")
|
||||
return
|
||||
}
|
||||
@@ -204,6 +204,65 @@ func (h *StripeHandler) ActivateFreeTier(w http.ResponseWriter, r *http.Request)
|
||||
})
|
||||
}
|
||||
|
||||
// CreateOnboardingCheckout creates a Stripe Checkout session for a user who
|
||||
// has not yet created an account. This is a public endpoint (no auth required).
|
||||
// The Firebase account is created on the frontend only after payment succeeds.
|
||||
func (h *StripeHandler) CreateOnboardingCheckout(w http.ResponseWriter, r *http.Request) {
|
||||
var body struct {
|
||||
Email string `json:"email"`
|
||||
Tier string `json:"tier"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||
writeError(w, http.StatusBadRequest, "BAD_REQUEST", "Invalid request body")
|
||||
return
|
||||
}
|
||||
|
||||
if body.Email == "" {
|
||||
writeError(w, http.StatusBadRequest, "VALIDATION_ERROR", "Email is required")
|
||||
return
|
||||
}
|
||||
|
||||
if body.Tier == "" {
|
||||
body.Tier = "premium"
|
||||
}
|
||||
|
||||
tier := domain.SubscriptionTier(body.Tier)
|
||||
if tier != domain.TierPremium && tier != domain.TierPro {
|
||||
writeError(w, http.StatusBadRequest, "VALIDATION_ERROR", "Tier must be 'premium' or 'pro'")
|
||||
return
|
||||
}
|
||||
|
||||
priceID, err := h.priceIDForTier(tier)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusBadRequest, "VALIDATION_ERROR", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
params := &stripe.CheckoutSessionParams{
|
||||
Mode: stripe.String(string(stripe.CheckoutSessionModeSubscription)),
|
||||
LineItems: []*stripe.CheckoutSessionLineItemParams{
|
||||
{
|
||||
Price: stripe.String(priceID),
|
||||
Quantity: stripe.Int64(1),
|
||||
},
|
||||
},
|
||||
SuccessURL: stripe.String(h.cfg.FrontendURL + "/subscribe?payment=success&session_id={CHECKOUT_SESSION_ID}"),
|
||||
CancelURL: stripe.String(h.cfg.FrontendURL + "/subscribe?payment=cancelled"),
|
||||
CustomerEmail: stripe.String(body.Email),
|
||||
}
|
||||
params.AddMetadata("tier", string(tier))
|
||||
params.AddMetadata("onboarding", "true")
|
||||
|
||||
s, err := checkoutsession.New(params)
|
||||
if err != nil {
|
||||
log.Printf("Failed to create onboarding checkout session: %v", err)
|
||||
writeError(w, http.StatusInternalServerError, "STRIPE_ERROR", "Failed to create checkout session")
|
||||
return
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusOK, map[string]string{"url": s.URL})
|
||||
}
|
||||
|
||||
// CreatePortalSession creates a Stripe Billing Portal session so the user can
|
||||
// manage their subscription (cancel, update payment method, view invoices).
|
||||
func (h *StripeHandler) CreatePortalSession(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
Reference in New Issue
Block a user