Overview
The create-checkout-session edge function creates a Stripe checkout session for organization owners to purchase event or attendee tokens. It handles dynamic pricing based on quantity tiers and integrates with Stripe for payment processing.
Endpoint
POST /functions/v1/create-checkout-session
Authentication
Requires a valid Bearer token. The authenticated user must be an organization owner.
Authorization: Bearer <supabase_access_token>
Request Body
Type of tokens to purchase. Must be either "event" or "attendee".
Number of tokens to purchase. Must be at least 1 and match available pricing tiers.
Example Request
curl -X POST 'https://<project-ref>.supabase.co/functions/v1/create-checkout-session' \
-H 'Authorization: Bearer <user_token>' \
-H 'Content-Type: application/json' \
-d '{
"token_type": "event",
"quantity": 10
}'
Response
Success Response (200 OK)
Stripe checkout session URL where the user should be redirected to complete payment
{
"url": "https://checkout.stripe.com/c/pay/cs_test_..."
}
Error Responses
400 Bad Request
Returned when request parameters are invalid.
{
"error": "Invalid token_type or quantity"
}
{
"error": "token_type must be 'event' or 'attendee'"
}
{
"error": "No pricing tier for quantity 1000"
}
401 Unauthorized
Returned when authentication fails.
{
"error": "Unauthorized"
}
404 Not Found
Returned when the user’s organization is not found.
{
"error": "Organization not found"
}
500 Internal Server Error
Returned when checkout session creation fails.
{
"error": "Payment session creation failed"
}
Pricing Tiers
The function dynamically calculates pricing based on the token_pricing table. It finds the appropriate tier based on min_quantity and max_quantity for the requested token type.
From source/supabase/functions/create-checkout-session/index.ts:54-69:
const { data: tiers } = await adminClient
.from("token_pricing")
.select("*")
.eq("type", token_type)
.order("min_quantity");
const tier = tiers.find(
(t: any) => quantity >= t.min_quantity && quantity <= t.max_quantity
);
if (!tier) throw new Error(`No pricing tier for quantity ${quantity}`);
const unitAmountCents = Math.round(Number(tier.price_per_unit) * 100);
const totalAmount = unitAmountCents * quantity;
Stripe Integration
Checkout Session Creation
From source/supabase/functions/create-checkout-session/index.ts:89-116:
const session = await stripe.checkout.sessions.create({
customer: customerId,
customer_email: customerId ? undefined : email,
line_items: [
{
price_data: {
currency: tier.currency.toLowerCase(),
product_data: {
name: `${token_type === "event" ? "Event" : "Attendee"} Tokens (x${quantity})`,
description: `${quantity} ${token_type} tokens for ${org.name}`,
},
unit_amount: unitAmountCents,
},
quantity,
},
],
mode: "payment",
success_url: `${req.headers.get("origin")}/purchase?status=success`,
cancel_url: `${req.headers.get("origin")}/purchase?status=cancelled`,
metadata: {
organization_id: org.id,
token_type,
quantity: String(quantity),
price_per_unit: String(tier.price_per_unit),
total_amount: String(totalAmount / 100),
user_id: userId,
},
});
Transaction Tracking
The function creates a pending transaction record that will be completed by the stripe-webhook function:
await adminClient.from("token_transactions").insert({
organization_id: org.id,
type: token_type,
quantity,
amount: totalAmount / 100,
currency: tier.currency,
status: "pending",
stripe_session_id: session.id,
payment_method: "stripe",
});
Flow
- Client requests checkout session with token type and quantity
- Function verifies user owns an organization
- Function retrieves pricing tier for requested quantity
- Function calculates total amount based on tier pricing
- Function creates or retrieves Stripe customer
- Function creates Stripe checkout session with metadata
- Function creates pending transaction record
- Client redirects user to Stripe checkout URL
- After payment, Stripe webhook completes the transaction (see stripe-webhook)
The pending transaction must be completed by the Stripe webhook. Ensure your STRIPE_WEBHOOK_SECRET is properly configured.