From d4f7f5041d79ee796018ac71b686979abe44f21a Mon Sep 17 00:00:00 2001 From: Josh Creek <8179928+jcreek@users.noreply.github.com> Date: Sat, 21 Sep 2024 19:55:10 +0100 Subject: [PATCH] feat(#29): Add ability to record that a user has purchased a product - part 1 --- README.md | 2 ++ src/routes/api/checkout/+server.ts | 22 +++++++++++++++++----- src/routes/api/webhook/stripe/+server.ts | 11 +++++++---- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index b927add..62a8574 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,8 @@ If you want a fully local development environment (other than stripe) then you c - [Local DB Url](http://localhost:54323/) - [Local Email Monitoring Url](http://localhost:54324/) +For stripe, you can forward the events to your local server using `stripe listen --forward-to localhost:5173/api/webhook/stripe --skip-verify` in a separate terminal window. + ## Building To create a production version: diff --git a/src/routes/api/checkout/+server.ts b/src/routes/api/checkout/+server.ts index 19c3965..29661e3 100644 --- a/src/routes/api/checkout/+server.ts +++ b/src/routes/api/checkout/+server.ts @@ -2,7 +2,16 @@ import { type RequestHandler, redirect } from '@sveltejs/kit'; import { stripe as stripeClient } from '$lib/utils/stripe'; // Create a checkout session -export const POST: RequestHandler = async ({ request, cookies }) => { +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; + const formData = new URLSearchParams(await request.text()); const items: { priceId: string; quantity: number }[] = []; @@ -16,14 +25,17 @@ export const POST: RequestHandler = async ({ request, cookies }) => { quantity: item.quantity })); - const session = await stripeClient.checkout.sessions.create({ + const checkoutSession = await stripeClient.checkout.sessions.create({ line_items: lineItems, mode: 'payment', success_url: `${request.headers.get('origin')}/checkout/success`, - cancel_url: `${request.headers.get('origin')}/checkout/cancelled` + 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', session.id, { path: '/' }); - return redirect(303, session.url as string); + cookies.set('checkout_session_id', checkoutSession.id, { path: '/' }); + return redirect(303, checkoutSession.url as string); }; diff --git a/src/routes/api/webhook/stripe/+server.ts b/src/routes/api/webhook/stripe/+server.ts index 1e31c00..0e8f3a6 100644 --- a/src/routes/api/webhook/stripe/+server.ts +++ b/src/routes/api/webhook/stripe/+server.ts @@ -1,4 +1,4 @@ -import type { RequestHandler } from '@sveltejs/kit'; +import { json, type RequestHandler } from '@sveltejs/kit'; import stripe from 'stripe'; import { STRIPE_ENDPOINT_SECRET } from '$env/static/private'; import { @@ -71,16 +71,19 @@ export const POST: RequestHandler = async ({ request }) => { checkoutSession.customer as string, true ); + } else if (checkoutSession.mode === 'payment') { + // TODO Record that they purchased the product + console.log(checkoutSession); } break; } default: - console.log(`Unhandled event type ${event.type}`) + console.log(`Unhandled event type ${event.type}`); } } catch (err) { const message = err instanceof Error ? err.message : 'An unknown error has occurred'; return new Response(`Webhook Error: ${message}`, { status: 500 }); } - return json({received: true}) -} + return json({ received: true }); +};