diff --git a/apps/dashboard/app/api/webhooks/stripe/route.ts b/apps/dashboard/app/api/webhooks/stripe/route.ts index 8c552dde71..7a78e94f06 100644 --- a/apps/dashboard/app/api/webhooks/stripe/route.ts +++ b/apps/dashboard/app/api/webhooks/stripe/route.ts @@ -73,10 +73,70 @@ export const POST = async (req: Request): Promise => { }); break; } + case "customer.subscription.created": { + const sub = event.data.object as Stripe.Subscription; + + // Only handle trial subscriptions + if (!sub.trial_end) { + return new Response("OK"); + } + + // Get product and price information + const price = await stripe.prices.retrieve(sub.items.data[0].price.id); + const product = await stripe.products.retrieve(price.product as string); + const customer = (await stripe.customers.retrieve(sub.customer as string)) as Stripe.Customer; + + const formattedPrice = new Intl.NumberFormat("en-US", { + style: "currency", + currency: "USD", + }).format(price.unit_amount! / 100); + + await alertSlack(product.name, formattedPrice, customer.email!, customer.name!); + break; + } default: - console.error("Incoming stripe event, that should not be received", event.type); + console.warn("Incoming stripe event, that should not be received", event.type); break; } return new Response("OK"); }; + +async function alertSlack( + product: string, + price: string, + email: string, + name?: string, +): Promise { + const url = process.env.SLACK_WEBHOOK_CUSTOMERS; + if (!url) { + return; + } + + await fetch(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + blocks: [ + { + type: "section", + text: { + type: "mrkdwn", + text: `:bugeyes: New customer ${name} signed up for a two week trial`, + }, + }, + { + type: "section", + text: { + type: "mrkdwn", + text: `A new trial for the ${product} tier has started at a price of ${price} by ${email} :moneybag: `, + }, + }, + ], + }), + }).catch((err: Error) => { + console.error(err); + }); +}