67 lines
2.2 KiB
TypeScript

import { NextResponse } from 'next/server';
import { cookies } from 'next/headers';
import { jwtVerify } from 'jose';
import Stripe from 'stripe';
import { prisma } from '@/lib/prisma';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
apiVersion: '2026-03-25.dahlia' as any,
});
async function verifyAdmin() {
const cookieStore = await cookies();
const token = cookieStore.get('admin_token')?.value;
if (!token) return false;
const jwtSecret = process.env.ADMIN_JWT_SECRET;
if (!jwtSecret) return false;
try {
await jwtVerify(token, new TextEncoder().encode(jwtSecret));
return true;
} catch {
return false;
}
}
// POST /api/admin/sync-orders/
// Fetches recent PaymentIntents from Stripe and upserts them into the DB
export async function POST() {
if (!(await verifyAdmin())) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
try {
const list = await stripe.paymentIntents.list({ limit: 100 });
let synced = 0;
for (const pi of list.data) {
if (pi.status !== 'succeeded' && pi.status !== 'canceled') continue;
const m = pi.metadata ?? {};
const data = {
amount: pi.amount,
currency: pi.currency,
status: pi.status,
customerName: m.customerName ?? null,
customerEmail: m.customerEmail ?? pi.receipt_email ?? null,
customerPhone: m.customerPhone ?? null,
customerAddress: m.customerAddress ?? null,
customerCity: m.customerCity ?? null,
customerCountry: m.customerCountry ?? null,
customerPostalCode: m.customerPostalCode ?? null,
persona: m.persona ?? null,
color: m.color ?? null,
priceItems: m.priceItems ?? null,
};
await prisma.order.upsert({
where: { paymentIntentId: pi.id },
create: { paymentIntentId: pi.id, ...data },
update: data,
});
synced++;
}
return NextResponse.json({ synced });
} catch (err) {
const message = err instanceof Error ? err.message : 'Sync failed';
return NextResponse.json({ error: message }, { status: 500 });
}
}