initial commit: rocket.new export of broadcastbeat
This commit is contained in:
100
src/app/api/webhooks/stripe/jtr/route.ts
Normal file
100
src/app/api/webhooks/stripe/jtr/route.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { createClient } from '@supabase/supabase-js';
|
||||
|
||||
const supabase = createClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
||||
{ db: { schema: process.env.NEXT_PUBLIC_SUPABASE_SCHEMA || 'bb' } }
|
||||
);
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
const body = await req.text();
|
||||
|
||||
let event: any;
|
||||
try {
|
||||
event = JSON.parse(body);
|
||||
} catch {
|
||||
return NextResponse.json({ error: 'Invalid payload' }, { status: 400 });
|
||||
}
|
||||
|
||||
try {
|
||||
await handleStripeEvent(event, 'jtr');
|
||||
return NextResponse.json({ received: true });
|
||||
} catch (err: any) {
|
||||
console.error('[Stripe JTR Webhook]', err.message);
|
||||
return NextResponse.json({ error: err.message }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
async function handleStripeEvent(event: any, company: 'rmp' | 'jtr') {
|
||||
const data = event?.data?.object;
|
||||
|
||||
switch (event.type) {
|
||||
case 'payment_intent.succeeded': {
|
||||
const piId = data?.id;
|
||||
if (piId) {
|
||||
const { data: inv } = await supabase
|
||||
.from('billing_invoices')
|
||||
.select('id')
|
||||
.eq('stripe_payment_link', piId)
|
||||
.single();
|
||||
if (inv) {
|
||||
await supabase.from('billing_invoices').update({
|
||||
status: 'paid',
|
||||
amount_paid: data.amount_received / 100,
|
||||
paid_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString(),
|
||||
}).eq('id', inv.id);
|
||||
|
||||
await supabase.from('billing_payments').insert({
|
||||
invoice_id: inv.id,
|
||||
amount: data.amount_received / 100,
|
||||
payment_date: new Date().toISOString().split('T')[0],
|
||||
payment_method: 'stripe',
|
||||
stripe_payment_intent_id: piId,
|
||||
status: 'succeeded',
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'payment_intent.payment_failed': {
|
||||
await supabase.from('billing_payments').insert({
|
||||
amount: (data?.amount || 0) / 100,
|
||||
payment_date: new Date().toISOString().split('T')[0],
|
||||
payment_method: 'stripe',
|
||||
stripe_payment_intent_id: data?.id,
|
||||
status: 'failed',
|
||||
notes: data?.last_payment_error?.message || 'Payment failed',
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case 'charge.dispute.created': {
|
||||
await supabase.from('billing_payments').insert({
|
||||
amount: (data?.amount || 0) / 100,
|
||||
payment_date: new Date().toISOString().split('T')[0],
|
||||
payment_method: 'stripe',
|
||||
stripe_charge_id: data?.id,
|
||||
status: 'disputed',
|
||||
notes: `Dispute created: ${data?.reason || 'unknown reason'}`,
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case 'payout.paid': {
|
||||
await supabase.from('billing_sync_log').insert({
|
||||
sync_type: `stripe_payout_${company}`,
|
||||
records_synced: 1,
|
||||
status: 'completed',
|
||||
started_at: new Date().toISOString(),
|
||||
completed_at: new Date().toISOString(),
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
106
src/app/api/webhooks/stripe/rmp/route.ts
Normal file
106
src/app/api/webhooks/stripe/rmp/route.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { createClient } from '@supabase/supabase-js';
|
||||
|
||||
const supabase = createClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
||||
{ db: { schema: process.env.NEXT_PUBLIC_SUPABASE_SCHEMA || 'bb' } }
|
||||
);
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
const body = await req.text();
|
||||
const sig = req.headers.get('stripe-signature') || '';
|
||||
|
||||
// Stripe signature verification would go here when STRIPE_SECRET_KEY_RMP is configured
|
||||
// For now, parse the raw event
|
||||
let event: any;
|
||||
try {
|
||||
event = JSON.parse(body);
|
||||
} catch {
|
||||
return NextResponse.json({ error: 'Invalid payload' }, { status: 400 });
|
||||
}
|
||||
|
||||
try {
|
||||
await handleStripeEvent(event, 'rmp');
|
||||
return NextResponse.json({ received: true });
|
||||
} catch (err: any) {
|
||||
console.error('[Stripe RMP Webhook]', err.message);
|
||||
return NextResponse.json({ error: err.message }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
async function handleStripeEvent(event: any, company: 'rmp' | 'jtr') {
|
||||
const data = event?.data?.object;
|
||||
|
||||
switch (event.type) {
|
||||
case 'payment_intent.succeeded': {
|
||||
const piId = data?.id;
|
||||
if (piId) {
|
||||
// Find invoice by stripe payment intent and mark paid
|
||||
const { data: inv } = await supabase
|
||||
.from('billing_invoices')
|
||||
.select('id')
|
||||
.eq('stripe_payment_link', piId)
|
||||
.single();
|
||||
if (inv) {
|
||||
await supabase.from('billing_invoices').update({
|
||||
status: 'paid',
|
||||
amount_paid: data.amount_received / 100,
|
||||
paid_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString(),
|
||||
}).eq('id', inv.id);
|
||||
|
||||
await supabase.from('billing_payments').insert({
|
||||
invoice_id: inv.id,
|
||||
amount: data.amount_received / 100,
|
||||
payment_date: new Date().toISOString().split('T')[0],
|
||||
payment_method: 'stripe',
|
||||
stripe_payment_intent_id: piId,
|
||||
status: 'succeeded',
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'payment_intent.payment_failed': {
|
||||
// Log failed payment — dashboard will show in red
|
||||
await supabase.from('billing_payments').insert({
|
||||
amount: (data?.amount || 0) / 100,
|
||||
payment_date: new Date().toISOString().split('T')[0],
|
||||
payment_method: 'stripe',
|
||||
stripe_payment_intent_id: data?.id,
|
||||
status: 'failed',
|
||||
notes: data?.last_payment_error?.message || 'Payment failed',
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case 'charge.dispute.created': {
|
||||
// Log dispute — urgent alert
|
||||
await supabase.from('billing_payments').insert({
|
||||
amount: (data?.amount || 0) / 100,
|
||||
payment_date: new Date().toISOString().split('T')[0],
|
||||
payment_method: 'stripe',
|
||||
stripe_charge_id: data?.id,
|
||||
status: 'disputed',
|
||||
notes: `Dispute created: ${data?.reason || 'unknown reason'}`,
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case 'payout.paid': {
|
||||
await supabase.from('billing_sync_log').insert({
|
||||
sync_type: `stripe_payout_${company}`,
|
||||
records_synced: 1,
|
||||
status: 'completed',
|
||||
started_at: new Date().toISOString(),
|
||||
completed_at: new Date().toISOString(),
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user