Merge pull request #39 from jcreek/32-set-up-separate-flow-where-subscriptions-are-done-with-a-button-directly-from-the-product-page-and-cannot-be-added-to-the-basket

feat(#32): Add separate flow for subscriptions
This commit is contained in:
Josh Creek
2024-10-08 20:48:24 +01:00
committed by GitHub
3 changed files with 165 additions and 99 deletions
+41
View File
@@ -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);
};
+23 -4
View File
@@ -44,6 +44,20 @@
}, 5000); }, 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 = {}; let item = {};
onMount(() => { onMount(() => {
@@ -58,7 +72,8 @@
imgSrc: product.images[0], imgSrc: product.images[0],
price: 0, price: 0,
priceId: product.default_price, priceId: product.default_price,
quantity: 1 quantity: 1,
isSubscription: product.isSubscription
}; };
// Fetch the price of the product // Fetch the price of the product
@@ -301,6 +316,7 @@
</div> </div>
</div> --> </div> -->
{#if !item.isSubscription}
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3 py-8"> <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"> <div class="flex sm:items-center sm:justify-center w-full">
<button <button
@@ -392,8 +408,9 @@
Add to basket</button Add to basket</button
> >
</div> </div>
{:else}
<div class="flex items-center gap-3"> <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" 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 <svg
@@ -412,13 +429,15 @@
stroke-linejoin="round" stroke-linejoin="round"
/> />
</svg> </svg>
</button> </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" 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> </button>
</div> </div>
{/if}
</div> </div>
</div> </div>
</div> </div>
@@ -1,8 +1,14 @@
import { json } from '@sveltejs/kit'; import { json } from '@sveltejs/kit';
import { stripe as stripeClient } from '$lib/utils/stripe'; import { stripe as stripeClient } from '$lib/utils/stripe';
import Stripe from 'stripe';
export const GET = async ({ params }) => { export const GET = async ({ params }) => {
const { productId } = params; const { productId } = params;
const product = await stripeClient.products.retrieve(productId); const product = await stripeClient.products.retrieve(productId);
const price = await stripeClient.prices.retrieve(product.default_price);
const isSubscription = price.type === ('recurring' as Stripe.Price.type);
product.isSubscription = isSubscription;
return json(product); return json(product);
}; };