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/amazonpay.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const crypto = require('crypto');
|
|
3
|
+
|
|
4
|
+
class AmazonPayClient {
|
|
5
|
+
constructor(config) {
|
|
6
|
+
const requiredFields = ['merchantId', 'accessKey', 'secretKey'];
|
|
7
|
+
for (let field of requiredFields) {
|
|
8
|
+
if (!config[field]) throw new Error(`Missing required field: ${field}`);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
this.merchantId = config.merchantId;
|
|
12
|
+
this.accessKey = config.accessKey;
|
|
13
|
+
this.secretKey = config.secretKey;
|
|
14
|
+
this.region = config.region || 'us'; // us, eu, jp
|
|
15
|
+
this.sandbox = config.sandbox || false;
|
|
16
|
+
|
|
17
|
+
const regionUrls = {
|
|
18
|
+
us: this.sandbox ? 'https://pay-api.amazon.com/sandbox' : 'https://pay-api.amazon.com/live',
|
|
19
|
+
eu: this.sandbox ? 'https://pay-api.amazon.eu/sandbox' : 'https://pay-api.amazon.eu/live',
|
|
20
|
+
jp: this.sandbox ? 'https://pay-api.amazon.jp/sandbox' : 'https://pay-api.amazon.jp/live'
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
this.baseURL = regionUrls[this.region];
|
|
24
|
+
|
|
25
|
+
this.client = axios.create({
|
|
26
|
+
baseURL: this.baseURL,
|
|
27
|
+
headers: {
|
|
28
|
+
'Content-Type': 'application/json'
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
generateSignature(payload) {
|
|
34
|
+
return crypto
|
|
35
|
+
.createHmac('sha256', this.secretKey)
|
|
36
|
+
.update(payload)
|
|
37
|
+
.digest('base64');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async createPayment(options) {
|
|
41
|
+
try {
|
|
42
|
+
const orderId = options.orderId || `ORDER-${Date.now()}`;
|
|
43
|
+
const timestamp = new Date().toISOString();
|
|
44
|
+
|
|
45
|
+
const payloadData = {
|
|
46
|
+
webCheckoutDetails: {
|
|
47
|
+
checkoutReviewReturnUrl: options.successUrl || options.callback_link
|
|
48
|
+
},
|
|
49
|
+
storeId: this.merchantId,
|
|
50
|
+
chargePermissionType: 'OneTime',
|
|
51
|
+
recurringMetadata: null,
|
|
52
|
+
paymentDetails: {
|
|
53
|
+
paymentIntent: 'Authorize',
|
|
54
|
+
chargeAmount: {
|
|
55
|
+
amount: parseFloat(options.amount).toFixed(2),
|
|
56
|
+
currencyCode: options.currency || 'USD'
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
merchantMetadata: {
|
|
60
|
+
merchantReferenceId: orderId,
|
|
61
|
+
merchantStoreName: options.storeName || 'Store',
|
|
62
|
+
noteToBuyer: options.description || ''
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const payload = JSON.stringify(payloadData);
|
|
67
|
+
const signature = this.generateSignature(payload);
|
|
68
|
+
|
|
69
|
+
const response = await this.client.post('/v2/checkoutSessions', payloadData, {
|
|
70
|
+
headers: {
|
|
71
|
+
'x-amz-pay-date': timestamp,
|
|
72
|
+
'x-amz-pay-region': this.region,
|
|
73
|
+
'Authorization': `AMZN-PAY-RSASSA-PSS ${signature}`
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
status: 'success',
|
|
79
|
+
data: {
|
|
80
|
+
checkoutSessionId: response.data.checkoutSessionId,
|
|
81
|
+
webCheckoutDetails: response.data.webCheckoutDetails,
|
|
82
|
+
url: response.data.webCheckoutDetails?.amazonPayRedirectUrl,
|
|
83
|
+
orderId: orderId,
|
|
84
|
+
amount: payloadData.paymentDetails.chargeAmount.amount,
|
|
85
|
+
currency: payloadData.paymentDetails.chargeAmount.currencyCode
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
} catch (error) {
|
|
89
|
+
throw new Error(`Payment creation error: ${error.response?.data?.message || error.message}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async handleCallback(callbackData) {
|
|
94
|
+
try {
|
|
95
|
+
const checkoutSessionId = callbackData.amazonCheckoutSessionId;
|
|
96
|
+
|
|
97
|
+
if (!checkoutSessionId) {
|
|
98
|
+
throw new Error('Checkout session ID not found in callback data');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Get checkout session details
|
|
102
|
+
const session = await this.getCheckoutSession(checkoutSessionId);
|
|
103
|
+
|
|
104
|
+
// Status mapping
|
|
105
|
+
const statusMapping = {
|
|
106
|
+
'Open': 'pending',
|
|
107
|
+
'Completed': 'success',
|
|
108
|
+
'Canceled': 'failed',
|
|
109
|
+
'Expired': 'failed'
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
status: statusMapping[session.statusDetails?.state] || 'unknown',
|
|
114
|
+
orderId: session.merchantMetadata?.merchantReferenceId,
|
|
115
|
+
transactionId: checkoutSessionId,
|
|
116
|
+
amount: parseFloat(session.chargeAmount?.amount || 0),
|
|
117
|
+
currency: session.chargeAmount?.currencyCode,
|
|
118
|
+
paymentStatus: session.statusDetails?.state,
|
|
119
|
+
buyer: session.buyer
|
|
120
|
+
};
|
|
121
|
+
} catch (error) {
|
|
122
|
+
throw new Error(`Error in Amazon Pay callback handling: ${error.message}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async getCheckoutSession(checkoutSessionId) {
|
|
127
|
+
try {
|
|
128
|
+
const timestamp = new Date().toISOString();
|
|
129
|
+
|
|
130
|
+
const response = await this.client.get(`/v2/checkoutSessions/${checkoutSessionId}`, {
|
|
131
|
+
headers: {
|
|
132
|
+
'x-amz-pay-date': timestamp,
|
|
133
|
+
'x-amz-pay-region': this.region
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
return response.data;
|
|
138
|
+
} catch (error) {
|
|
139
|
+
throw new Error(`Error fetching checkout session: ${error.response?.data?.message || error.message}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async updateCheckoutSession(checkoutSessionId, updates) {
|
|
144
|
+
try {
|
|
145
|
+
const timestamp = new Date().toISOString();
|
|
146
|
+
|
|
147
|
+
const response = await this.client.patch(`/v2/checkoutSessions/${checkoutSessionId}`, updates, {
|
|
148
|
+
headers: {
|
|
149
|
+
'x-amz-pay-date': timestamp,
|
|
150
|
+
'x-amz-pay-region': this.region
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
return response.data;
|
|
155
|
+
} catch (error) {
|
|
156
|
+
throw new Error(`Error updating checkout session: ${error.response?.data?.message || error.message}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
module.exports = AmazonPayClient;
|
package/lib/bitpay.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const crypto = require('crypto');
|
|
3
|
+
|
|
4
|
+
class BitPayClient {
|
|
5
|
+
constructor(config) {
|
|
6
|
+
const requiredFields = ['apiToken'];
|
|
7
|
+
for (let field of requiredFields) {
|
|
8
|
+
if (!config[field]) throw new Error(`Missing required field: ${field}`);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
this.apiToken = config.apiToken;
|
|
12
|
+
this.environment = config.environment || 'test'; // 'test' or 'prod'
|
|
13
|
+
this.baseURL = this.environment === 'prod'
|
|
14
|
+
? 'https://bitpay.com'
|
|
15
|
+
: 'https://test.bitpay.com';
|
|
16
|
+
|
|
17
|
+
this.client = axios.create({
|
|
18
|
+
baseURL: this.baseURL,
|
|
19
|
+
headers: {
|
|
20
|
+
'Content-Type': 'application/json',
|
|
21
|
+
'X-Accept-Version': '2.0.0',
|
|
22
|
+
'Authorization': `Bearer ${this.apiToken}`
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async createPayment(options) {
|
|
28
|
+
try {
|
|
29
|
+
const orderId = options.orderId || `ORDER-${Date.now()}`;
|
|
30
|
+
|
|
31
|
+
const invoiceData = {
|
|
32
|
+
price: parseFloat(options.amount),
|
|
33
|
+
currency: options.currency || 'USD',
|
|
34
|
+
orderId: orderId,
|
|
35
|
+
itemDesc: options.description || options.name || 'Payment',
|
|
36
|
+
notificationURL: options.callbackUrl || options.callback_link,
|
|
37
|
+
redirectURL: options.successUrl || options.callback_link,
|
|
38
|
+
buyer: {
|
|
39
|
+
email: options.email || '',
|
|
40
|
+
name: options.name || ''
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const response = await this.client.post('/invoices', invoiceData);
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
status: 'success',
|
|
48
|
+
data: {
|
|
49
|
+
invoiceId: response.data.data.id,
|
|
50
|
+
url: response.data.data.url,
|
|
51
|
+
orderId: orderId,
|
|
52
|
+
amount: response.data.data.price,
|
|
53
|
+
currency: response.data.data.currency,
|
|
54
|
+
status: response.data.data.status
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
} catch (error) {
|
|
58
|
+
throw new Error(`Payment creation error: ${error.response?.data?.error || error.message}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async handleCallback(callbackData) {
|
|
63
|
+
try {
|
|
64
|
+
const invoiceId = callbackData.id || callbackData.data?.id;
|
|
65
|
+
|
|
66
|
+
if (!invoiceId) {
|
|
67
|
+
throw new Error('Invoice ID not found in callback data');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Get invoice details
|
|
71
|
+
const invoice = await this.getInvoice(invoiceId);
|
|
72
|
+
|
|
73
|
+
// Status mapping
|
|
74
|
+
const statusMapping = {
|
|
75
|
+
'confirmed': 'success',
|
|
76
|
+
'complete': 'success',
|
|
77
|
+
'paid': 'success',
|
|
78
|
+
'new': 'pending',
|
|
79
|
+
'expired': 'failed',
|
|
80
|
+
'invalid': 'failed'
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
status: statusMapping[invoice.status.toLowerCase()] || 'unknown',
|
|
85
|
+
orderId: invoice.orderId,
|
|
86
|
+
transactionId: invoice.id,
|
|
87
|
+
amount: parseFloat(invoice.price),
|
|
88
|
+
currency: invoice.currency,
|
|
89
|
+
paymentStatus: invoice.status,
|
|
90
|
+
exceptionStatus: invoice.exceptionStatus
|
|
91
|
+
};
|
|
92
|
+
} catch (error) {
|
|
93
|
+
throw new Error(`Error in BitPay callback handling: ${error.message}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async getInvoice(invoiceId) {
|
|
98
|
+
try {
|
|
99
|
+
const response = await this.client.get(`/invoices/${invoiceId}`);
|
|
100
|
+
return response.data.data;
|
|
101
|
+
} catch (error) {
|
|
102
|
+
throw new Error(`Error fetching invoice: ${error.response?.data?.error || error.message}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async refundInvoice(invoiceId, options = {}) {
|
|
107
|
+
try {
|
|
108
|
+
const refundData = {
|
|
109
|
+
amount: options.amount,
|
|
110
|
+
currency: options.currency,
|
|
111
|
+
preview: options.preview || false
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const response = await this.client.post(`/invoices/${invoiceId}/refunds`, refundData);
|
|
115
|
+
return response.data.data;
|
|
116
|
+
} catch (error) {
|
|
117
|
+
throw new Error(`Error creating refund: ${error.response?.data?.error || error.message}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
module.exports = BitPayClient;
|
package/lib/cardcom.js
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
|
|
3
|
+
class CardcomClient {
|
|
4
|
+
constructor(config) {
|
|
5
|
+
const requiredFields = ['terminalNumber', 'userName'];
|
|
6
|
+
for (let field of requiredFields) {
|
|
7
|
+
if (!config[field]) throw new Error(`Missing required field: ${field}`);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
this.terminalNumber = config.terminalNumber;
|
|
11
|
+
this.userName = config.userName;
|
|
12
|
+
this.apiName = config.apiName || this.userName;
|
|
13
|
+
this.URL = 'https://secure.cardcom.solutions/api/v11';
|
|
14
|
+
|
|
15
|
+
this.client = axios.create({
|
|
16
|
+
baseURL: this.URL,
|
|
17
|
+
headers: {
|
|
18
|
+
'Content-Type': 'application/json'
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
this.client.interceptors.response.use(response => {
|
|
23
|
+
return response;
|
|
24
|
+
}, error => {
|
|
25
|
+
if (error.response) {
|
|
26
|
+
throw new Error(`Cardcom API error: ${error.response.data.ResponseMessage || error.message}`);
|
|
27
|
+
}
|
|
28
|
+
throw new Error(`Cardcom API error: ${error.message}`);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async createPayment(options) {
|
|
33
|
+
try {
|
|
34
|
+
const requestData = {
|
|
35
|
+
TerminalNumber: this.terminalNumber,
|
|
36
|
+
UserName: this.userName,
|
|
37
|
+
APILevel: 10,
|
|
38
|
+
Operation: {
|
|
39
|
+
Type: 2, // Create Invoice
|
|
40
|
+
SumToBill: parseFloat(options.amount),
|
|
41
|
+
Currency: options.currency || 'ILS',
|
|
42
|
+
Description: options.description || options.name || 'Payment',
|
|
43
|
+
InvoiceHead: {
|
|
44
|
+
CustName: options.customerName || options.name || 'Customer',
|
|
45
|
+
SendByEmail: true,
|
|
46
|
+
CustEmail: options.email,
|
|
47
|
+
CustMobile: options.mobile || options.phone || '',
|
|
48
|
+
ExtendedInvoiceType: 1,
|
|
49
|
+
InvoiceType: options.invoiceType || 1,
|
|
50
|
+
Language: options.language || 'he'
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
ReturnValue: options.returnUrl || options.callback_link,
|
|
54
|
+
IndicatorUrl: options.callbackUrl || options.callback_link,
|
|
55
|
+
InternalDealNumber: options.internalDealNumber || options.orderId || `ORDER-${Date.now()}`
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
if (options.items && Array.isArray(options.items)) {
|
|
59
|
+
requestData.Operation.InvoiceLines = {
|
|
60
|
+
InvoiceLine: options.items
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const response = await this.client.post('/LowProfile/CreateInvoice', requestData);
|
|
65
|
+
|
|
66
|
+
if (response.data.ResponseCode === 0) {
|
|
67
|
+
return {
|
|
68
|
+
status: 'success',
|
|
69
|
+
data: {
|
|
70
|
+
lowProfileId: response.data.LowProfileId,
|
|
71
|
+
lowProfileCode: response.data.LowProfileCode,
|
|
72
|
+
url: response.data.Url,
|
|
73
|
+
internalDealNumber: requestData.InternalDealNumber
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
} else {
|
|
77
|
+
throw new Error(response.data.ResponseMessage || 'Payment creation failed');
|
|
78
|
+
}
|
|
79
|
+
} catch (error) {
|
|
80
|
+
throw new Error(`Payment creation error: ${error.message}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async getInvoiceDetails(lowProfileId) {
|
|
85
|
+
try {
|
|
86
|
+
const requestData = {
|
|
87
|
+
TerminalNumber: this.terminalNumber,
|
|
88
|
+
UserName: this.userName,
|
|
89
|
+
LowProfileId: lowProfileId
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const response = await this.client.post('/LowProfile/GetLowProfileIndicator', requestData);
|
|
93
|
+
return response.data;
|
|
94
|
+
} catch (error) {
|
|
95
|
+
throw new Error(`Invoice details error: ${error.message}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async handleCallback(callbackData) {
|
|
100
|
+
try {
|
|
101
|
+
const verification = await this.verifyCallback(callbackData);
|
|
102
|
+
|
|
103
|
+
if (!verification.status) {
|
|
104
|
+
throw new Error(verification.error.message);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const data = verification.data;
|
|
108
|
+
|
|
109
|
+
// Status mapping based on OperationResponse
|
|
110
|
+
const statusMapping = {
|
|
111
|
+
'0': 'success',
|
|
112
|
+
'1': 'failed'
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
status: statusMapping[data.OperationResponse] || 'unknown',
|
|
117
|
+
lowProfileId: data.LowProfileId,
|
|
118
|
+
internalDealNumber: data.InternalDealNumber,
|
|
119
|
+
orderId: data.InternalDealNumber,
|
|
120
|
+
operationResponse: data.OperationResponse,
|
|
121
|
+
operationResponseText: data.OperationResponseText,
|
|
122
|
+
extendedResponseText: data.ExtendedResponseText
|
|
123
|
+
};
|
|
124
|
+
} catch (error) {
|
|
125
|
+
throw new Error(`Error in Cardcom callback handling: ${error.message}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async verifyCallback(data) {
|
|
130
|
+
try {
|
|
131
|
+
if (data.OperationResponse !== '0') {
|
|
132
|
+
return {
|
|
133
|
+
status: false,
|
|
134
|
+
error: {
|
|
135
|
+
code: 400,
|
|
136
|
+
message: data.ExtendedResponseText || 'Payment failed'
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
status: true,
|
|
143
|
+
data: data
|
|
144
|
+
};
|
|
145
|
+
} catch (error) {
|
|
146
|
+
return {
|
|
147
|
+
status: false,
|
|
148
|
+
error: {
|
|
149
|
+
code: 500,
|
|
150
|
+
message: error.message
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async chargeCard(options) {
|
|
157
|
+
try {
|
|
158
|
+
const requestData = {
|
|
159
|
+
TerminalNumber: this.terminalNumber,
|
|
160
|
+
UserName: this.userName,
|
|
161
|
+
APILevel: 10,
|
|
162
|
+
CardNumber: options.cardNumber,
|
|
163
|
+
DateMMYY: options.expiryDate, // MMYY format
|
|
164
|
+
CVV: options.cvv,
|
|
165
|
+
SumToBill: parseFloat(options.amount),
|
|
166
|
+
Currency: options.currency || 'ILS',
|
|
167
|
+
CustomerName: options.customerName || options.name || 'Customer',
|
|
168
|
+
CustomerEmail: options.email,
|
|
169
|
+
InternalDealNumber: options.internalDealNumber || options.orderId || `ORDER-${Date.now()}`,
|
|
170
|
+
IndicatorUrl: options.callbackUrl || options.callback_link
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const response = await this.client.post('/DealWasSuccessful', requestData);
|
|
174
|
+
|
|
175
|
+
if (response.data.ResponseCode === 0) {
|
|
176
|
+
return {
|
|
177
|
+
status: 'success',
|
|
178
|
+
data: {
|
|
179
|
+
dealResponse: response.data.DealResponse,
|
|
180
|
+
internalDealNumber: response.data.InternalDealNumber,
|
|
181
|
+
confirmationNumber: response.data.ConfirmationNumber
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
} else {
|
|
185
|
+
throw new Error(response.data.ResponseMessage || 'Card charge failed');
|
|
186
|
+
}
|
|
187
|
+
} catch (error) {
|
|
188
|
+
throw new Error(`Card charge error: ${error.message}`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
module.exports = CardcomClient;
|
package/lib/cashfree.js
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const crypto = require('crypto');
|
|
3
|
+
|
|
4
|
+
class CashfreeClient {
|
|
5
|
+
constructor(config) {
|
|
6
|
+
const requiredFields = ['appId', 'secretKey'];
|
|
7
|
+
for (let field of requiredFields) {
|
|
8
|
+
if (!config[field]) throw new Error(`Missing required field: ${field}`);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
this.appId = config.appId;
|
|
12
|
+
this.secretKey = config.secretKey;
|
|
13
|
+
this.environment = config.environment || 'production'; // 'sandbox' or 'production'
|
|
14
|
+
this.baseURL = this.environment === 'sandbox'
|
|
15
|
+
? 'https://sandbox.cashfree.com/pg'
|
|
16
|
+
: 'https://api.cashfree.com/pg';
|
|
17
|
+
|
|
18
|
+
this.client = axios.create({
|
|
19
|
+
baseURL: this.baseURL,
|
|
20
|
+
headers: {
|
|
21
|
+
'Content-Type': 'application/json',
|
|
22
|
+
'x-client-id': this.appId,
|
|
23
|
+
'x-client-secret': this.secretKey,
|
|
24
|
+
'x-api-version': '2023-08-01'
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async createPayment(options) {
|
|
30
|
+
try {
|
|
31
|
+
const orderId = options.orderId || `order_${Date.now()}`;
|
|
32
|
+
|
|
33
|
+
const orderData = {
|
|
34
|
+
order_id: orderId,
|
|
35
|
+
order_amount: parseFloat(options.amount),
|
|
36
|
+
order_currency: options.currency || 'INR',
|
|
37
|
+
customer_details: {
|
|
38
|
+
customer_id: options.customerId || `customer_${Date.now()}`,
|
|
39
|
+
customer_email: options.email || '',
|
|
40
|
+
customer_phone: options.phone || '',
|
|
41
|
+
customer_name: options.name || options.customerName || ''
|
|
42
|
+
},
|
|
43
|
+
order_meta: {
|
|
44
|
+
return_url: options.successUrl || options.callback_link,
|
|
45
|
+
notify_url: options.callbackUrl || options.callback_link
|
|
46
|
+
},
|
|
47
|
+
order_note: options.description || ''
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const response = await this.client.post('/orders', orderData);
|
|
51
|
+
|
|
52
|
+
if (response.data.order_status === 'ACTIVE') {
|
|
53
|
+
return {
|
|
54
|
+
status: 'success',
|
|
55
|
+
data: {
|
|
56
|
+
orderId: orderId,
|
|
57
|
+
paymentSessionId: response.data.payment_session_id,
|
|
58
|
+
orderStatus: response.data.order_status,
|
|
59
|
+
amount: orderData.order_amount,
|
|
60
|
+
currency: orderData.order_currency,
|
|
61
|
+
// Payment link construction
|
|
62
|
+
url: `${this.baseURL}/checkout?order_id=${orderId}&payment_session_id=${response.data.payment_session_id}`
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
} else {
|
|
66
|
+
throw new Error('Order creation failed');
|
|
67
|
+
}
|
|
68
|
+
} catch (error) {
|
|
69
|
+
throw new Error(`Payment creation error: ${error.response?.data?.message || error.message}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async handleCallback(callbackData) {
|
|
74
|
+
try {
|
|
75
|
+
const verification = await this.verifyCallback(callbackData);
|
|
76
|
+
|
|
77
|
+
if (!verification.status) {
|
|
78
|
+
throw new Error(verification.error.message);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const orderId = callbackData.order_id || callbackData.orderId;
|
|
82
|
+
|
|
83
|
+
// Get order details
|
|
84
|
+
const order = await this.getOrder(orderId);
|
|
85
|
+
|
|
86
|
+
// Status mapping
|
|
87
|
+
const statusMapping = {
|
|
88
|
+
'PAID': 'success',
|
|
89
|
+
'ACTIVE': 'pending',
|
|
90
|
+
'EXPIRED': 'failed',
|
|
91
|
+
'TERMINATED': 'failed',
|
|
92
|
+
'PENDING': 'pending'
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
status: statusMapping[order.order_status] || 'unknown',
|
|
97
|
+
orderId: order.order_id,
|
|
98
|
+
transactionId: order.cf_order_id,
|
|
99
|
+
amount: parseFloat(order.order_amount),
|
|
100
|
+
currency: order.order_currency,
|
|
101
|
+
paymentStatus: order.order_status,
|
|
102
|
+
paymentMethod: order.payment_method
|
|
103
|
+
};
|
|
104
|
+
} catch (error) {
|
|
105
|
+
throw new Error(`Error in Cashfree callback handling: ${error.message}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async verifyCallback(data) {
|
|
110
|
+
try {
|
|
111
|
+
// Verify signature if present
|
|
112
|
+
if (data.signature) {
|
|
113
|
+
const { signature, ...callbackData } = data;
|
|
114
|
+
const signatureString = Object.keys(callbackData)
|
|
115
|
+
.sort()
|
|
116
|
+
.map(key => `${key}=${callbackData[key]}`)
|
|
117
|
+
.join('&');
|
|
118
|
+
|
|
119
|
+
const expectedSignature = crypto
|
|
120
|
+
.createHmac('sha256', this.secretKey)
|
|
121
|
+
.update(signatureString)
|
|
122
|
+
.digest('hex');
|
|
123
|
+
|
|
124
|
+
if (signature !== expectedSignature) {
|
|
125
|
+
return {
|
|
126
|
+
status: false,
|
|
127
|
+
error: {
|
|
128
|
+
code: 401,
|
|
129
|
+
message: 'Invalid signature'
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
status: true,
|
|
137
|
+
data: data
|
|
138
|
+
};
|
|
139
|
+
} catch (error) {
|
|
140
|
+
return {
|
|
141
|
+
status: false,
|
|
142
|
+
error: {
|
|
143
|
+
code: 500,
|
|
144
|
+
message: error.message
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async getOrder(orderId) {
|
|
151
|
+
try {
|
|
152
|
+
const response = await this.client.get(`/orders/${orderId}`);
|
|
153
|
+
return response.data;
|
|
154
|
+
} catch (error) {
|
|
155
|
+
throw new Error(`Error fetching order: ${error.response?.data?.message || error.message}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async getPayments(orderId) {
|
|
160
|
+
try {
|
|
161
|
+
const response = await this.client.get(`/orders/${orderId}/payments`);
|
|
162
|
+
return response.data;
|
|
163
|
+
} catch (error) {
|
|
164
|
+
throw new Error(`Error fetching payments: ${error.response?.data?.message || error.message}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async refundPayment(orderId, options = {}) {
|
|
169
|
+
try {
|
|
170
|
+
const refundData = {
|
|
171
|
+
refund_amount: options.amount,
|
|
172
|
+
refund_id: options.refundId || `refund_${Date.now()}`,
|
|
173
|
+
refund_note: options.note || 'Refund'
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const response = await this.client.post(`/orders/${orderId}/refunds`, refundData);
|
|
177
|
+
return response.data;
|
|
178
|
+
} catch (error) {
|
|
179
|
+
throw new Error(`Error creating refund: ${error.response?.data?.message || error.message}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
module.exports = CashfreeClient;
|