CognxSafeTrack
chore: execute Sprint 38 technical debt resolution (Type Safety, Zod validation, Vitest, Mock LLM extracted)
d9879cf
import Stripe from 'stripe';
export class StripeService {
private stripe: Stripe | null = null;
private webhookSecret: string | null = null;
private clientUrl: string;
constructor() {
const secretKey = process.env.STRIPE_SECRET_KEY;
const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET;
this.webhookSecret = webhookSecret || null;
this.clientUrl = process.env.VITE_CLIENT_URL || 'http://localhost:5174';
if (secretKey) {
this.stripe = new Stripe(secretKey, {
apiVersion: '2025-01-27.acacia' as any,
});
}
}
/**
* Creates a Stripe Checkout Session for a specific track and user.
*/
async createCheckoutSession(userId: string, trackId: string, priceId: string, userPhone: string) {
if (!this.stripe) throw new Error('[StripeService] STRIPE_SECRET_KEY is not configured');
try {
const session = await this.stripe.checkout.sessions.create({
payment_method_types: ['card'],
line_items: [
{
price: priceId,
quantity: 1,
},
],
mode: 'payment',
success_url: `${this.clientUrl}/payment/success?session_id={CHECKOUT_SESSION_ID}&track=${trackId}`,
cancel_url: `${this.clientUrl}/student?cancel=true`,
metadata: {
userId,
trackId,
userPhone
}
});
return session.url;
} catch (error) {
console.error('[StripeService] Failed to create checkout session:', error);
throw error;
}
}
/**
* Verifies the signature of an incoming Stripe webhook.
*/
verifyWebhookSignature(payload: Buffer, signature: string | undefined): Stripe.Event {
if (!this.stripe || !this.webhookSecret) {
throw new Error('[StripeService] Stripe is not configured (missing keys)');
}
if (!signature) {
throw new Error('Missing stripe-signature header');
}
try {
return this.stripe.webhooks.constructEvent(
payload,
signature,
this.webhookSecret
);
} catch (err: unknown) {
throw new Error(`Webhook Error: ${(err instanceof Error ? (err instanceof Error ? err.message : String(err)) : String(err))}`);
}
}
}
export const stripeService = new StripeService();