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>

339 lines (295 loc) • 10.6 kB
/** * PrimePayments - JavaScript client for PrimePayments payment service */ class PrimePayments { /** * Create a new PrimePayments client * @param {Object} config - Configuration options * @param {string} config.projectId - Project ID * @param {string} config.secretWord1 - Secret word 1 for signing requests * @param {string} config.secretWord2 - Secret word 2 for verifying notifications * @param {string} config.payoutKey - Key for payout operations */ constructor(config) { this.config = config; this.apiUrl = 'https://pay.primepayments.io/API/v2/'; } /** * Calculate MD5 hash * @param {string} str - Input string * @returns {string} - MD5 hash */ md5(str) { return require('crypto').createHash('md5').update(str).digest('hex'); } /** * Make an API request to PrimePayments * @param {Object} data - Request data * @returns {Promise<Object>} - Response data */ async makeRequest(data) { const queryString = Object.entries(data) .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`) .join('&'); try { const response = await fetch(this.apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: queryString }); const result = await response.json(); return result; } catch (error) { throw new Error(`PrimePayments API request failed: ${error.message}`); } } /** * Initialize a payment and get payment form URL * @param {Object} options - Payment options * @param {number} options.sum - Payment amount * @param {string} options.currency - Payment currency (RUB, UAH, USD, EUR) * @param {string} options.innerID - Internal ID in your system * @param {string} options.email - Customer email * @param {string} [options.payWay] - Preferred payment method (1-cards, 2-Yandex, etc.) * @param {string} [options.comment] - Payment description * @param {boolean} [options.needFailNotice] - Send notification on payment failure * @param {string} [options.lang] - Form language * @param {boolean} [options.strict_payWay] - Force specified payment method * @param {boolean} [options.block_payWay] - Block other payment methods * @param {boolean} [options.directPay] - Direct payment without intermediate page * @returns {Promise<Object>} - Response with payment URL */ async initPayment(options) { const data = { action: 'initPayment', project: this.config.projectId, sum: options.sum, currency: options.currency, innerID: options.innerID, email: options.email, }; if (options.payWay) data.payWay = options.payWay; if (options.comment) data.comment = options.comment; if (options.needFailNotice) data.needFailNotice = options.needFailNotice; if (options.lang) data.lang = options.lang; if (options.strict_payWay) data.strict_payWay = options.strict_payWay; if (options.block_payWay) data.block_payWay = options.block_payWay; if (options.directPay) data.directPay = options.directPay; // Calculate signature let signString = this.config.secretWord1 + data.action + data.project + data.sum + data.currency + data.innerID + data.email; if (data.payWay) signString += data.payWay; data.sign = this.md5(signString); return this.makeRequest(data); } /** * Initialize a payout * @param {Object} options - Payout options * @param {number} options.sum - Payout amount * @param {string} options.currency - Payout currency * @param {string} options.payWay - Payout method * @param {string} options.email - Recipient email * @param {string} options.purse - Card number or wallet * @param {string} [options.comment] - Payout description * @param {string} [options.cardholder] - Card holder name * @param {string} [options.SBP_id] - SBP bank identifier * @param {string} [options.needUnique] - Unique identifier for the payout * @returns {Promise<Object>} - Response with payout ID */ async initPayout(options) { const data = { action: 'initPayout', project: this.config.projectId, sum: options.sum, currency: options.currency, payWay: options.payWay, email: options.email, purse: options.purse }; if (options.comment) data.comment = options.comment; if (options.cardholder) data.cardholder = options.cardholder; if (options.SBP_id) data.SBP_id = options.SBP_id; if (options.needUnique) data.needUnique = options.needUnique; // Calculate signature const signString = this.config.payoutKey + data.action + data.project + data.sum + data.currency + data.payWay + data.email + data.purse; data.sign = this.md5(signString); return this.makeRequest(data); } /** * Get order information * @param {string} orderID - Order ID * @returns {Promise<Object>} - Order information */ async getOrderInfo(orderID) { const data = { action: 'getOrderInfo', project: this.config.projectId, orderID: orderID }; // Calculate signature data.sign = this.md5(this.config.secretWord1 + data.action + data.project + data.orderID); return this.makeRequest(data); } /** * Refund a payment * @param {string} orderID - Order ID to refund * @returns {Promise<Object>} - Refund result */ async refund(orderID) { const data = { action: 'refund', orderID: orderID }; // Calculate signature data.sign = this.md5(this.config.secretWord1 + data.action + data.orderID); return this.makeRequest(data); } /** * Get project balance * @returns {Promise<Object>} - Project balance information */ async getProjectBalance() { const data = { action: 'getProjectBalance', project: this.config.projectId }; // Calculate signature data.sign = this.md5(this.config.secretWord1 + data.action + data.project); return this.makeRequest(data); } /** * Get payout information * @param {string} payoutID - Payout ID * @returns {Promise<Object>} - Payout information */ async getPayoutInfo(payoutID) { const data = { action: 'getPayoutInfo', project: this.config.projectId, payoutID: payoutID }; // Calculate signature data.sign = this.md5(this.config.secretWord1 + data.action + data.project + data.payoutID); return this.makeRequest(data); } /** * Get project information * @returns {Promise<Object>} - Project information and available payment methods */ async getProjectInfo() { const data = { action: 'getProjectInfo', project: this.config.projectId }; // Calculate signature data.sign = this.md5(this.config.secretWord1 + data.action + data.project); return this.makeRequest(data); } /** * Get exchange rates * @returns {Promise<Object>} - Exchange rates information */ async getExchangeRates() { const data = { action: 'getExchangeRates' }; return this.makeRequest(data); } /** * Verify payment notification * @param {Object} postData - POST data from notification * @returns {boolean} - True if signature is valid */ verifyPaymentNotification(postData) { if (postData.action === 'order_payed') { const hash = this.md5(this.config.secretWord2 + postData.orderID + postData.payWay + postData.innerID + postData.sum + postData.webmaster_profit); return hash === postData.sign; } else if (postData.action === 'order_cancel') { const hash = this.md5(this.config.secretWord2 + postData.orderID + postData.innerID); return hash === postData.sign; } return false; } /** * Create payment (wrapper for initPayment) * @param {Object} paymentData - Payment data * @returns {Promise<Object>} - Payment result */ async createPayment(paymentData) { try { const result = await this.initPayment({ amount: paymentData.amount, currency: paymentData.currency || 'USD', description: paymentData.description || 'Payment', order_id: paymentData.orderId, success_url: paymentData.callback_link, fail_url: paymentData.fail_link }); if (result.result === 'ok') { return { success: true, paymentUrl: result.payment_url, transactionId: result.order_id, amount: paymentData.amount, currency: paymentData.currency }; } else { throw new Error(result.message || 'Payment creation failed'); } } catch (error) { throw new Error(`PrimePayments payment creation failed: ${error.message}`); } } /** * Handle callback/notification * @param {Object} callbackData - Callback data * @returns {Promise<Object>} - Callback result */ async handleCallback(callbackData) { try { // Verify notification with secret word 2 const isValid = this.verifyNotification(callbackData); if (!isValid) { return { success: false, status: 'invalid', rawData: callbackData }; } const orderStatus = callbackData.status; const orderId = callbackData.order_id; if (orderStatus === 'success') { return { success: true, transactionId: orderId, status: 'completed', amount: parseFloat(callbackData.amount), currency: callbackData.currency, rawData: callbackData }; } else if (orderStatus === 'fail') { return { success: false, status: 'failed', transactionId: orderId, rawData: callbackData }; } else { return { success: false, status: 'pending', transactionId: orderId, rawData: callbackData }; } } catch (error) { throw new Error(`PrimePayments callback handling failed: ${error.message}`); } } } module.exports = PrimePayments;