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/paynettr.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const crypto = require('crypto');
|
|
3
|
+
|
|
4
|
+
class PayNetTRClient {
|
|
5
|
+
constructor(config) {
|
|
6
|
+
const requiredFields = ['merchantId', '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.secretKey = config.secretKey;
|
|
13
|
+
this.baseURL = 'https://api.paynet.com.tr';
|
|
14
|
+
|
|
15
|
+
this.client = axios.create({
|
|
16
|
+
baseURL: this.baseURL,
|
|
17
|
+
headers: {
|
|
18
|
+
'Content-Type': 'application/json'
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
generateSignature(data) {
|
|
24
|
+
const signatureString = Object.keys(data)
|
|
25
|
+
.filter(key => key !== 'signature')
|
|
26
|
+
.sort()
|
|
27
|
+
.map(key => `${key}=${data[key]}`)
|
|
28
|
+
.join('&');
|
|
29
|
+
|
|
30
|
+
return crypto
|
|
31
|
+
.createHmac('sha256', this.secretKey)
|
|
32
|
+
.update(signatureString)
|
|
33
|
+
.digest('hex')
|
|
34
|
+
.toUpperCase();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async createPayment(options) {
|
|
38
|
+
try {
|
|
39
|
+
const orderId = options.orderId || `ORDER-${Date.now()}`;
|
|
40
|
+
const amount = parseFloat(options.amount) * 100; // Kuruş cinsine çevir
|
|
41
|
+
|
|
42
|
+
const paymentData = {
|
|
43
|
+
merchant_id: this.merchantId,
|
|
44
|
+
order_id: orderId,
|
|
45
|
+
amount: amount,
|
|
46
|
+
currency: options.currency || 'TRY',
|
|
47
|
+
description: options.description || options.name || 'Payment',
|
|
48
|
+
success_url: options.successUrl || options.callback_link,
|
|
49
|
+
fail_url: options.failUrl || options.callback_link,
|
|
50
|
+
callback_url: options.callbackUrl || options.callback_link,
|
|
51
|
+
customer_email: options.email || '',
|
|
52
|
+
customer_name: options.name || '',
|
|
53
|
+
customer_phone: options.phone || ''
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
paymentData.signature = this.generateSignature(paymentData);
|
|
57
|
+
|
|
58
|
+
const response = await this.client.post('/api/v1/payment', paymentData);
|
|
59
|
+
|
|
60
|
+
if (response.data.success) {
|
|
61
|
+
return {
|
|
62
|
+
status: 'success',
|
|
63
|
+
data: {
|
|
64
|
+
url: response.data.payment_url,
|
|
65
|
+
orderId: orderId,
|
|
66
|
+
paymentId: response.data.payment_id,
|
|
67
|
+
amount: amount / 100,
|
|
68
|
+
currency: paymentData.currency
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
} else {
|
|
72
|
+
throw new Error(response.data.message || 'Payment creation failed');
|
|
73
|
+
}
|
|
74
|
+
} catch (error) {
|
|
75
|
+
throw new Error(`Payment creation error: ${error.response?.data?.message || error.message}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async handleCallback(callbackData) {
|
|
80
|
+
try {
|
|
81
|
+
const verification = await this.verifyCallback(callbackData);
|
|
82
|
+
|
|
83
|
+
if (!verification.status) {
|
|
84
|
+
throw new Error(verification.error.message);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const data = verification.data;
|
|
88
|
+
|
|
89
|
+
// Status mapping
|
|
90
|
+
const statusMapping = {
|
|
91
|
+
'success': 'success',
|
|
92
|
+
'completed': 'success',
|
|
93
|
+
'approved': 'success',
|
|
94
|
+
'failed': 'failed',
|
|
95
|
+
'declined': 'failed',
|
|
96
|
+
'cancelled': 'failed',
|
|
97
|
+
'pending': 'pending',
|
|
98
|
+
'processing': 'pending'
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
status: statusMapping[data.status] || 'unknown',
|
|
103
|
+
orderId: data.order_id,
|
|
104
|
+
transactionId: data.payment_id || data.transaction_id,
|
|
105
|
+
amount: parseFloat(data.amount) / 100,
|
|
106
|
+
currency: data.currency,
|
|
107
|
+
paymentStatus: data.status,
|
|
108
|
+
paymentMethod: data.payment_method
|
|
109
|
+
};
|
|
110
|
+
} catch (error) {
|
|
111
|
+
throw new Error(`Error in PayNetTR callback handling: ${error.message}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async verifyCallback(data) {
|
|
116
|
+
try {
|
|
117
|
+
const receivedSign = data.signature;
|
|
118
|
+
const dataToVerify = { ...data };
|
|
119
|
+
delete dataToVerify.signature;
|
|
120
|
+
|
|
121
|
+
const expectedSign = this.generateSignature(dataToVerify);
|
|
122
|
+
|
|
123
|
+
if (receivedSign !== expectedSign) {
|
|
124
|
+
return {
|
|
125
|
+
status: false,
|
|
126
|
+
error: {
|
|
127
|
+
code: 401,
|
|
128
|
+
message: 'Invalid signature'
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
status: true,
|
|
135
|
+
data: data
|
|
136
|
+
};
|
|
137
|
+
} catch (error) {
|
|
138
|
+
return {
|
|
139
|
+
status: false,
|
|
140
|
+
error: {
|
|
141
|
+
code: 500,
|
|
142
|
+
message: error.message
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async getPaymentStatus(paymentId) {
|
|
149
|
+
try {
|
|
150
|
+
const data = {
|
|
151
|
+
merchant_id: this.merchantId,
|
|
152
|
+
payment_id: paymentId
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
data.signature = this.generateSignature(data);
|
|
156
|
+
|
|
157
|
+
const response = await this.client.post('/api/v1/payment/status', data);
|
|
158
|
+
return response.data;
|
|
159
|
+
} catch (error) {
|
|
160
|
+
throw new Error(`Error getting payment status: ${error.response?.data?.message || error.message}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
module.exports = PayNetTRClient;
|
package/lib/payoneer.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const crypto = require('crypto');
|
|
3
|
+
|
|
4
|
+
class PayoneerClient {
|
|
5
|
+
constructor(config) {
|
|
6
|
+
const requiredFields = ['programId', 'username', 'password'];
|
|
7
|
+
for (let field of requiredFields) {
|
|
8
|
+
if (!config[field]) throw new Error(`Missing required field: ${field}`);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
this.programId = config.programId;
|
|
12
|
+
this.username = config.username;
|
|
13
|
+
this.password = config.password;
|
|
14
|
+
this.baseURL = config.sandbox
|
|
15
|
+
? 'https://api.sandbox.payoneer.com'
|
|
16
|
+
: 'https://api.payoneer.com';
|
|
17
|
+
|
|
18
|
+
this.client = axios.create({
|
|
19
|
+
baseURL: this.baseURL,
|
|
20
|
+
auth: {
|
|
21
|
+
username: this.username,
|
|
22
|
+
password: this.password
|
|
23
|
+
},
|
|
24
|
+
headers: {
|
|
25
|
+
'Content-Type': 'application/json'
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async createPayment(options) {
|
|
31
|
+
try {
|
|
32
|
+
const payeeId = options.payeeId || options.email;
|
|
33
|
+
const orderId = options.orderId || `ORDER-${Date.now()}`;
|
|
34
|
+
|
|
35
|
+
const paymentData = {
|
|
36
|
+
program_id: this.programId,
|
|
37
|
+
payee_id: payeeId,
|
|
38
|
+
payment_id: orderId,
|
|
39
|
+
amount: parseFloat(options.amount),
|
|
40
|
+
currency: options.currency || 'USD',
|
|
41
|
+
description: options.description || options.name || 'Payment',
|
|
42
|
+
payee_email: options.email,
|
|
43
|
+
payee_first_name: options.firstName || '',
|
|
44
|
+
payee_last_name: options.lastName || ''
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const response = await this.client.post('/v2/payments', paymentData);
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
status: 'success',
|
|
51
|
+
data: {
|
|
52
|
+
paymentId: orderId,
|
|
53
|
+
payeeId: payeeId,
|
|
54
|
+
amount: paymentData.amount,
|
|
55
|
+
currency: paymentData.currency,
|
|
56
|
+
status: response.data.status,
|
|
57
|
+
paymentStatus: response.data.payment_status
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
} catch (error) {
|
|
61
|
+
throw new Error(`Payment creation error: ${error.response?.data?.error || error.message}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async handleCallback(callbackData) {
|
|
66
|
+
try {
|
|
67
|
+
// Payoneer typically doesn't use callbacks but status checks
|
|
68
|
+
const paymentId = callbackData.payment_id || callbackData.paymentId;
|
|
69
|
+
|
|
70
|
+
if (!paymentId) {
|
|
71
|
+
throw new Error('Payment ID not found in callback data');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Get payment status
|
|
75
|
+
const payment = await this.getPaymentStatus(paymentId);
|
|
76
|
+
|
|
77
|
+
// Status mapping
|
|
78
|
+
const statusMapping = {
|
|
79
|
+
'Done': 'success',
|
|
80
|
+
'Completed': 'success',
|
|
81
|
+
'Pending': 'pending',
|
|
82
|
+
'Canceled': 'failed',
|
|
83
|
+
'Failed': 'failed'
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
status: statusMapping[payment.status] || 'unknown',
|
|
88
|
+
orderId: payment.payment_id,
|
|
89
|
+
transactionId: payment.payment_id,
|
|
90
|
+
amount: parseFloat(payment.amount),
|
|
91
|
+
currency: payment.currency,
|
|
92
|
+
paymentStatus: payment.status,
|
|
93
|
+
payeeId: payment.payee_id
|
|
94
|
+
};
|
|
95
|
+
} catch (error) {
|
|
96
|
+
throw new Error(`Error in Payoneer callback handling: ${error.message}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async getPaymentStatus(paymentId) {
|
|
101
|
+
try {
|
|
102
|
+
const response = await this.client.get(`/v2/payments/${paymentId}`);
|
|
103
|
+
return response.data;
|
|
104
|
+
} catch (error) {
|
|
105
|
+
throw new Error(`Error getting payment status: ${error.response?.data?.error || error.message}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async getPayeeDetails(payeeId) {
|
|
110
|
+
try {
|
|
111
|
+
const response = await this.client.get(`/v2/payees/${payeeId}`);
|
|
112
|
+
return response.data;
|
|
113
|
+
} catch (error) {
|
|
114
|
+
throw new Error(`Error getting payee details: ${error.response?.data?.error || error.message}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async cancelPayment(paymentId) {
|
|
119
|
+
try {
|
|
120
|
+
const response = await this.client.delete(`/v2/payments/${paymentId}`);
|
|
121
|
+
return response.data;
|
|
122
|
+
} catch (error) {
|
|
123
|
+
throw new Error(`Error canceling payment: ${error.response?.data?.error || error.message}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
module.exports = PayoneerClient;
|
package/lib/payop.js
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payop - JavaScript client for Payop payment service
|
|
3
|
+
* Based on documentation: https://github.com/Payop/payop-api-doc
|
|
4
|
+
*/
|
|
5
|
+
class Payop {
|
|
6
|
+
/**
|
|
7
|
+
* Create a new Payop client
|
|
8
|
+
* @param {Object} config - Configuration options
|
|
9
|
+
* @param {string} config.publicKey - Public key for merchant identification
|
|
10
|
+
* @param {string} config.secretKey - Secret key for signing requests
|
|
11
|
+
* @param {string} [config.environment] - API environment ('production' or 'sandbox')
|
|
12
|
+
*/
|
|
13
|
+
constructor(config) {
|
|
14
|
+
this.config = {
|
|
15
|
+
environment: 'production',
|
|
16
|
+
...config
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
this.baseUrl = this.config.environment === 'sandbox'
|
|
20
|
+
? 'https://payop.com/api/v1'
|
|
21
|
+
: 'https://payop.com/api/v1';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Generate a unique identifier
|
|
26
|
+
* @returns {string} - Unique ID
|
|
27
|
+
*/
|
|
28
|
+
generateUniqueId() {
|
|
29
|
+
return require('crypto').randomBytes(16).toString('hex');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Calculate a signature for Payop requests
|
|
34
|
+
* @param {Object} data - Data to sign
|
|
35
|
+
* @returns {string} - Signature
|
|
36
|
+
*/
|
|
37
|
+
createSignature(data) {
|
|
38
|
+
const stringToSign = this._createStringToSign(data);
|
|
39
|
+
return require('crypto')
|
|
40
|
+
.createHash('sha256')
|
|
41
|
+
.update(stringToSign)
|
|
42
|
+
.digest('hex');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Create string to sign from data object
|
|
47
|
+
* @param {Object} data - Data object
|
|
48
|
+
* @returns {string} - String to sign
|
|
49
|
+
* @private
|
|
50
|
+
*/
|
|
51
|
+
_createStringToSign(data) {
|
|
52
|
+
// According to Payop docs, we need to sort the data,
|
|
53
|
+
// concatenate everything except the 'signature' field,
|
|
54
|
+
// and then hash it
|
|
55
|
+
const sortedKeys = Object.keys(data).sort();
|
|
56
|
+
return sortedKeys
|
|
57
|
+
.filter(key => key !== 'signature' && data[key] !== null && data[key] !== undefined)
|
|
58
|
+
.map(key => data[key])
|
|
59
|
+
.join(':');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Make an authenticated API request to Payop
|
|
64
|
+
* @param {string} endpoint - API endpoint
|
|
65
|
+
* @param {Object} data - Request data
|
|
66
|
+
* @param {string} method - HTTP method
|
|
67
|
+
* @returns {Promise<Object>} - Response data
|
|
68
|
+
*/
|
|
69
|
+
async makeRequest(endpoint, data = {}, method = 'POST') {
|
|
70
|
+
try {
|
|
71
|
+
const url = `${this.baseUrl}${endpoint}`;
|
|
72
|
+
|
|
73
|
+
const options = {
|
|
74
|
+
method,
|
|
75
|
+
headers: {
|
|
76
|
+
'Content-Type': 'application/json',
|
|
77
|
+
'Accept': 'application/json',
|
|
78
|
+
'X-API-KEY': this.config.publicKey
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
if (method !== 'GET' && data) {
|
|
83
|
+
options.body = JSON.stringify(data);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const response = await fetch(url, options);
|
|
87
|
+
const result = await response.json();
|
|
88
|
+
|
|
89
|
+
if (!response.ok) {
|
|
90
|
+
throw new Error(`Payop API error: ${JSON.stringify(result)}`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return result;
|
|
94
|
+
} catch (error) {
|
|
95
|
+
throw new Error(`Payop API request failed: ${error.message}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Create a checkout invoice
|
|
101
|
+
* @param {Object} options - Invoice options
|
|
102
|
+
* @param {string} options.order - Order ID in your system
|
|
103
|
+
* @param {number} options.amount - Payment amount
|
|
104
|
+
* @param {string} options.currency - Payment currency (3-letter code)
|
|
105
|
+
* @param {string} options.description - Payment description
|
|
106
|
+
* @param {Object} options.customer - Customer information (email, name, etc)
|
|
107
|
+
* @param {string} options.resultUrl - URL to redirect after payment
|
|
108
|
+
* @param {string} options.failPath - URL to redirect after failed payment
|
|
109
|
+
* @param {Object[]} [options.products] - Products information
|
|
110
|
+
* @returns {Promise<Object>} - Created invoice data
|
|
111
|
+
*/
|
|
112
|
+
async createInvoice(options) {
|
|
113
|
+
const data = {
|
|
114
|
+
publicKey: this.config.publicKey,
|
|
115
|
+
order: {
|
|
116
|
+
id: options.order,
|
|
117
|
+
amount: options.amount,
|
|
118
|
+
currency: options.currency,
|
|
119
|
+
description: options.description,
|
|
120
|
+
items: options.products || []
|
|
121
|
+
},
|
|
122
|
+
customer: options.customer,
|
|
123
|
+
resultUrl: options.resultUrl,
|
|
124
|
+
failPath: options.failPath
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
// Calculate and add signature
|
|
128
|
+
const signature = this.createSignature({
|
|
129
|
+
id: data.order.id,
|
|
130
|
+
amount: data.order.amount,
|
|
131
|
+
currency: data.order.currency
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
data.signature = signature;
|
|
135
|
+
|
|
136
|
+
return this.makeRequest('/checkout/create', data);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Get invoice status
|
|
141
|
+
* @param {string} invoiceId - Invoice ID
|
|
142
|
+
* @returns {Promise<Object>} - Invoice status information
|
|
143
|
+
*/
|
|
144
|
+
async getInvoice(invoiceId) {
|
|
145
|
+
return this.makeRequest(`/checkout/invoice/${invoiceId}`, null, 'GET');
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Get transaction information
|
|
150
|
+
* @param {string} transactionId - Transaction ID
|
|
151
|
+
* @returns {Promise<Object>} - Transaction information
|
|
152
|
+
*/
|
|
153
|
+
async getTransaction(transactionId) {
|
|
154
|
+
return this.makeRequest(`/transaction/${transactionId}`, null, 'GET');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Get available payment methods
|
|
159
|
+
* @param {string} currency - Currency code (e.g., 'USD')
|
|
160
|
+
* @returns {Promise<Object>} - Available payment methods
|
|
161
|
+
*/
|
|
162
|
+
async getPaymentMethods(currency) {
|
|
163
|
+
return this.makeRequest(`/instrument-settings/payment-methods/${currency}`, null, 'GET');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Issue a refund
|
|
168
|
+
* @param {Object} options - Refund options
|
|
169
|
+
* @param {string} options.transactionId - Transaction ID
|
|
170
|
+
* @param {number} options.amount - Refund amount
|
|
171
|
+
* @param {string} [options.currency] - Refund currency
|
|
172
|
+
* @param {string} [options.description] - Refund description
|
|
173
|
+
* @returns {Promise<Object>} - Refund result
|
|
174
|
+
*/
|
|
175
|
+
async refund(options) {
|
|
176
|
+
const data = {
|
|
177
|
+
transactionId: options.transactionId,
|
|
178
|
+
amount: options.amount
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
if (options.currency) data.currency = options.currency;
|
|
182
|
+
if (options.description) data.description = options.description;
|
|
183
|
+
|
|
184
|
+
return this.makeRequest('/refund/create', data);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Verify IPN (Instant Payment Notification) from Payop
|
|
189
|
+
* @param {Object} notification - Notification data received from Payop
|
|
190
|
+
* @returns {boolean} - True if notification is valid
|
|
191
|
+
*/
|
|
192
|
+
verifyNotification(notification) {
|
|
193
|
+
if (!notification || !notification.signature) {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const receivedSignature = notification.signature;
|
|
198
|
+
const calculatedSignature = this.createSignature({
|
|
199
|
+
id: notification.transaction.id,
|
|
200
|
+
amount: notification.transaction.amount,
|
|
201
|
+
currency: notification.transaction.currency
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
return receivedSignature === calculatedSignature;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Create a payout
|
|
209
|
+
* @param {Object} options - Payout options
|
|
210
|
+
* @param {string} options.method - Payout method ID
|
|
211
|
+
* @param {number} options.amount - Payout amount
|
|
212
|
+
* @param {string} options.currency - Payout currency
|
|
213
|
+
* @param {Object} options.recipient - Recipient information
|
|
214
|
+
* @param {string} [options.metadata] - Additional payout metadata
|
|
215
|
+
* @returns {Promise<Object>} - Payout result
|
|
216
|
+
*/
|
|
217
|
+
async createPayout(options) {
|
|
218
|
+
const data = {
|
|
219
|
+
method: options.method,
|
|
220
|
+
amount: options.amount,
|
|
221
|
+
currency: options.currency,
|
|
222
|
+
recipient: options.recipient
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
if (options.metadata) data.metadata = options.metadata;
|
|
226
|
+
|
|
227
|
+
// Calculate and add signature
|
|
228
|
+
const signature = this.createSignature({
|
|
229
|
+
amount: data.amount,
|
|
230
|
+
currency: data.currency
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
data.signature = signature;
|
|
234
|
+
|
|
235
|
+
return this.makeRequest('/payouts/create', data);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Get available payout methods
|
|
240
|
+
* @returns {Promise<Object>} - Available payout methods
|
|
241
|
+
*/
|
|
242
|
+
async getPayoutMethods() {
|
|
243
|
+
return this.makeRequest('/payouts/methods', null, 'GET');
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Check payout status
|
|
248
|
+
* @param {string} payoutId - Payout ID
|
|
249
|
+
* @returns {Promise<Object>} - Payout status
|
|
250
|
+
*/
|
|
251
|
+
async getPayoutStatus(payoutId) {
|
|
252
|
+
return this.makeRequest(`/payouts/${payoutId}`, null, 'GET');
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
module.exports = Payop;
|