|
| 1 | +import { buffer, stripe } from "@/lib/stripe"; |
| 2 | +import { NextRequest } from "next/server"; |
| 3 | + |
| 4 | +export const config = { |
| 5 | + api: { |
| 6 | + bodyParser: false, |
| 7 | + }, |
| 8 | +}; |
| 9 | + |
| 10 | +export async function POST(req : NextRequest){ |
| 11 | + const sig = req.headers.get("stripe-signature") |
| 12 | + const wh_sec = process.env.STRIPE_WEBHOOK_SECRET |
| 13 | + let event: Stripe.Event; |
| 14 | + if (!sig){ |
| 15 | + throw new Error("Invalid Signature") |
| 16 | + } |
| 17 | + try { |
| 18 | + const body = Uint8Array.from(await buffer(req)) as Buffer<ArrayBufferLike> |
| 19 | + event = stripe.webhooks.constructEvent(body, sig!, wh_sec) |
| 20 | + } |
| 21 | + catch (err : any){ |
| 22 | + console.log(`❌ Error message: ${err.message}`); |
| 23 | + return new Response(`Webhook Error: ${err.message}`, {status : 400}) |
| 24 | + } |
| 25 | + console.log('✅ Success:', event.id); |
| 26 | + |
| 27 | + // Cast event data to Stripe object |
| 28 | + if (event.type === 'payment_intent.succeeded') { |
| 29 | + const stripeObject: Stripe.PaymentIntent = event.data |
| 30 | + .object as Stripe.PaymentIntent; |
| 31 | + console.log(`💰 PaymentIntent status: ${stripeObject.status}`); |
| 32 | + } else if (event.type === 'charge.succeeded') { |
| 33 | + const charge = event.data.object as Stripe.Charge; |
| 34 | + console.log(`💵 Charge id: ${charge.id}`); |
| 35 | + } else { |
| 36 | + console.warn(`🤷♀️ Unhandled event type: ${event.type}`); |
| 37 | + } |
| 38 | + |
| 39 | + // Return a response to acknowledge receipt of the event |
| 40 | + return Response.json({received: true}, {status : 200}); |
| 41 | +} |
| 42 | + |
| 43 | +const buffer = async(req: NextRequest) => { |
| 44 | + const body = req.body; |
| 45 | + if (!body) { |
| 46 | + throw new Error('Request body is null'); |
| 47 | + } |
| 48 | + const reader = body.getReader(); |
| 49 | + const chunks = []; |
| 50 | + let done, value; |
| 51 | + while ({ done, value } = await reader.read(), !done) { |
| 52 | + chunks.push(value); |
| 53 | + } |
| 54 | + const buf = new Uint8Array(chunks.reduce((acc, chunk) => acc + chunk.length, 0)); |
| 55 | + let offset = 0; |
| 56 | + for (const chunk of chunks) { |
| 57 | + buf.set(chunk, offset); |
| 58 | + offset += chunk.length; |
| 59 | + } |
| 60 | + return buf; |
| 61 | +}; |
0 commit comments