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>

151 lines (132 loc) • 5.47 kB
const axios = require('axios'); const crypto = require('crypto'); class CoinbaseCommerceClient { constructor(config) { const requiredFields = ['apiKey']; for (let field of requiredFields) { if (!config[field]) throw new Error(`Missing required field: ${field}`); } this.apiKey = config.apiKey; this.webhookSecret = config.webhookSecret || ''; this.baseURL = 'https://api.commerce.coinbase.com'; this.client = axios.create({ baseURL: this.baseURL, headers: { 'Content-Type': 'application/json', 'X-CC-Api-Key': this.apiKey, 'X-CC-Version': '2018-03-22' } }); } async createPayment(options) { try { const orderId = options.orderId || `ORDER-${Date.now()}`; const chargeData = { name: options.name || 'Payment', description: options.description || 'Payment description', pricing_type: 'fixed_price', local_price: { amount: parseFloat(options.amount).toFixed(2), currency: options.currency || 'USD' }, metadata: { order_id: orderId, customer_email: options.email || '', customer_name: options.customerName || '' }, redirect_url: options.successUrl || options.callback_link, cancel_url: options.failUrl || options.callback_link }; const response = await this.client.post('/charges', chargeData); return { status: 'success', data: { id: response.data.data.id, code: response.data.data.code, url: response.data.data.hosted_url, orderId: orderId, amount: response.data.data.pricing.local.amount, currency: response.data.data.pricing.local.currency, addresses: response.data.data.addresses, expiresAt: response.data.data.expires_at } }; } catch (error) { throw new Error(`Payment creation error: ${error.response?.data?.error?.message || error.message}`); } } async handleCallback(callbackData, signature) { try { // Verify webhook signature if (this.webhookSecret && signature) { const verification = this.verifyWebhook(callbackData, signature); if (!verification) { throw new Error('Invalid webhook signature'); } } const event = callbackData.event; const charge = event.data; // Status mapping based on event type const statusMapping = { 'charge:confirmed': 'success', 'charge:resolved': 'success', 'charge:pending': 'pending', 'charge:failed': 'failed', 'charge:delayed': 'pending' }; return { status: statusMapping[event.type] || 'unknown', orderId: charge.metadata?.order_id, transactionId: charge.id, code: charge.code, amount: parseFloat(charge.pricing?.local?.amount || 0), currency: charge.pricing?.local?.currency, paymentStatus: event.type, timeline: charge.timeline, payments: charge.payments }; } catch (error) { throw new Error(`Error in Coinbase Commerce callback handling: ${error.message}`); } } verifyWebhook(payload, signature) { try { const computedSignature = crypto .createHmac('sha256', this.webhookSecret) .update(JSON.stringify(payload)) .digest('hex'); return computedSignature === signature; } catch (error) { return false; } } async getCharge(chargeId) { try { const response = await this.client.get(`/charges/${chargeId}`); return response.data.data; } catch (error) { throw new Error(`Error fetching charge: ${error.response?.data?.error?.message || error.message}`); } } async listCharges(options = {}) { try { const params = { limit: options.limit || 25, order: options.order || 'desc' }; const response = await this.client.get('/charges', { params }); return response.data; } catch (error) { throw new Error(`Error listing charges: ${error.response?.data?.error?.message || error.message}`); } } async cancelCharge(chargeId) { try { const response = await this.client.post(`/charges/${chargeId}/cancel`); return response.data.data; } catch (error) { throw new Error(`Error canceling charge: ${error.response?.data?.error?.message || error.message}`); } } } module.exports = CoinbaseCommerceClient;