From 9305d68b5863266511c12f277dac17b20ecabd73 Mon Sep 17 00:00:00 2001 From: Kevin Reber Date: Sat, 23 Nov 2024 23:10:51 -0800 Subject: [PATCH] debugging stripe --- app/routes/api.webhook.ts | 72 ++++++++++++++++++++++++++++++++++++ app/routes/webhook.ts | 78 ++++++++++++++------------------------- 2 files changed, 99 insertions(+), 51 deletions(-) create mode 100644 app/routes/api.webhook.ts diff --git a/app/routes/api.webhook.ts b/app/routes/api.webhook.ts new file mode 100644 index 0000000..e0a88f7 --- /dev/null +++ b/app/routes/api.webhook.ts @@ -0,0 +1,72 @@ +import type { ActionFunction } from "@remix-run/node"; +import { json } from "@remix-run/node"; +import { stripe } from "~/services/stripe.server"; +import { handleStripeEvent } from "~/services/webhook.server"; +import { Logger } from "~/utils/logger.server"; + +// [credit @kiliman to get this webhook working](https://github.com/remix-run/remix/discussions/1978) +// To have this webhook working locally, in another server we must run `stripe listen --forward-to localhost:3000/webhook` (yarn run stripe:listen) +export const action: ActionFunction = async ({ request }) => { + console.log("Webhook endpoint hit!", new Date().toISOString()); + + if (request.method !== "POST") { + return json({ error: "Method not allowed" }, { status: 405 }); + } + + const payload = await request.text(); + const sig = request.headers.get("stripe-signature"); + + if (!sig) { + return json({ error: "No signature" }, { status: 400 }); + } + + try { + Logger.info({ + message: "[api.webhook.ts]: Processing webhook request", + metadata: { + method: request.method, + headers: Object.fromEntries(request.headers.entries()), + signature: sig, + }, + }); + + const event = stripe.webhooks.constructEvent( + payload, + sig, + process.env.STRIPE_WEB_HOOK_SECRET! + ); + + const result = await handleStripeEvent(event.type, event.data, event.id); + + return json( + { success: true, data: result }, + { + status: 200, + headers: { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "POST", + "Access-Control-Allow-Headers": "Content-Type, stripe-signature", + }, + } + ); + } catch (error: unknown) { + Logger.error({ + message: "[api.webhook.ts]: Webhook error", + error: error instanceof Error ? error : new Error(String(error)), + }); + + return json( + { + error: error instanceof Error ? error.message : "Unknown error", + }, + { + status: 400, + headers: { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "POST", + "Access-Control-Allow-Headers": "Content-Type, stripe-signature", + }, + } + ); + } +}; diff --git a/app/routes/webhook.ts b/app/routes/webhook.ts index 52ccb2a..1278633 100644 --- a/app/routes/webhook.ts +++ b/app/routes/webhook.ts @@ -1,60 +1,32 @@ -import type { ActionFunction, MetaFunction } from "@remix-run/node"; +import type { ActionFunction } from "@remix-run/node"; import { json } from "@remix-run/node"; import { stripe } from "~/services/stripe.server"; import { handleStripeEvent } from "~/services/webhook.server"; import { Logger } from "~/utils/logger.server"; -export const meta: MetaFunction = () => { - return [{ title: "Stripe Webhook" }]; -}; - // [credit @kiliman to get this webhook working](https://github.com/remix-run/remix/discussions/1978) // To have this webhook working locally, in another server we must run `stripe listen --forward-to localhost:3000/webhook` (yarn run stripe:listen) export const action: ActionFunction = async ({ request }) => { console.log("Webhook endpoint hit!", new Date().toISOString()); - Logger.info({ - message: "[webhook.ts]: Received webhook request", - metadata: { - method: request.method, - url: request.url, - headers: Object.fromEntries(request.headers.entries()), - timestamp: new Date().toISOString(), - }, - }); - - // Only allow POST requests if (request.method !== "POST") { - Logger.warn({ - message: "[webhook.ts]: Invalid method for webhook", - metadata: { method: request.method }, - }); - return json({ error: "Method not allowed" }, 405); + return json({ error: "Method not allowed" }, { status: 405 }); } const payload = await request.text(); - - Logger.info({ - message: "[webhook.ts]: Payload", - metadata: { payload }, - }); - const sig = request.headers.get("stripe-signature"); if (!sig) { - Logger.warn({ - message: "[webhook.ts]: Missing Stripe signature", - }); - return json({ error: "No signature" }, 400); + return json({ error: "No signature" }, { status: 400 }); } try { Logger.info({ - message: "[webhook.ts]: Constructing Stripe event", + message: "[webhook.ts]: Processing webhook request", metadata: { - signaturePresent: !!sig, - payloadLength: payload.length, - webhookSecretPresent: !!process.env.STRIPE_WEB_HOOK_SECRET, + method: request.method, + headers: Object.fromEntries(request.headers.entries()), + signature: sig, }, }); @@ -64,33 +36,37 @@ export const action: ActionFunction = async ({ request }) => { process.env.STRIPE_WEB_HOOK_SECRET! ); - Logger.info({ - message: "[webhook.ts]: Successfully constructed Stripe event ", - metadata: { - eventType: event.type, - eventId: event.id, - }, - }); - const result = await handleStripeEvent(event.type, event.data, event.id); - return json({ success: true, data: result }); + return json( + { success: true, data: result }, + { + status: 200, + headers: { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "POST", + "Access-Control-Allow-Headers": "Content-Type, stripe-signature", + }, + } + ); } catch (error: unknown) { Logger.error({ message: "[webhook.ts]: Webhook error", error: error instanceof Error ? error : new Error(String(error)), - metadata: { - payload: payload.substring(0, 100) + "...", // Log first 100 chars of payload - }, }); return json( { - errors: [ - { message: error instanceof Error ? error.message : "Unknown error" }, - ], + error: error instanceof Error ? error.message : "Unknown error", }, - 400 + { + status: 400, + headers: { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "POST", + "Access-Control-Allow-Headers": "Content-Type, stripe-signature", + }, + } ); } };