mirror of
https://github.com/jcreek/SvelteKitSaasBoilerplate.git
synced 2026-07-12 18:43:50 +00:00
feat(#31): Add ability to record the stripe customer id in the customers table when a purchase is made
This commit is contained in:
@@ -110,6 +110,31 @@ const createCustomerInStripe = async (uuid: string, email: string) => {
|
||||
return newCustomer.id;
|
||||
};
|
||||
|
||||
const getStripeCustomerId = async (email: string, uuid: string) => {
|
||||
const { data: existingSupabaseCustomer, error: queryError } = await supabaseAdmin
|
||||
.from('customers')
|
||||
.select('*')
|
||||
.eq('id', uuid)
|
||||
.maybeSingle();
|
||||
|
||||
if (queryError) {
|
||||
throw new Error(`Supabase customer lookup failed: ${queryError.message}`);
|
||||
}
|
||||
|
||||
let stripeCustomerId: string | undefined;
|
||||
if (existingSupabaseCustomer?.stripe_customer_id) {
|
||||
const existingStripeCustomer = await stripeClient.customers.retrieve(
|
||||
existingSupabaseCustomer.stripe_customer_id
|
||||
);
|
||||
stripeCustomerId = existingStripeCustomer.id;
|
||||
} else {
|
||||
const stripeCustomers = await stripeClient.customers.list({ email: email });
|
||||
stripeCustomerId = stripeCustomers.data.length > 0 ? stripeCustomers.data[0].id : undefined;
|
||||
}
|
||||
|
||||
return stripeCustomerId;
|
||||
};
|
||||
|
||||
const createOrRetrieveCustomer = async ({ email, uuid }: { email: string; uuid: string }) => {
|
||||
// Check if the customer already exists in Supabase
|
||||
const { data: existingSupabaseCustomer, error: queryError } = await supabaseAdmin
|
||||
@@ -453,5 +478,7 @@ export {
|
||||
addCredits,
|
||||
deductCredits,
|
||||
getUserCredits,
|
||||
getActiveProductsWithPrices
|
||||
getActiveProductsWithPrices,
|
||||
upsertCustomerToSupabase,
|
||||
getStripeCustomerId
|
||||
};
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { type RequestHandler, redirect } from '@sveltejs/kit';
|
||||
import { stripe as stripeClient } from '$lib/utils/stripe';
|
||||
import { getStripeCustomerId } from '$lib/utils/supabase/admin';
|
||||
import type Stripe from 'stripe';
|
||||
|
||||
// Create a checkout session
|
||||
export const POST: RequestHandler = async ({ request, cookies, locals: { safeGetSession } }) => {
|
||||
@@ -26,9 +28,16 @@ export const POST: RequestHandler = async ({ request, cookies, locals: { safeGet
|
||||
quantity: item.quantity
|
||||
}));
|
||||
|
||||
const checkoutSession = await stripeClient.checkout.sessions.create({
|
||||
customer_creation: 'always',
|
||||
customer_email: userEmail,
|
||||
let stripeCustomerId = null;
|
||||
|
||||
// Get the existing Stripe customer ID from Supabase, if it exists
|
||||
try {
|
||||
stripeCustomerId = await getStripeCustomerId(userEmail!, userId);
|
||||
} catch (error) {
|
||||
console.error('Error fetching Stripe customer ID:', error);
|
||||
}
|
||||
|
||||
const stripeCheckoutSessionObject = {
|
||||
line_items: lineItems,
|
||||
mode: 'payment',
|
||||
success_url: `${request.headers.get('origin')}/checkout/success`,
|
||||
@@ -36,7 +45,18 @@ export const POST: RequestHandler = async ({ request, cookies, locals: { safeGet
|
||||
metadata: {
|
||||
userId: userId
|
||||
}
|
||||
});
|
||||
} as Stripe.Checkout.SessionCreateParams;
|
||||
|
||||
if (stripeCustomerId) {
|
||||
// If the user has a Stripe customer ID, attach it to the checkout session
|
||||
stripeCheckoutSessionObject.customer = stripeCustomerId;
|
||||
} else {
|
||||
// If the user doesn't have a Stripe customer ID, create a new customer
|
||||
stripeCheckoutSessionObject.customer_creation = 'always';
|
||||
stripeCheckoutSessionObject.customer_email = userEmail;
|
||||
}
|
||||
|
||||
const checkoutSession = await stripeClient.checkout.sessions.create(stripeCheckoutSessionObject);
|
||||
|
||||
// Store the checkout session.id for access from the frontend
|
||||
cookies.set('checkout_session_id', checkoutSession.id, { path: '/' });
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { json } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from './$types';
|
||||
import { upsertCustomerToSupabase } from '$lib/utils/supabase/admin';
|
||||
|
||||
export const GET: RequestHandler = async ({ url, locals: { safeGetSession } }) => {
|
||||
const stripeCustomerId = url.searchParams.get('stripeCustomerId');
|
||||
const { session } = await safeGetSession();
|
||||
|
||||
if (!session || !stripeCustomerId) {
|
||||
return json({ error: 'Unauthorized' }, { status: 401 });
|
||||
}
|
||||
|
||||
await upsertCustomerToSupabase(session?.user.id, stripeCustomerId);
|
||||
|
||||
return json({ message: 'Customer created' });
|
||||
};
|
||||
@@ -2,8 +2,8 @@ import type { PageLoad } from './$types';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import Stripe from 'stripe';
|
||||
|
||||
export const load: PageLoad = async ({fetch}) => {
|
||||
const response = await fetch('/api/checkout/status');
|
||||
export const load: PageLoad = async ({ fetch }) => {
|
||||
const response = await fetch('/api/checkout/status');
|
||||
if (!response.ok) {
|
||||
console.error('Failed to fetch checkout status');
|
||||
return;
|
||||
@@ -18,10 +18,19 @@ export const load: PageLoad = async ({fetch}) => {
|
||||
throw redirect(303, '/checkout/cancelled');
|
||||
}
|
||||
|
||||
// Save the stripe customer id in the customers table
|
||||
const stripeCustomerId = checkoutSession.customer as string;
|
||||
console.log('stripeCustomerId', stripeCustomerId);
|
||||
const createCustomerResponse = await fetch(
|
||||
'/api/checkout/create-customer?stripeCustomerId=' + stripeCustomerId
|
||||
);
|
||||
if (!createCustomerResponse.ok) {
|
||||
console.error('Failed to create customer');
|
||||
}
|
||||
|
||||
return {
|
||||
checkoutSession,
|
||||
lineItems,
|
||||
paymentStatus
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user