cre-sync/lib/stripe/checkout.ts
BusyBee3333 4e6467ffb0 Add CRESync CRM application with Setup page
- Build complete Next.js CRM for commercial real estate
- Add authentication with JWT sessions and role-based access
- Add GoHighLevel API integration for contacts, conversations, opportunities
- Add AI-powered Control Center with tool calling
- Add Setup page with onboarding checklist (/setup)
- Add sidebar navigation with Setup menu item
- Fix type errors in onboarding API, GHL services, and control center tools
- Add Prisma schema with SQLite for local development
- Add UI components with clay morphism design system

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 17:30:55 -05:00

102 lines
2.4 KiB
TypeScript

import { getStripeClient } from './client';
import { getDFYProduct } from './dfy-products';
import { prisma } from '@/lib/db';
export interface CreateCheckoutParams {
userId: string;
productId: string;
successUrl: string;
cancelUrl: string;
}
export async function createDFYCheckoutSession(params: CreateCheckoutParams) {
const { userId, productId, successUrl, cancelUrl } = params;
const product = getDFYProduct(productId);
if (!product) {
throw new Error(`Invalid product ID: ${productId}`);
}
const user = await prisma.user.findUnique({
where: { id: userId },
select: { email: true, firstName: true, lastName: true },
});
if (!user) {
throw new Error('User not found');
}
const stripe = await getStripeClient();
const session = await stripe.checkout.sessions.create({
mode: 'payment',
customer_email: user.email,
line_items: [
{
price_data: {
currency: 'usd',
product_data: {
name: product.name,
description: product.description,
metadata: {
product_id: productId,
delivery_days: product.deliveryDays.toString(),
},
},
unit_amount: product.priceInCents,
},
quantity: 1,
},
],
metadata: {
user_id: userId,
product_id: productId,
type: 'dfy_service',
},
success_url: successUrl,
cancel_url: cancelUrl,
});
// Create pending DFY request
await prisma.dFYRequest.create({
data: {
userId,
serviceType: productId,
status: 'PENDING_PAYMENT',
stripePaymentId: session.id,
amountPaid: product.priceInCents,
},
});
return session;
}
export async function handleCheckoutComplete(sessionId: string) {
const stripe = await getStripeClient();
const session = await stripe.checkout.sessions.retrieve(sessionId);
if (session.payment_status !== 'paid') {
return { success: false, error: 'Payment not completed' };
}
const userId = session.metadata?.user_id;
const productId = session.metadata?.product_id;
if (!userId || !productId) {
return { success: false, error: 'Missing metadata' };
}
// Update DFY request status
await prisma.dFYRequest.updateMany({
where: {
stripePaymentId: sessionId,
},
data: {
status: 'PAID',
updatedAt: new Date(),
},
});
return { success: true, userId, productId };
}