Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 4x 4x 1x 1x 1x 1x 4x 4x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 4x 4x 7x 7x 7x 7x 7x 6x 11x 1x 1x 5x 11x 1x 1x 4x 4x 4x 4x 4x 4x 4x 4x 3x 3x 3x 3x 3x 3x 1x 1x | import { NextRequest, NextResponse } from 'next/server';
import {
withAuth,
withErrorHandling,
successResponse,
ApiError,
ApiSuccessResponse,
ApiErrorResponse } from "@/lib/api";
import { RouteContext } from "@/lib/api/middleware";
import { prisma } from "@/lib/prisma";
import Stripe from "stripe";
import { z } from "zod";
import { Session } from "next-auth";
// Lazy initialization to avoid build-time errors when STRIPE_SECRET_KEY is not set
let stripeClient: Stripe | null = null;
function getStripe(): Stripe {
if (!stripeClient) {
const key = process.env.STRIPE_SECRET_KEY;
if (!key) {
throw new Error("STRIPE_SECRET_KEY is not configured");
}
stripeClient = new Stripe(key);
}
return stripeClient;
}
const IntentSchema = z.object({
orderId: z.number(),
amount: z.number().positive()});
// Response type
interface PaymentIntentResponse {
clientSecret: string | null;
amount: number;
orderId: number;
}
// POST /api/payments/create-intent - Create Stripe payment intent
async function handlePost(
request: NextRequest,
_context: RouteContext | undefined,
session: Session
): Promise<NextResponse<ApiSuccessResponse<PaymentIntentResponse> | ApiErrorResponse>> {
const body = await request.json();
// Validate input
const validationResult = IntentSchema.safeParse(body);
if (!validationResult.success) {
throw ApiError.validation("Invalid data", validationResult.error.issues);
}
const validatedData = validationResult.data;
// Verify order exists and belongs to user
const order = await prisma.order.findUnique({
where: { id: validatedData.orderId }});
if (!order) {
throw ApiError.notFound("Order", validatedData.orderId);
}
if (order.userId !== session.user.id) {
throw ApiError.forbidden("You do not have access to this order");
}
// Create Stripe payment intent
const paymentIntent = await getStripe().paymentIntents.create({
amount: Math.round(validatedData.amount * 100), // Convert to cents
currency: "usd",
metadata: {
orderId: validatedData.orderId.toString(),
userId: session.user.id.toString()}});
return successResponse({
clientSecret: paymentIntent.client_secret,
amount: validatedData.amount,
orderId: validatedData.orderId});
}
export const POST = withErrorHandling(withAuth(handlePost));
|