Skip to content

Instantly share code, notes, and snippets.

@chand1012
Created April 26, 2025 15:59
Show Gist options
  • Save chand1012/be3e627f15742a7e28da99a4505c1aa6 to your computer and use it in GitHub Desktop.
Save chand1012/be3e627f15742a7e28da99a4505c1aa6 to your computer and use it in GitHub Desktop.
Example stripe checkout code for Supabase.
import "jsr:@supabase/functions-js/edge-runtime.d.ts";
import Stripe from "npm:stripe";
import { createClient } from "jsr:@supabase/supabase-js@2";
import headers from "../_shared/headers.ts";
import type { Database } from "../_shared/database.types.ts";
type CheckoutRequest = {
price?: string;
};
const SUCCESS_REDIRECT_URL = Deno.env.get("SUCCESS_REDIRECT_URL")!;
const CANCEL_REDIRECT_URL = Deno.env.get("CANCEL_REDIRECT_URL")!;
const stripe = new Stripe(Deno.env.get("STRIPE_SECRET_KEY")!);
Deno.serve(async (req) => {
if (req.method === "OPTIONS") {
return new Response(null, {
headers,
});
}
const authHeader = req.headers.get("Authorization")!;
// create a new supabase instance
const supabase = createClient<Database>(
Deno.env.get("SUPABASE_URL") ?? "",
Deno.env.get("SUPABASE_ANON_KEY") ?? "",
{ global: { headers: { Authorization: authHeader } } },
);
const serviceSupabase = createClient<Database>(
Deno.env.get("SUPABASE_URL") ?? "",
Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? "",
);
const { price } = await req.json() as CheckoutRequest;
if (!price) {
return new Response(
JSON.stringify({ error: "Price is required" }),
{
status: 400,
headers: { "Content-Type": "application/json", ...headers },
},
);
}
const { data: { user } } = await supabase.auth.getUser();
if (!user) {
return new Response(
JSON.stringify({ error: "User not found" }),
{
status: 404,
headers: { "Content-Type": "application/json", ...headers },
},
);
}
// see if there's a corresponding customer in the database
// if there is, use the customer's email to create the session
// if not, create a new customer
const { data, error } = await serviceSupabase.from("customers").select(
"*",
).eq("id", user.id);
// if there's an error, return it
if (error) {
return new Response(
JSON.stringify({ error: error.message }),
{
status: 500,
headers: { "Content-Type": "application/json", ...headers },
},
);
}
let customerData = data?.[0];
// create a new customer on stripe if one doesn't exist
if (!customerData) {
// first see if the user has a stripe customer id from the stripe api
const existingCustomers = await stripe.customers.list({
email: user.email,
});
// find the first customer id that matches the user's email
const existingCustomer = existingCustomers.data.find(
(customer) => customer.email === user.email,
);
// if the customer exists, insert the customer into the database
if (existingCustomer) {
const { error } = await serviceSupabase.from("customers").insert({
id: user.id,
stripe_customer_id: existingCustomer.id,
});
if (error) {
return new Response(
JSON.stringify({ error: error.message }),
{
status: 500,
headers: { "Content-Type": "application/json", ...headers },
},
);
}
customerData = {
id: user.id,
stripe_customer_id: existingCustomer.id,
};
} else {
// create a new customer on stripe since one doesn't exist
const stripeCustomer = await stripe.customers.create({
email: user.email,
});
console.log({ stripeCustomer });
// insert the customer into the database
const { error } = await serviceSupabase.from("customers").insert({
id: user.id,
stripe_customer_id: stripeCustomer.id,
});
if (error) {
return new Response(
JSON.stringify({ error: error.message }),
{
status: 500,
headers: { "Content-Type": "application/json", ...headers },
},
);
}
customerData = {
id: user.id,
stripe_customer_id: stripeCustomer.id,
};
}
}
const session = await stripe.checkout.sessions.create({
line_items: [{
price,
quantity: 1,
}],
invoice_creation: {
enabled: true,
},
mode: "payment",
success_url: SUCCESS_REDIRECT_URL,
cancel_url: CANCEL_REDIRECT_URL,
automatic_tax: { enabled: false },
allow_promotion_codes: true,
customer: customerData?.stripe_customer_id as string | undefined,
});
return new Response(
JSON.stringify({ url: session.url }),
{ headers: { "Content-Type": "application/json", ...headers } },
);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment