mirror of
https://github.com/jcreek/SvelteKitSaasBoilerplate.git
synced 2026-07-16 12:33:49 +00:00
feat(#32): Add separate flow for subscriptions
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
import { type RequestHandler, redirect } from '@sveltejs/kit';
|
||||
import { stripe as stripeClient } from '$lib/utils/stripe';
|
||||
|
||||
// Create a subscription checkout session
|
||||
export const POST: RequestHandler = async ({ request, cookies, locals: { safeGetSession } }) => {
|
||||
const { session } = await safeGetSession();
|
||||
|
||||
if (!session) {
|
||||
// If no session is found, the user isn't authenticated, so block the action
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
||||
const userId = session.user.id;
|
||||
|
||||
// Get the price ID from the request body
|
||||
const { priceId } = await request.json();
|
||||
|
||||
if (!priceId) {
|
||||
return new Response('Price ID is required', { status: 400 });
|
||||
}
|
||||
|
||||
// Create a subscription checkout session with Stripe
|
||||
const checkoutSession = await stripeClient.checkout.sessions.create({
|
||||
line_items: [
|
||||
{
|
||||
price: priceId,
|
||||
quantity: 1
|
||||
}
|
||||
],
|
||||
mode: 'subscription',
|
||||
success_url: `${request.headers.get('origin')}/checkout/success`,
|
||||
cancel_url: `${request.headers.get('origin')}/checkout/cancelled`,
|
||||
metadata: {
|
||||
userId: userId
|
||||
}
|
||||
});
|
||||
|
||||
// Store the checkout session.id for access from the frontend
|
||||
cookies.set('checkout_session_id', checkoutSession.id, { path: '/' });
|
||||
return redirect(303, checkoutSession.url as string);
|
||||
};
|
||||
@@ -44,6 +44,20 @@
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
function startSubscription() {
|
||||
fetch('/api/subscribe', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ priceId: item.priceId })
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
console.log(data);
|
||||
});
|
||||
}
|
||||
|
||||
let item = {};
|
||||
|
||||
onMount(() => {
|
||||
@@ -58,7 +72,8 @@
|
||||
imgSrc: product.images[0],
|
||||
price: 0,
|
||||
priceId: product.default_price,
|
||||
quantity: 1
|
||||
quantity: 1,
|
||||
isSubscription: product.isSubscription
|
||||
};
|
||||
|
||||
// Fetch the price of the product
|
||||
@@ -301,6 +316,7 @@
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
{#if !item.isSubscription}
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3 py-8">
|
||||
<div class="flex sm:items-center sm:justify-center w-full">
|
||||
<button
|
||||
@@ -392,8 +408,9 @@
|
||||
Add to basket</button
|
||||
>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex items-center gap-3">
|
||||
<button
|
||||
<!-- <button
|
||||
class="group transition-all duration-500 p-4 rounded-full bg-indigo-50 hover:bg-indigo-100 hover:shadow-sm hover:shadow-indigo-300"
|
||||
>
|
||||
<svg
|
||||
@@ -412,13 +429,15 @@
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</button> -->
|
||||
<button
|
||||
class="text-center w-full px-5 py-4 rounded-[100px] bg-indigo-600 flex items-center justify-center font-semibold text-lg text-white shadow-sm transition-all duration-500 hover:bg-indigo-700 hover:shadow-indigo-400"
|
||||
on:click={startSubscription}
|
||||
>
|
||||
Buy Now
|
||||
Subscribe
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,5 +4,10 @@ import { stripe as stripeClient } from '$lib/utils/stripe';
|
||||
export const GET = async ({ params }) => {
|
||||
const { productId } = params;
|
||||
const product = await stripeClient.products.retrieve(productId);
|
||||
|
||||
const price = await stripeClient.prices.retrieve(product.default_price);
|
||||
|
||||
const isSubscription = price.type === 'recurring';
|
||||
product.isSubscription = isSubscription;
|
||||
return json(product);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user