UNPKG

quickpos

Version:

<div align="center"> <h1>💳 QuickPos 🚀</h1> <p><strong>A powerful, multi-gateway payment integration module for Node.js</strong></p> <p>Seamlessly integrate with 50+ payment providers worldwide</p>

195 lines (163 loc) • 6.54 kB
const { FedaPay, Transaction, Customer } = require('fedapay'); class FedaPayClient { constructor(config) { this.config = config || {}; const requiredFields = ['apiKey', 'environment']; for (let field of requiredFields) { if (!config[field]) throw new Error(`Missing required field: ${field}`); } // Initialize FedaPay client FedaPay.setApiKey(config.apiKey); FedaPay.setEnvironment(config.environment || 'sandbox'); // sandbox or live // Optional configuration if (config.accountId) FedaPay.setAccountId(config.accountId); this.debug = config.debug || false; } async createPayment(paymentDetails) { try { // Validate required fields const requiredData = ['amount', 'currency', 'description']; for (let data of requiredData) { if (!paymentDetails[data]) throw new Error(`Missing required data: ${data}`); } if (this.debug) console.log('Creating payment with details:', paymentDetails); // Prepare customer data if available let customer = null; if (paymentDetails.email || paymentDetails.firstName || paymentDetails.lastName || paymentDetails.phone) { customer = { email: paymentDetails.email, firstname: paymentDetails.firstName || paymentDetails.name, lastname: paymentDetails.lastName || paymentDetails.surname }; // Format phone number correctly according to FedaPay API if (paymentDetails.phone) { customer.phone_number = { number: paymentDetails.phone, country: paymentDetails.phoneCountry || 'BJ' // Default to Benin if not specified }; } } // Create transaction data const transactionData = { description: paymentDetails.description, amount: paymentDetails.amount, currency: { iso: paymentDetails.currency }, callback_url: paymentDetails.callbackUrl || paymentDetails.notificationUrl, reference: paymentDetails.orderId || `order-${Date.now()}` }; // Add payment mode if specified (mtn, moov, etc.) if (paymentDetails.mode) { transactionData.mode = paymentDetails.mode; } // Add customer if exists if (customer) { transactionData.customer = customer; } // Create transaction const transaction = await Transaction.create(transactionData); if (this.debug) console.log('Transaction created:', transaction); // Correct way to generate payment URL using the Transaction class directly // We need to retrieve the transaction first to use generateToken method const retrievedTransaction = await Transaction.retrieve(transaction.id); const tokenData = await retrievedTransaction.generateToken({ return_url: paymentDetails.returnUrl || paymentDetails.successUrl, cancel_url: paymentDetails.cancelUrl || paymentDetails.failUrl }); if (this.debug) console.log('Payment token generated:', tokenData); // Extract the token and URL from the response const paymentUrl = tokenData.url; const token = tokenData.token; return { status: 'success', data: { id: transaction.id, transactionId: transaction.id, reference: transaction.reference, url: paymentUrl, token: token } }; } catch (error) { if (this.debug) console.error('FedaPay payment creation error:', error); return { status: 'fail', message: error.message || 'Unknown error' }; } } async handleCallback(callbackData) { try { if (this.debug) console.log('Processing callback data:', callbackData); // FedaPay webhook data structure may vary, adjust as needed const transactionId = callbackData.id || callbackData.transaction_id; if (!transactionId) { throw new Error('Invalid callback data: missing transaction ID'); } // Retrieve the transaction to verify its status const transaction = await Transaction.retrieve(transactionId); if (this.debug) console.log('Retrieved transaction:', transaction); if (transaction && transaction.status === 'approved') { return { status: 'success', transactionId: transaction.id, orderId: transaction.reference, amount: transaction.amount, currency: transaction.currency.iso, paymentDate: transaction.approved_at || transaction.updated_at, paymentMethod: transaction.mode || 'unknown' }; } else { throw new Error(`Payment failed with status: ${transaction?.status || 'unknown'}`); } } catch (error) { if (this.debug) console.error('Callback handling error:', error); throw new Error(`Error in FedaPay callback handling: ${error.message}`); } } // Additional utility methods async getTransaction(transactionId) { try { const transaction = await Transaction.retrieve(transactionId); return { status: 'success', data: transaction }; } catch (error) { if (this.debug) console.error('Get transaction error:', error); return { status: 'fail', message: error.message }; } } async listTransactions(params = {}) { try { const transactions = await Transaction.all(params); return { status: 'success', data: transactions }; } catch (error) { if (this.debug) console.error('List transactions error:', error); return { status: 'fail', message: error.message }; } } async verifySignature(payload, signature, key = null) { try { // Use provided key or default to API key const secretKey = key || this.config.apiKey; // Implementation depends on FedaPay's webhook signature verification method // This is a placeholder - adjust according to FedaPay's actual verification method return FedaPay.Webhook.verifySignature(payload, signature, secretKey); } catch (error) { if (this.debug) console.error('Signature verification error:', error); return false; } } } module.exports = FedaPayClient;