85 lines
2.8 KiB
TypeScript
85 lines
2.8 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
|
import { stripe } from '@/lib/stripe';
|
|
import { db } from '@/lib/db';
|
|
|
|
const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET!;
|
|
|
|
export async function POST(req: NextRequest) {
|
|
const body = await req.text();
|
|
const sig = req.headers.get('stripe-signature')!;
|
|
|
|
let event;
|
|
|
|
try {
|
|
event = stripe.webhooks.constructEvent(body, sig, webhookSecret);
|
|
} catch (err: any) {
|
|
console.error(`Webhook Error: ${err.message}`);
|
|
return NextResponse.json({ error: `Webhook Error: ${err.message}` }, { status: 400 });
|
|
}
|
|
|
|
const session = event.data.object as any;
|
|
|
|
// Handle the business logic based on event type
|
|
switch (event.type) {
|
|
case 'payment_intent.succeeded':
|
|
await handlePaymentSucceeded(session);
|
|
break;
|
|
case 'payment_intent.payment_failed':
|
|
await handlePaymentFailed(session);
|
|
break;
|
|
default:
|
|
console.log(`Unhandled event type ${event.type}`);
|
|
}
|
|
|
|
return NextResponse.json({ received: true });
|
|
}
|
|
|
|
async function handlePaymentSucceeded(paymentIntent: any) {
|
|
// 1. Update status in our DB
|
|
const result = await db.query(
|
|
'UPDATE transactions SET status = $1 WHERE stripe_pi_id = $2 RETURNING *',
|
|
['succeeded', paymentIntent.id]
|
|
);
|
|
const transaction = result.rows[0];
|
|
|
|
if (!transaction) {
|
|
console.error('Transaction not found for success webhook:', paymentIntent.id);
|
|
return;
|
|
}
|
|
|
|
// 2. If callback_url exists, notify the merchant (firm)
|
|
if (transaction && transaction.callback_url) {
|
|
try {
|
|
console.log(`Sending callback to: ${transaction.callback_url}`);
|
|
|
|
const response = await fetch(transaction.callback_url, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
status: 'success',
|
|
amount: transaction.amount,
|
|
currency: transaction.currency,
|
|
ref_id: transaction.source_ref_id,
|
|
transaction_id: transaction.id,
|
|
stripe_id: transaction.stripe_pi_id,
|
|
customer_name: transaction.customer_name,
|
|
timestamp: new Date().toISOString()
|
|
}),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
console.warn(`Callback failed with status: ${response.status}`);
|
|
}
|
|
} catch (err) {
|
|
console.error('Error sending callback:', err);
|
|
}
|
|
}
|
|
}
|
|
|
|
async function handlePaymentFailed(paymentIntent: any) {
|
|
await db.query(
|
|
'UPDATE transactions SET status = $1 WHERE stripe_pi_id = $2',
|
|
['failed', paymentIntent.id]
|
|
);
|
|
}
|