import { type NextRequest, NextResponse } from "next/server"
import Stripe from "stripe"
export const runtime = "edge"
async function sendThankYouEmail(
customerEmail: string,
customerName: string | null,
amount: number,
currency: string,
productName: string
) {
const sendgridApiKey = process.env.SENDGRID_API_KEY?.trim()
if (!sendgridApiKey) {
console.log("⚠️ SENDGRID_API_KEY not configured, skipping email")
return
}
const formattedAmount = new Intl.NumberFormat("en-CA", {
style: "currency",
currency: currency.toUpperCase(),
}).format(amount / 100)
const name = customerName || "Valued Supporter"
try {
const response = await fetch("https://api.sendgrid.com/v3/mail/send", {
method: "POST",
headers: {
"Authorization": `Bearer ${sendgridApiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
personalizations: [
{
to: [{ email: customerEmail, name: name }],
},
],
from: {
email: "noreply@alertbaytrumpeter.com",
name: "Alert Bay Trumpeter",
},
subject: "Thank You for Supporting the Alert Bay Trumpeter!",
content: [
{
type: "text/html",
value: `
Thank You, ${name}!
Your generous support means the world to Jerry Higginson, the Alert Bay Trumpeter.
Subscription Details
Amount: ${formattedAmount}/month
Plan: ${productName}
Your monthly contribution helps Jerry continue spreading smiles at sea by serenading cruise ship passengers with his trumpet.
With over 1,000 nautical serenades since 1996, your support keeps the music playing!
With gratitude,
Jerry Higginson
The Alert Bay Trumpeter
If you have any questions, contact us at alertbaytrumpeter@icloud.com
`,
},
],
}),
})
if (response.ok || response.status === 202) {
console.log(`✅ Thank you email sent to ${customerEmail}`)
} else {
const error = await response.text()
console.error(`❌ Failed to send email: ${error}`)
}
} catch (error) {
console.error("❌ Error sending email:", error)
}
}
export async function POST(request: NextRequest) {
try {
const stripeSecretKey = process.env.STRIPE_SECRET_KEY?.trim()
const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET?.trim()
if (!stripeSecretKey || !webhookSecret) {
return NextResponse.json({ error: "Stripe configuration missing" }, { status: 500 })
}
const stripe = new Stripe(stripeSecretKey, {
apiVersion: "2024-06-20",
})
const body = await request.text()
const signature = request.headers.get("stripe-signature")!
let event: Stripe.Event
try {
event = stripe.webhooks.constructEvent(body, signature, webhookSecret)
} catch (err: any) {
console.log(`⚠️ Webhook signature verification failed.`, err.message)
return NextResponse.json({ error: "Invalid signature" }, { status: 400 })
}
// Handle the event
switch (event.type) {
case "checkout.session.completed":
const session = event.data.object as Stripe.Checkout.Session
console.log(`💰 Payment successful for session: ${session.id}`)
// Send thank you email for subscriptions
if (session.mode === "subscription" && session.customer_details?.email) {
// Get subscription details
const subscriptionId = session.subscription as string
if (subscriptionId) {
const subscription = await stripe.subscriptions.retrieve(subscriptionId)
const item = subscription.items.data[0]
const amount = item.price.unit_amount || 0
const currency = item.price.currency
const productId = item.price.product as string
const product = await stripe.products.retrieve(productId)
await sendThankYouEmail(
session.customer_details.email,
session.customer_details.name,
amount,
currency,
product.name
)
}
}
break
case "customer.subscription.created":
const newSubscription = event.data.object as Stripe.Subscription
console.log(`🎉 New subscription created: ${newSubscription.id}`)
break
case "invoice.paid":
const invoice = event.data.object as Stripe.Invoice
console.log(`💵 Invoice paid: ${invoice.id}`)
break
case "customer.subscription.deleted":
const cancelledSubscription = event.data.object as Stripe.Subscription
console.log(`😢 Subscription cancelled: ${cancelledSubscription.id}`)
break
default:
console.log(`Unhandled event type ${event.type}`)
}
return NextResponse.json({ received: true })
} catch (error: any) {
console.error("Webhook error:", error)
return NextResponse.json({ error: { message: error.message } }, { status: 500 })
}
}