const Paystack = require('paystack-node'); export class PaystackService { private paystack: any; private initialized: boolean = false; private initialize() { if (this.initialized) { return; } const secretKey = process.env.PAYSTACK_SECRET_KEY; if (!secretKey) { throw new Error('PAYSTACK_SECRET_KEY not configured'); } const environment = process.env.NODE_ENV === 'production' ? 'production' : 'development'; this.paystack = new Paystack(secretKey, environment); this.initialized = true; } async initializeTransaction(data: { email: string; amount: number; // Amount in kobo (NGN) or smallest currency unit reference: string; metadata?: Record; callback_url?: string; }) { this.initialize(); try { const payload: any = { email: data.email, amount: data.amount, reference: data.reference, }; if (data.metadata) { payload.metadata = JSON.stringify(data.metadata); } if (data.callback_url) { payload.callback_url = data.callback_url; } const response = await this.paystack.initializeTransaction(payload); // paystack-node returns response.body.data const responseData = response.body.data; return { authorization_url: responseData.authorization_url, access_code: responseData.access_code, reference: responseData.reference, }; } catch (error: any) { console.error('Paystack initialize error:', error); throw new Error(`Failed to initialize transaction: ${error.message || 'Unknown error'}`); } } /** * Verify transaction by reference */ async verifyTransaction(reference: string) { this.initialize(); try { const response = await this.paystack.verifyTransaction({ reference: reference, }); // paystack-node returns response.body.data const responseData = response.body.data; // Parse metadata if it's a string (paystack-node may return it as JSON string) let metadata = responseData.metadata; if (typeof metadata === 'string') { try { metadata = JSON.parse(metadata); } catch (e) { // If parsing fails, keep as string } } return { status: responseData.status, reference: responseData.reference, amount: responseData.amount, currency: responseData.currency, customer: responseData.customer, metadata: metadata, paidAt: responseData.paid_at, gatewayResponse: responseData.gateway_response, channel: responseData.channel, }; } catch (error: any) { console.error('Paystack verify error:', error); throw new Error(`Failed to verify transaction: ${error.message || 'Unknown error'}`); } } /** * Get public key for frontend */ getPublicKey(): string { const publicKey = process.env.PAYSTACK_PUBLIC_KEY; if (!publicKey) { throw new Error('PAYSTACK_PUBLIC_KEY not configured'); } return publicKey; } /** * Check if Paystack is configured */ isConfigured(): boolean { return !!(process.env.PAYSTACK_SECRET_KEY && process.env.PAYSTACK_PUBLIC_KEY); } }