quickpos 1.0.910 → 1.0.912
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/PROVIDERS-DETAILS.md +1544 -0
- package/examples/example-2checkout.js +78 -0
- package/examples/example-bitpay.js +83 -0
- package/examples/example-cardcom.js +80 -0
- package/examples/example-cashfree.js +109 -0
- package/examples/example-checkout.js +85 -0
- package/examples/example-coingate.js +101 -0
- package/examples/example-coinpayments.js +89 -0
- package/examples/example-doku.js +27 -0
- package/examples/example-epay.js +64 -0
- package/examples/example-epoint.js +91 -0
- package/examples/example-freekassa.js +26 -0
- package/examples/example-heleket.js +139 -0
- package/examples/example-konnect.js +227 -0
- package/examples/example-midtrans.js +80 -0
- package/examples/example-noonpayments.js +297 -0
- package/examples/example-nowpayments.js +289 -0
- package/examples/example-omise.js +27 -0
- package/examples/example-paycom.js +82 -0
- package/{example-paydisini.js → examples/example-paydisini.js} +1 -1
- package/examples/example-payid19.js +87 -0
- package/examples/example-paykun.js +29 -0
- package/examples/example-payme.js +202 -0
- package/examples/example-paymentwall.js +201 -0
- package/examples/example-paynet.js +104 -0
- package/examples/example-paynettr.js +18 -0
- package/examples/example-payoneer.js +74 -0
- package/examples/example-payop.js +351 -0
- package/examples/example-paypal.js +200 -0
- package/examples/example-payriff.js +89 -0
- package/examples/example-paysend.js +81 -0
- package/examples/example-payspace.js +103 -0
- package/examples/example-payssion.js +27 -0
- package/examples/example-paytabs.js +28 -0
- package/examples/example-paytm.js +78 -0
- package/examples/example-payuindia.js +108 -0
- package/examples/example-payulatam.js +75 -0
- package/examples/example-phonepe.js +27 -0
- package/examples/example-picpay.js +27 -0
- package/examples/example-plisio.js +84 -0
- package/examples/example-portwallet.js +90 -0
- package/examples/example-primepayments.js +250 -0
- package/examples/example-razorpay.js +30 -0
- package/examples/example-senangpay.js +28 -0
- package/examples/example-shurjopay.js +94 -0
- package/examples/example-toyyibpay.js +80 -0
- package/examples/example-tripay.js +89 -0
- package/examples/example-unitpay.js +26 -0
- package/examples/example-urway.js +28 -0
- package/examples/example-volet.js +80 -0
- package/examples/example-xendit.js +28 -0
- package/examples/example-yallapay.js +253 -0
- package/examples/example-yookassa.js +27 -0
- package/examples/example-youcanpay.js +28 -0
- package/examples/example-zarinpal.js +98 -0
- package/{example.js → examples/example.js} +1 -1
- package/lib/2checkout.js +165 -0
- package/lib/amazonpay.js +161 -0
- package/lib/bitpay.js +122 -0
- package/lib/cardcom.js +193 -0
- package/lib/cashfree.js +184 -0
- package/lib/checkout.js +248 -0
- package/lib/coinbase.js +150 -0
- package/lib/coingate.js +137 -0
- package/lib/coinpayments.js +245 -0
- package/lib/doku.js +173 -0
- package/lib/epay.js +175 -0
- package/lib/epoint.js +162 -0
- package/lib/freekassa.js +128 -0
- package/lib/heleket.js +67 -1
- package/lib/instamojo.js +158 -0
- package/lib/konnect.js +211 -0
- package/lib/midtrans.js +227 -0
- package/lib/noonpayments.js +650 -0
- package/lib/nowpayments.js +311 -0
- package/lib/omise.js +150 -0
- package/lib/paddle.js +180 -0
- package/lib/paycom.js +216 -0
- package/lib/payid19.js +211 -0
- package/lib/paykun.js +144 -0
- package/lib/payme.js +302 -0
- package/lib/paymentwall.js +205 -0
- package/lib/paynet.js +186 -0
- package/lib/paynettr.js +165 -0
- package/lib/payoneer.js +128 -0
- package/lib/payop.js +256 -0
- package/lib/paypal.js +542 -0
- package/lib/payriff.js +148 -0
- package/lib/paysend.js +189 -0
- package/lib/payspace.js +168 -0
- package/lib/payssion.js +177 -0
- package/lib/paytabs.js +145 -0
- package/lib/paytm.js +253 -0
- package/lib/payuindia.js +162 -0
- package/lib/payulatam.js +179 -0
- package/lib/perfectmoney.js +143 -0
- package/lib/phonepe.js +174 -0
- package/lib/picpay.js +119 -0
- package/lib/plisio.js +234 -0
- package/lib/portwallet.js +152 -0
- package/lib/primepayments.js +256 -0
- package/lib/razorpay.js +205 -0
- package/lib/senangpay.js +130 -0
- package/lib/shurjopay.js +159 -0
- package/lib/toyyibpay.js +151 -0
- package/lib/tripay.js +220 -0
- package/lib/unitpay.js +223 -0
- package/lib/urway.js +182 -0
- package/lib/volet.js +147 -0
- package/lib/xendit.js +206 -0
- package/lib/yallapay.js +279 -0
- package/lib/yookassa.js +193 -0
- package/lib/youcanpay.js +124 -0
- package/lib/zarinpal.js +157 -0
- package/package.json +138 -64
- package/readme.md +348 -105
- package/test.js +492 -0
- package/example-heleket.js +0 -83
- package/lib/vallet.js +0 -22
- /package/{example-anypay.js → examples/example-anypay.js} +0 -0
- /package/{example-bufpay.js → examples/example-bufpay.js} +0 -0
- /package/{example-cryptomus.js → examples/example-cryptomus.js} +0 -0
- /package/{example-esnekpos.js → examples/example-esnekpos.js} +0 -0
- /package/{example-fedapay.js → examples/example-fedapay.js} +0 -0
- /package/{example-iyzico.js → examples/example-iyzico.js} +0 -0
- /package/{example-papara.js → examples/example-papara.js} +0 -0
- /package/{example-payeer.js → examples/example-payeer.js} +0 -0
- /package/{example-paymaya.js → examples/example-paymaya.js} +0 -0
- /package/{example-shopier.js → examples/example-shopier.js} +0 -0
- /package/{ipaymu.js → examples/ipaymu.js} +0 -0
- /package/{oderopay.js → examples/oderopay.js} +0 -0
package/lib/checkout.js
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const crypto = require('crypto');
|
|
3
|
+
|
|
4
|
+
class CheckoutClient {
|
|
5
|
+
constructor(config) {
|
|
6
|
+
const requiredFields = ['secretKey'];
|
|
7
|
+
for (let field of requiredFields) {
|
|
8
|
+
if (!config[field]) throw new Error(`Missing required field: ${field}`);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
this.secretKey = config.secretKey;
|
|
12
|
+
this.publicKey = config.publicKey || '';
|
|
13
|
+
this.isSandbox = config.sandbox || false;
|
|
14
|
+
|
|
15
|
+
this.URL = this.isSandbox
|
|
16
|
+
? 'https://api.sandbox.checkout.com'
|
|
17
|
+
: 'https://api.checkout.com';
|
|
18
|
+
|
|
19
|
+
this.client = axios.create({
|
|
20
|
+
baseURL: this.URL,
|
|
21
|
+
headers: {
|
|
22
|
+
'Authorization': this.secretKey,
|
|
23
|
+
'Content-Type': 'application/json'
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
this.client.interceptors.response.use(response => {
|
|
28
|
+
return response;
|
|
29
|
+
}, error => {
|
|
30
|
+
if (error.response) {
|
|
31
|
+
throw new Error(`Checkout.com API error: ${error.response.data.error_type || error.message}`);
|
|
32
|
+
}
|
|
33
|
+
throw new Error(`Checkout.com API error: ${error.message}`);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async createPayment(options) {
|
|
38
|
+
try {
|
|
39
|
+
const requestData = {
|
|
40
|
+
source: {
|
|
41
|
+
type: options.sourceType || 'token',
|
|
42
|
+
token: options.token
|
|
43
|
+
},
|
|
44
|
+
amount: Math.round(parseFloat(options.amount) * 100), // Convert to cents
|
|
45
|
+
currency: options.currency || 'USD',
|
|
46
|
+
payment_type: options.paymentType || 'Regular',
|
|
47
|
+
reference: options.reference || options.orderId || `ORDER-${Date.now()}`,
|
|
48
|
+
description: options.description || options.name || 'Payment',
|
|
49
|
+
capture: options.capture !== undefined ? options.capture : true,
|
|
50
|
+
customer: {
|
|
51
|
+
email: options.customerEmail || options.email,
|
|
52
|
+
name: options.customerName || options.name || 'Customer'
|
|
53
|
+
},
|
|
54
|
+
billing_descriptor: {
|
|
55
|
+
name: options.billingName || options.name || 'Product',
|
|
56
|
+
city: options.billingCity || 'London'
|
|
57
|
+
},
|
|
58
|
+
metadata: {
|
|
59
|
+
order_id: options.orderId || `ORDER-${Date.now()}`,
|
|
60
|
+
...options.metadata
|
|
61
|
+
},
|
|
62
|
+
success_url: options.successUrl || options.callback_link,
|
|
63
|
+
failure_url: options.failureUrl || options.callback_link
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// If using hosted payment page
|
|
67
|
+
if (options.useHostedPage) {
|
|
68
|
+
const response = await this.client.post('/payment-links', {
|
|
69
|
+
amount: requestData.amount,
|
|
70
|
+
currency: requestData.currency,
|
|
71
|
+
reference: requestData.reference,
|
|
72
|
+
description: requestData.description,
|
|
73
|
+
customer: requestData.customer,
|
|
74
|
+
billing: {
|
|
75
|
+
address: {
|
|
76
|
+
country: options.billingCountry || 'GB'
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
products: options.products || [{
|
|
80
|
+
name: options.name || 'Product',
|
|
81
|
+
quantity: 1,
|
|
82
|
+
price: requestData.amount
|
|
83
|
+
}],
|
|
84
|
+
metadata: requestData.metadata,
|
|
85
|
+
return_url: options.returnUrl || options.callback_link,
|
|
86
|
+
locale: options.locale || 'en-GB'
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
status: 'success',
|
|
91
|
+
data: {
|
|
92
|
+
id: response.data.id,
|
|
93
|
+
url: response.data._links.redirect.href,
|
|
94
|
+
reference: requestData.reference,
|
|
95
|
+
expiresOn: response.data.expires_on
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Direct payment
|
|
101
|
+
const response = await this.client.post('/payments', requestData);
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
status: response.data.approved ? 'success' : 'pending',
|
|
105
|
+
data: {
|
|
106
|
+
id: response.data.id,
|
|
107
|
+
actionId: response.data.action_id,
|
|
108
|
+
amount: response.data.amount,
|
|
109
|
+
currency: response.data.currency,
|
|
110
|
+
approved: response.data.approved,
|
|
111
|
+
status: response.data.status,
|
|
112
|
+
reference: response.data.reference,
|
|
113
|
+
responseCode: response.data.response_code,
|
|
114
|
+
responseMessage: response.data.response_summary,
|
|
115
|
+
redirectUrl: response.data._links?.redirect?.href
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
} catch (error) {
|
|
119
|
+
throw new Error(`Payment creation error: ${error.message}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async getPaymentDetails(paymentId) {
|
|
124
|
+
try {
|
|
125
|
+
const response = await this.client.get(`/payments/${paymentId}`);
|
|
126
|
+
return response.data;
|
|
127
|
+
} catch (error) {
|
|
128
|
+
throw new Error(`Payment details error: ${error.message}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async handleCallback(callbackData) {
|
|
133
|
+
try {
|
|
134
|
+
const verification = await this.verifyWebhook(callbackData);
|
|
135
|
+
|
|
136
|
+
if (!verification.status) {
|
|
137
|
+
throw new Error(verification.error.message);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const data = verification.data;
|
|
141
|
+
|
|
142
|
+
// Status mapping
|
|
143
|
+
const statusMapping = {
|
|
144
|
+
'Authorized': 'success',
|
|
145
|
+
'Card Verified': 'success',
|
|
146
|
+
'Pending': 'pending',
|
|
147
|
+
'Declined': 'failed',
|
|
148
|
+
'Canceled': 'cancelled',
|
|
149
|
+
'Expired': 'expired'
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const eventData = data.data;
|
|
153
|
+
|
|
154
|
+
return {
|
|
155
|
+
status: statusMapping[eventData.status] || 'unknown',
|
|
156
|
+
paymentId: eventData.id,
|
|
157
|
+
actionId: eventData.action_id,
|
|
158
|
+
orderId: eventData.reference,
|
|
159
|
+
amount: parseFloat(eventData.amount) / 100,
|
|
160
|
+
currency: eventData.currency,
|
|
161
|
+
approved: eventData.approved,
|
|
162
|
+
paymentStatus: eventData.status,
|
|
163
|
+
responseCode: eventData.response_code,
|
|
164
|
+
responseMessage: eventData.response_summary,
|
|
165
|
+
eventType: data.type
|
|
166
|
+
};
|
|
167
|
+
} catch (error) {
|
|
168
|
+
throw new Error(`Error in Checkout.com callback handling: ${error.message}`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async verifyWebhook(data, signature = null) {
|
|
173
|
+
try {
|
|
174
|
+
// Checkout.com webhook signature verification
|
|
175
|
+
// This is a simplified version - in production, verify the signature
|
|
176
|
+
|
|
177
|
+
if (data.type && data.data) {
|
|
178
|
+
return {
|
|
179
|
+
status: true,
|
|
180
|
+
data: data
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return {
|
|
185
|
+
status: false,
|
|
186
|
+
error: {
|
|
187
|
+
code: 400,
|
|
188
|
+
message: 'Invalid webhook data'
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
} catch (error) {
|
|
192
|
+
return {
|
|
193
|
+
status: false,
|
|
194
|
+
error: {
|
|
195
|
+
code: 500,
|
|
196
|
+
message: error.message
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
async capturePayment(paymentId, amount = null) {
|
|
203
|
+
try {
|
|
204
|
+
const requestData = {};
|
|
205
|
+
if (amount) {
|
|
206
|
+
requestData.amount = Math.round(parseFloat(amount) * 100);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const response = await this.client.post(`/payments/${paymentId}/captures`, requestData);
|
|
210
|
+
return response.data;
|
|
211
|
+
} catch (error) {
|
|
212
|
+
throw new Error(`Capture payment error: ${error.message}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
async voidPayment(paymentId, reference = null) {
|
|
217
|
+
try {
|
|
218
|
+
const requestData = {};
|
|
219
|
+
if (reference) {
|
|
220
|
+
requestData.reference = reference;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const response = await this.client.post(`/payments/${paymentId}/voids`, requestData);
|
|
224
|
+
return response.data;
|
|
225
|
+
} catch (error) {
|
|
226
|
+
throw new Error(`Void payment error: ${error.message}`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
async refundPayment(paymentId, amount = null, reference = null) {
|
|
231
|
+
try {
|
|
232
|
+
const requestData = {};
|
|
233
|
+
if (amount) {
|
|
234
|
+
requestData.amount = Math.round(parseFloat(amount) * 100);
|
|
235
|
+
}
|
|
236
|
+
if (reference) {
|
|
237
|
+
requestData.reference = reference;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const response = await this.client.post(`/payments/${paymentId}/refunds`, requestData);
|
|
241
|
+
return response.data;
|
|
242
|
+
} catch (error) {
|
|
243
|
+
throw new Error(`Refund payment error: ${error.message}`);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
module.exports = CheckoutClient;
|
package/lib/coinbase.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const crypto = require('crypto');
|
|
3
|
+
|
|
4
|
+
class CoinbaseCommerceClient {
|
|
5
|
+
constructor(config) {
|
|
6
|
+
const requiredFields = ['apiKey'];
|
|
7
|
+
for (let field of requiredFields) {
|
|
8
|
+
if (!config[field]) throw new Error(`Missing required field: ${field}`);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
this.apiKey = config.apiKey;
|
|
12
|
+
this.webhookSecret = config.webhookSecret || '';
|
|
13
|
+
this.baseURL = 'https://api.commerce.coinbase.com';
|
|
14
|
+
|
|
15
|
+
this.client = axios.create({
|
|
16
|
+
baseURL: this.baseURL,
|
|
17
|
+
headers: {
|
|
18
|
+
'Content-Type': 'application/json',
|
|
19
|
+
'X-CC-Api-Key': this.apiKey,
|
|
20
|
+
'X-CC-Version': '2018-03-22'
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async createPayment(options) {
|
|
26
|
+
try {
|
|
27
|
+
const orderId = options.orderId || `ORDER-${Date.now()}`;
|
|
28
|
+
|
|
29
|
+
const chargeData = {
|
|
30
|
+
name: options.name || 'Payment',
|
|
31
|
+
description: options.description || 'Payment description',
|
|
32
|
+
pricing_type: 'fixed_price',
|
|
33
|
+
local_price: {
|
|
34
|
+
amount: parseFloat(options.amount).toFixed(2),
|
|
35
|
+
currency: options.currency || 'USD'
|
|
36
|
+
},
|
|
37
|
+
metadata: {
|
|
38
|
+
order_id: orderId,
|
|
39
|
+
customer_email: options.email || '',
|
|
40
|
+
customer_name: options.customerName || ''
|
|
41
|
+
},
|
|
42
|
+
redirect_url: options.successUrl || options.callback_link,
|
|
43
|
+
cancel_url: options.failUrl || options.callback_link
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const response = await this.client.post('/charges', chargeData);
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
status: 'success',
|
|
50
|
+
data: {
|
|
51
|
+
id: response.data.data.id,
|
|
52
|
+
code: response.data.data.code,
|
|
53
|
+
url: response.data.data.hosted_url,
|
|
54
|
+
orderId: orderId,
|
|
55
|
+
amount: response.data.data.pricing.local.amount,
|
|
56
|
+
currency: response.data.data.pricing.local.currency,
|
|
57
|
+
addresses: response.data.data.addresses,
|
|
58
|
+
expiresAt: response.data.data.expires_at
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
} catch (error) {
|
|
62
|
+
throw new Error(`Payment creation error: ${error.response?.data?.error?.message || error.message}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async handleCallback(callbackData, signature) {
|
|
67
|
+
try {
|
|
68
|
+
// Verify webhook signature
|
|
69
|
+
if (this.webhookSecret && signature) {
|
|
70
|
+
const verification = this.verifyWebhook(callbackData, signature);
|
|
71
|
+
if (!verification) {
|
|
72
|
+
throw new Error('Invalid webhook signature');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const event = callbackData.event;
|
|
77
|
+
const charge = event.data;
|
|
78
|
+
|
|
79
|
+
// Status mapping based on event type
|
|
80
|
+
const statusMapping = {
|
|
81
|
+
'charge:confirmed': 'success',
|
|
82
|
+
'charge:resolved': 'success',
|
|
83
|
+
'charge:pending': 'pending',
|
|
84
|
+
'charge:failed': 'failed',
|
|
85
|
+
'charge:delayed': 'pending'
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
status: statusMapping[event.type] || 'unknown',
|
|
90
|
+
orderId: charge.metadata?.order_id,
|
|
91
|
+
transactionId: charge.id,
|
|
92
|
+
code: charge.code,
|
|
93
|
+
amount: parseFloat(charge.pricing?.local?.amount || 0),
|
|
94
|
+
currency: charge.pricing?.local?.currency,
|
|
95
|
+
paymentStatus: event.type,
|
|
96
|
+
timeline: charge.timeline,
|
|
97
|
+
payments: charge.payments
|
|
98
|
+
};
|
|
99
|
+
} catch (error) {
|
|
100
|
+
throw new Error(`Error in Coinbase Commerce callback handling: ${error.message}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
verifyWebhook(payload, signature) {
|
|
105
|
+
try {
|
|
106
|
+
const computedSignature = crypto
|
|
107
|
+
.createHmac('sha256', this.webhookSecret)
|
|
108
|
+
.update(JSON.stringify(payload))
|
|
109
|
+
.digest('hex');
|
|
110
|
+
|
|
111
|
+
return computedSignature === signature;
|
|
112
|
+
} catch (error) {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async getCharge(chargeId) {
|
|
118
|
+
try {
|
|
119
|
+
const response = await this.client.get(`/charges/${chargeId}`);
|
|
120
|
+
return response.data.data;
|
|
121
|
+
} catch (error) {
|
|
122
|
+
throw new Error(`Error fetching charge: ${error.response?.data?.error?.message || error.message}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async listCharges(options = {}) {
|
|
127
|
+
try {
|
|
128
|
+
const params = {
|
|
129
|
+
limit: options.limit || 25,
|
|
130
|
+
order: options.order || 'desc'
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const response = await this.client.get('/charges', { params });
|
|
134
|
+
return response.data;
|
|
135
|
+
} catch (error) {
|
|
136
|
+
throw new Error(`Error listing charges: ${error.response?.data?.error?.message || error.message}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async cancelCharge(chargeId) {
|
|
141
|
+
try {
|
|
142
|
+
const response = await this.client.post(`/charges/${chargeId}/cancel`);
|
|
143
|
+
return response.data.data;
|
|
144
|
+
} catch (error) {
|
|
145
|
+
throw new Error(`Error canceling charge: ${error.response?.data?.error?.message || error.message}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
module.exports = CoinbaseCommerceClient;
|
package/lib/coingate.js
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const crypto = require('crypto');
|
|
3
|
+
|
|
4
|
+
class CoinGateClient {
|
|
5
|
+
constructor(config) {
|
|
6
|
+
const requiredFields = ['apiKey'];
|
|
7
|
+
for (let field of requiredFields) {
|
|
8
|
+
if (!config[field]) throw new Error(`Missing required field: ${field}`);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
this.apiKey = config.apiKey;
|
|
12
|
+
this.environment = config.environment || 'live'; // 'sandbox' or 'live'
|
|
13
|
+
this.baseURL = this.environment === 'sandbox'
|
|
14
|
+
? 'https://api-sandbox.coingate.com/v2'
|
|
15
|
+
: 'https://api.coingate.com/v2';
|
|
16
|
+
|
|
17
|
+
this.client = axios.create({
|
|
18
|
+
baseURL: this.baseURL,
|
|
19
|
+
headers: {
|
|
20
|
+
'Content-Type': 'application/json',
|
|
21
|
+
'Authorization': `Token ${this.apiKey}`
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async createPayment(options) {
|
|
27
|
+
try {
|
|
28
|
+
const orderId = options.orderId || `ORDER-${Date.now()}`;
|
|
29
|
+
|
|
30
|
+
const orderData = {
|
|
31
|
+
order_id: orderId,
|
|
32
|
+
price_amount: parseFloat(options.amount),
|
|
33
|
+
price_currency: options.currency || 'USD',
|
|
34
|
+
receive_currency: options.receiveCurrency || options.currency || 'USD',
|
|
35
|
+
title: options.title || options.name || 'Payment',
|
|
36
|
+
description: options.description || '',
|
|
37
|
+
callback_url: options.callbackUrl || options.callback_link,
|
|
38
|
+
cancel_url: options.failUrl || options.callback_link,
|
|
39
|
+
success_url: options.successUrl || options.callback_link,
|
|
40
|
+
purchaser_email: options.email || '',
|
|
41
|
+
token: options.token || 'DO_NOT_CONVERT'
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const response = await this.client.post('/orders', orderData);
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
status: 'success',
|
|
48
|
+
data: {
|
|
49
|
+
id: response.data.id,
|
|
50
|
+
url: response.data.payment_url,
|
|
51
|
+
orderId: orderId,
|
|
52
|
+
amount: response.data.price_amount,
|
|
53
|
+
currency: response.data.price_currency,
|
|
54
|
+
status: response.data.status,
|
|
55
|
+
payAmount: response.data.pay_amount,
|
|
56
|
+
payCurrency: response.data.pay_currency
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
} catch (error) {
|
|
60
|
+
throw new Error(`Payment creation error: ${error.response?.data?.message || error.message}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async handleCallback(callbackData) {
|
|
65
|
+
try {
|
|
66
|
+
const orderId = callbackData.id || callbackData.order_id;
|
|
67
|
+
|
|
68
|
+
if (!orderId) {
|
|
69
|
+
throw new Error('Order ID not found in callback data');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Get order details for verification
|
|
73
|
+
const order = await this.getOrder(orderId);
|
|
74
|
+
|
|
75
|
+
// Status mapping
|
|
76
|
+
const statusMapping = {
|
|
77
|
+
'paid': 'success',
|
|
78
|
+
'confirmed': 'success',
|
|
79
|
+
'pending': 'pending',
|
|
80
|
+
'expired': 'failed',
|
|
81
|
+
'canceled': 'failed',
|
|
82
|
+
'refunded': 'refunded',
|
|
83
|
+
'invalid': 'failed'
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
status: statusMapping[order.status] || 'unknown',
|
|
88
|
+
orderId: order.order_id,
|
|
89
|
+
transactionId: order.id.toString(),
|
|
90
|
+
amount: parseFloat(order.price_amount),
|
|
91
|
+
currency: order.price_currency,
|
|
92
|
+
paymentStatus: order.status,
|
|
93
|
+
payAmount: order.pay_amount,
|
|
94
|
+
payCurrency: order.pay_currency,
|
|
95
|
+
receiveAmount: order.receive_amount,
|
|
96
|
+
receiveCurrency: order.receive_currency
|
|
97
|
+
};
|
|
98
|
+
} catch (error) {
|
|
99
|
+
throw new Error(`Error in CoinGate callback handling: ${error.message}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async getOrder(orderId) {
|
|
104
|
+
try {
|
|
105
|
+
const response = await this.client.get(`/orders/${orderId}`);
|
|
106
|
+
return response.data;
|
|
107
|
+
} catch (error) {
|
|
108
|
+
throw new Error(`Error fetching order: ${error.response?.data?.message || error.message}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async listOrders(options = {}) {
|
|
113
|
+
try {
|
|
114
|
+
const params = {
|
|
115
|
+
sort: options.sort || 'created_at_desc',
|
|
116
|
+
per_page: options.perPage || 100,
|
|
117
|
+
page: options.page || 1
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const response = await this.client.get('/orders', { params });
|
|
121
|
+
return response.data;
|
|
122
|
+
} catch (error) {
|
|
123
|
+
throw new Error(`Error listing orders: ${error.response?.data?.message || error.message}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async getExchangeRate(from, to) {
|
|
128
|
+
try {
|
|
129
|
+
const response = await this.client.get(`/rates/merchant/${from}/${to}`);
|
|
130
|
+
return parseFloat(response.data);
|
|
131
|
+
} catch (error) {
|
|
132
|
+
throw new Error(`Error getting exchange rate: ${error.response?.data?.message || error.message}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
module.exports = CoinGateClient;
|