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.
Files changed (131) hide show
  1. package/PROVIDERS-DETAILS.md +1544 -0
  2. package/examples/example-2checkout.js +78 -0
  3. package/examples/example-bitpay.js +83 -0
  4. package/examples/example-cardcom.js +80 -0
  5. package/examples/example-cashfree.js +109 -0
  6. package/examples/example-checkout.js +85 -0
  7. package/examples/example-coingate.js +101 -0
  8. package/examples/example-coinpayments.js +89 -0
  9. package/examples/example-doku.js +27 -0
  10. package/examples/example-epay.js +64 -0
  11. package/examples/example-epoint.js +91 -0
  12. package/examples/example-freekassa.js +26 -0
  13. package/examples/example-heleket.js +139 -0
  14. package/examples/example-konnect.js +227 -0
  15. package/examples/example-midtrans.js +80 -0
  16. package/examples/example-noonpayments.js +297 -0
  17. package/examples/example-nowpayments.js +289 -0
  18. package/examples/example-omise.js +27 -0
  19. package/examples/example-paycom.js +82 -0
  20. package/{example-paydisini.js → examples/example-paydisini.js} +1 -1
  21. package/examples/example-payid19.js +87 -0
  22. package/examples/example-paykun.js +29 -0
  23. package/examples/example-payme.js +202 -0
  24. package/examples/example-paymentwall.js +201 -0
  25. package/examples/example-paynet.js +104 -0
  26. package/examples/example-paynettr.js +18 -0
  27. package/examples/example-payoneer.js +74 -0
  28. package/examples/example-payop.js +351 -0
  29. package/examples/example-paypal.js +200 -0
  30. package/examples/example-payriff.js +89 -0
  31. package/examples/example-paysend.js +81 -0
  32. package/examples/example-payspace.js +103 -0
  33. package/examples/example-payssion.js +27 -0
  34. package/examples/example-paytabs.js +28 -0
  35. package/examples/example-paytm.js +78 -0
  36. package/examples/example-payuindia.js +108 -0
  37. package/examples/example-payulatam.js +75 -0
  38. package/examples/example-phonepe.js +27 -0
  39. package/examples/example-picpay.js +27 -0
  40. package/examples/example-plisio.js +84 -0
  41. package/examples/example-portwallet.js +90 -0
  42. package/examples/example-primepayments.js +250 -0
  43. package/examples/example-razorpay.js +30 -0
  44. package/examples/example-senangpay.js +28 -0
  45. package/examples/example-shurjopay.js +94 -0
  46. package/examples/example-toyyibpay.js +80 -0
  47. package/examples/example-tripay.js +89 -0
  48. package/examples/example-unitpay.js +26 -0
  49. package/examples/example-urway.js +28 -0
  50. package/examples/example-volet.js +80 -0
  51. package/examples/example-xendit.js +28 -0
  52. package/examples/example-yallapay.js +253 -0
  53. package/examples/example-yookassa.js +27 -0
  54. package/examples/example-youcanpay.js +28 -0
  55. package/examples/example-zarinpal.js +98 -0
  56. package/{example.js → examples/example.js} +1 -1
  57. package/lib/2checkout.js +165 -0
  58. package/lib/amazonpay.js +161 -0
  59. package/lib/bitpay.js +122 -0
  60. package/lib/cardcom.js +193 -0
  61. package/lib/cashfree.js +184 -0
  62. package/lib/checkout.js +248 -0
  63. package/lib/coinbase.js +150 -0
  64. package/lib/coingate.js +137 -0
  65. package/lib/coinpayments.js +245 -0
  66. package/lib/doku.js +173 -0
  67. package/lib/epay.js +175 -0
  68. package/lib/epoint.js +162 -0
  69. package/lib/freekassa.js +128 -0
  70. package/lib/heleket.js +67 -1
  71. package/lib/instamojo.js +158 -0
  72. package/lib/konnect.js +211 -0
  73. package/lib/midtrans.js +227 -0
  74. package/lib/noonpayments.js +650 -0
  75. package/lib/nowpayments.js +311 -0
  76. package/lib/omise.js +150 -0
  77. package/lib/paddle.js +180 -0
  78. package/lib/paycom.js +216 -0
  79. package/lib/payid19.js +211 -0
  80. package/lib/paykun.js +144 -0
  81. package/lib/payme.js +302 -0
  82. package/lib/paymentwall.js +205 -0
  83. package/lib/paynet.js +186 -0
  84. package/lib/paynettr.js +165 -0
  85. package/lib/payoneer.js +128 -0
  86. package/lib/payop.js +256 -0
  87. package/lib/paypal.js +542 -0
  88. package/lib/payriff.js +148 -0
  89. package/lib/paysend.js +189 -0
  90. package/lib/payspace.js +168 -0
  91. package/lib/payssion.js +177 -0
  92. package/lib/paytabs.js +145 -0
  93. package/lib/paytm.js +253 -0
  94. package/lib/payuindia.js +162 -0
  95. package/lib/payulatam.js +179 -0
  96. package/lib/perfectmoney.js +143 -0
  97. package/lib/phonepe.js +174 -0
  98. package/lib/picpay.js +119 -0
  99. package/lib/plisio.js +234 -0
  100. package/lib/portwallet.js +152 -0
  101. package/lib/primepayments.js +256 -0
  102. package/lib/razorpay.js +205 -0
  103. package/lib/senangpay.js +130 -0
  104. package/lib/shurjopay.js +159 -0
  105. package/lib/toyyibpay.js +151 -0
  106. package/lib/tripay.js +220 -0
  107. package/lib/unitpay.js +223 -0
  108. package/lib/urway.js +182 -0
  109. package/lib/volet.js +147 -0
  110. package/lib/xendit.js +206 -0
  111. package/lib/yallapay.js +279 -0
  112. package/lib/yookassa.js +193 -0
  113. package/lib/youcanpay.js +124 -0
  114. package/lib/zarinpal.js +157 -0
  115. package/package.json +138 -64
  116. package/readme.md +348 -105
  117. package/test.js +492 -0
  118. package/example-heleket.js +0 -83
  119. package/lib/vallet.js +0 -22
  120. /package/{example-anypay.js → examples/example-anypay.js} +0 -0
  121. /package/{example-bufpay.js → examples/example-bufpay.js} +0 -0
  122. /package/{example-cryptomus.js → examples/example-cryptomus.js} +0 -0
  123. /package/{example-esnekpos.js → examples/example-esnekpos.js} +0 -0
  124. /package/{example-fedapay.js → examples/example-fedapay.js} +0 -0
  125. /package/{example-iyzico.js → examples/example-iyzico.js} +0 -0
  126. /package/{example-papara.js → examples/example-papara.js} +0 -0
  127. /package/{example-payeer.js → examples/example-payeer.js} +0 -0
  128. /package/{example-paymaya.js → examples/example-paymaya.js} +0 -0
  129. /package/{example-shopier.js → examples/example-shopier.js} +0 -0
  130. /package/{ipaymu.js → examples/ipaymu.js} +0 -0
  131. /package/{oderopay.js → examples/oderopay.js} +0 -0
package/lib/unitpay.js ADDED
@@ -0,0 +1,223 @@
1
+ const axios = require('axios');
2
+ const crypto = require('crypto');
3
+
4
+ class UnitpayClient {
5
+ constructor(config) {
6
+ const requiredFields = ['publicKey', 'secretKey'];
7
+ for (let field of requiredFields) {
8
+ if (!config[field]) throw new Error(`Missing required field: ${field}`);
9
+ }
10
+
11
+ this.publicKey = config.publicKey;
12
+ this.secretKey = config.secretKey;
13
+ this.domain = config.domain || 'unitpay.ru';
14
+ this.baseURL = `https://${this.domain}/api`;
15
+
16
+ this.client = axios.create({
17
+ baseURL: this.baseURL,
18
+ headers: {
19
+ 'Content-Type': 'application/json'
20
+ }
21
+ });
22
+ }
23
+
24
+ generateSignature(params) {
25
+ const sorted = Object.keys(params).sort().reduce((acc, key) => {
26
+ if (params[key] !== undefined && params[key] !== null) {
27
+ acc[key] = params[key];
28
+ }
29
+ return acc;
30
+ }, {});
31
+
32
+ const signatureString = Object.entries(sorted)
33
+ .map(([key, value]) => value)
34
+ .join('{up}');
35
+
36
+ return crypto
37
+ .createHash('sha256')
38
+ .update(signatureString + '{up}' + this.secretKey)
39
+ .digest('hex');
40
+ }
41
+
42
+ async createPayment(options) {
43
+ try {
44
+ const orderId = options.orderId || `ORDER-${Date.now()}`;
45
+
46
+ const params = {
47
+ account: options.account || orderId,
48
+ sum: parseFloat(options.amount).toFixed(2),
49
+ desc: options.description || options.name || 'Payment',
50
+ currency: options.currency || 'RUB',
51
+ resultUrl: options.callbackUrl || options.callback_link,
52
+ successUrl: options.successUrl || options.callback_link,
53
+ errorUrl: options.failureUrl || options.callback_link,
54
+ customerEmail: options.email || '',
55
+ customerPhone: options.phone || '',
56
+ locale: options.locale || 'ru'
57
+ };
58
+
59
+ params.signature = this.generateSignature({
60
+ account: params.account,
61
+ currency: params.currency,
62
+ desc: params.desc,
63
+ sum: params.sum
64
+ });
65
+
66
+ // Create payment URL
67
+ const paymentUrl = `https://${this.domain}/pay/${this.publicKey}?` +
68
+ new URLSearchParams(params).toString();
69
+
70
+ return {
71
+ status: 'success',
72
+ data: {
73
+ url: paymentUrl,
74
+ orderId: orderId,
75
+ account: params.account,
76
+ amount: params.sum,
77
+ currency: params.currency
78
+ }
79
+ };
80
+ } catch (error) {
81
+ throw new Error(`Payment creation error: ${error.message}`);
82
+ }
83
+ }
84
+
85
+ async handleCallback(callbackData) {
86
+ try {
87
+ const method = callbackData.method;
88
+ const params = callbackData.params || callbackData;
89
+
90
+ // Verify signature
91
+ const verification = await this.verifyCallback(params, method);
92
+
93
+ if (!verification.status) {
94
+ throw new Error(verification.error.message);
95
+ }
96
+
97
+ // Handle different methods
98
+ if (method === 'check') {
99
+ // Payment check - validate order
100
+ return {
101
+ status: 'pending',
102
+ orderId: params.account,
103
+ message: 'Order validation'
104
+ };
105
+ } else if (method === 'pay') {
106
+ // Payment successful
107
+ return {
108
+ status: 'success',
109
+ orderId: params.account,
110
+ transactionId: params.unitpayId,
111
+ amount: parseFloat(params.orderSum),
112
+ currency: params.orderCurrency || 'RUB',
113
+ paymentStatus: 'completed',
114
+ paymentType: params.paymentType,
115
+ profit: parseFloat(params.profit || 0)
116
+ };
117
+ } else if (method === 'error') {
118
+ // Payment error
119
+ return {
120
+ status: 'failed',
121
+ orderId: params.account,
122
+ message: params.message || 'Payment failed'
123
+ };
124
+ } else if (method === 'refund') {
125
+ // Refund notification
126
+ return {
127
+ status: 'refunded',
128
+ orderId: params.account,
129
+ transactionId: params.unitpayId,
130
+ amount: parseFloat(params.orderSum)
131
+ };
132
+ }
133
+
134
+ throw new Error(`Unknown method: ${method}`);
135
+ } catch (error) {
136
+ throw new Error(`Error in Unitpay callback handling: ${error.message}`);
137
+ }
138
+ }
139
+
140
+ async verifyCallback(params, method) {
141
+ try {
142
+ const receivedSignature = params.signature;
143
+
144
+ let signatureParams;
145
+ if (method === 'check') {
146
+ signatureParams = {
147
+ account: params.account,
148
+ orderSum: params.orderSum,
149
+ orderCurrency: params.orderCurrency,
150
+ method: method
151
+ };
152
+ } else if (method === 'pay') {
153
+ signatureParams = {
154
+ account: params.account,
155
+ orderSum: params.orderSum,
156
+ orderCurrency: params.orderCurrency,
157
+ profit: params.profit,
158
+ method: method
159
+ };
160
+ } else if (method === 'refund') {
161
+ signatureParams = {
162
+ account: params.account,
163
+ orderSum: params.orderSum,
164
+ method: method
165
+ };
166
+ } else {
167
+ signatureParams = params;
168
+ }
169
+
170
+ const expectedSignature = this.generateSignature(signatureParams);
171
+
172
+ if (receivedSignature !== expectedSignature) {
173
+ return {
174
+ status: false,
175
+ error: {
176
+ code: 401,
177
+ message: 'Invalid signature'
178
+ }
179
+ };
180
+ }
181
+
182
+ return {
183
+ status: true,
184
+ data: params
185
+ };
186
+ } catch (error) {
187
+ return {
188
+ status: false,
189
+ error: {
190
+ code: 500,
191
+ message: error.message
192
+ }
193
+ };
194
+ }
195
+ }
196
+
197
+ async initPayment(options) {
198
+ try {
199
+ // API method to init payment and get payment ID
200
+ const params = {
201
+ account: options.account || options.orderId || `ORDER-${Date.now()}`,
202
+ sum: parseFloat(options.amount).toFixed(2),
203
+ projectId: this.publicKey,
204
+ desc: options.description || 'Payment',
205
+ currency: options.currency || 'RUB',
206
+ resultUrl: options.callbackUrl || options.callback_link,
207
+ secretKey: this.secretKey
208
+ };
209
+
210
+ const response = await this.client.get('/initPayment', { params });
211
+
212
+ if (response.data.result) {
213
+ return response.data.result;
214
+ } else {
215
+ throw new Error(response.data.error?.message || 'Payment initialization failed');
216
+ }
217
+ } catch (error) {
218
+ throw new Error(`Error initializing payment: ${error.response?.data?.error?.message || error.message}`);
219
+ }
220
+ }
221
+ }
222
+
223
+ module.exports = UnitpayClient;
package/lib/urway.js ADDED
@@ -0,0 +1,182 @@
1
+ const axios = require('axios');
2
+ const crypto = require('crypto');
3
+
4
+ class URWayClient {
5
+ constructor(config) {
6
+ const requiredFields = ['terminalId', 'password', 'merchantKey'];
7
+ for (let field of requiredFields) {
8
+ if (!config[field]) throw new Error(`Missing required field: ${field}`);
9
+ }
10
+
11
+ this.terminalId = config.terminalId;
12
+ this.password = config.password;
13
+ this.merchantKey = config.merchantKey;
14
+ this.baseURL = config.testMode
15
+ ? 'https://payments-dev.urway-tech.com/URWAYPGService/transaction/jsonProcess/JSONrequest'
16
+ : 'https://payments.urway-tech.com/URWAYPGService/transaction/jsonProcess/JSONrequest';
17
+
18
+ this.client = axios.create({
19
+ headers: {
20
+ 'Content-Type': 'application/json'
21
+ }
22
+ });
23
+ }
24
+
25
+ generateHash(trackId, amount, currency) {
26
+ const hashString = `${trackId}|${this.terminalId}|${this.password}|${this.merchantKey}|${amount}|${currency}`;
27
+ return crypto.createHash('sha256').update(hashString).digest('hex');
28
+ }
29
+
30
+ async createPayment(options) {
31
+ try {
32
+ const orderId = options.orderId || `ORDER-${Date.now()}`;
33
+ const trackId = options.trackId || orderId;
34
+ const amount = parseFloat(options.amount).toFixed(2);
35
+ const currency = options.currency || 'SAR';
36
+
37
+ const requestHash = this.generateHash(trackId, amount, currency);
38
+
39
+ const paymentData = {
40
+ trackid: trackId,
41
+ terminalId: this.terminalId,
42
+ customerEmail: options.email || '',
43
+ action: '1', // Purchase action
44
+ merchantIp: options.merchantIp || '',
45
+ password: this.password,
46
+ currency: currency,
47
+ country: options.country || 'SA',
48
+ amount: amount,
49
+ requestHash: requestHash,
50
+ udf1: options.udf1 || '',
51
+ udf2: options.udf2 || orderId,
52
+ udf3: options.udf3 || '',
53
+ udf4: options.udf4 || '',
54
+ udf5: options.udf5 || '',
55
+ tokenizationType: options.tokenization || '0'
56
+ };
57
+
58
+ const response = await this.client.post(this.baseURL, paymentData);
59
+
60
+ if (response.data.responseCode === '000') {
61
+ return {
62
+ status: 'success',
63
+ data: {
64
+ url: response.data.paymentUrl || response.data.targetUrl,
65
+ trackId: trackId,
66
+ orderId: orderId,
67
+ amount: amount,
68
+ currency: currency,
69
+ payid: response.data.payid
70
+ }
71
+ };
72
+ } else {
73
+ throw new Error(response.data.responseMessage || 'Payment creation failed');
74
+ }
75
+ } catch (error) {
76
+ throw new Error(`Payment creation error: ${error.response?.data?.responseMessage || error.message}`);
77
+ }
78
+ }
79
+
80
+ async handleCallback(callbackData) {
81
+ try {
82
+ const trackId = callbackData.trackid || callbackData.TrackId;
83
+
84
+ if (!trackId) {
85
+ throw new Error('Track ID not found in callback data');
86
+ }
87
+
88
+ // Verify transaction hash
89
+ const verification = await this.verifyTransaction(callbackData);
90
+
91
+ if (!verification.status) {
92
+ throw new Error(verification.error.message);
93
+ }
94
+
95
+ // Status mapping
96
+ const statusMapping = {
97
+ '000': 'success', // Approved
98
+ '001': 'pending', // In progress
99
+ '100': 'failed', // Declined
100
+ '400': 'failed', // Error
101
+ '401': 'failed' // Invalid
102
+ };
103
+
104
+ return {
105
+ status: statusMapping[callbackData.responseCode] || 'unknown',
106
+ orderId: callbackData.udf2 || trackId,
107
+ trackId: trackId,
108
+ transactionId: callbackData.TranId || callbackData.tranid,
109
+ amount: parseFloat(callbackData.amount),
110
+ currency: callbackData.currency || 'SAR',
111
+ paymentStatus: callbackData.result,
112
+ responseCode: callbackData.responseCode,
113
+ responseMessage: callbackData.responseMessage,
114
+ authCode: callbackData.auth,
115
+ paymentId: callbackData.payid
116
+ };
117
+ } catch (error) {
118
+ throw new Error(`Error in URWay callback handling: ${error.message}`);
119
+ }
120
+ }
121
+
122
+ async verifyTransaction(data) {
123
+ try {
124
+ const receivedHash = data.responseHash;
125
+ const trackId = data.trackid || data.TrackId;
126
+ const amount = data.amount;
127
+ const currency = data.currency || 'SAR';
128
+
129
+ const expectedHash = this.generateHash(trackId, amount, currency);
130
+
131
+ if (receivedHash && receivedHash !== expectedHash) {
132
+ return {
133
+ status: false,
134
+ error: {
135
+ code: 401,
136
+ message: 'Invalid transaction hash'
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 refund(trackId, options = {}) {
157
+ try {
158
+ const amount = parseFloat(options.amount).toFixed(2);
159
+ const currency = options.currency || 'SAR';
160
+
161
+ const requestHash = this.generateHash(trackId, amount, currency);
162
+
163
+ const refundData = {
164
+ trackid: trackId,
165
+ terminalId: this.terminalId,
166
+ password: this.password,
167
+ action: '2', // Refund action
168
+ amount: amount,
169
+ currency: currency,
170
+ requestHash: requestHash
171
+ };
172
+
173
+ const response = await this.client.post(this.baseURL, refundData);
174
+
175
+ return response.data;
176
+ } catch (error) {
177
+ throw new Error(`Error processing refund: ${error.response?.data?.responseMessage || error.message}`);
178
+ }
179
+ }
180
+ }
181
+
182
+ module.exports = URWayClient;
package/lib/volet.js ADDED
@@ -0,0 +1,147 @@
1
+ const axios = require('axios');
2
+ const crypto = require('crypto');
3
+
4
+ class VoletClient {
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.URL = 'https://volet.com/sci';
14
+
15
+ this.client = axios.create({
16
+ baseURL: this.URL,
17
+ headers: {
18
+ 'Content-Type': 'application/x-www-form-urlencoded'
19
+ }
20
+ });
21
+ }
22
+
23
+ generateSignature(data) {
24
+ const signatureString = Object.keys(data)
25
+ .sort()
26
+ .map(key => `${key}=${data[key]}`)
27
+ .join(':');
28
+
29
+ return crypto
30
+ .createHash('md5')
31
+ .update(signatureString + ':' + this.secretKey)
32
+ .digest('hex');
33
+ }
34
+
35
+ async createPayment(options) {
36
+ try {
37
+ const orderId = options.orderId || `ORDER-${Date.now()}`;
38
+
39
+ const paymentData = {
40
+ v_merchant_id: this.merchantId,
41
+ v_amount: parseFloat(options.amount),
42
+ v_currency: options.currency || 'USD',
43
+ v_description: options.description || options.name || 'Payment',
44
+ v_order_id: orderId,
45
+ v_success_url: options.successUrl || options.callback_link,
46
+ v_fail_url: options.failUrl || options.callback_link,
47
+ v_status_url: options.callbackUrl || options.callback_link,
48
+ v_email: options.email || '',
49
+ v_phone: options.phone || ''
50
+ };
51
+
52
+ // Generate signature
53
+ paymentData.v_sign = this.generateSignature(paymentData);
54
+
55
+ // Create payment URL
56
+ const params = new URLSearchParams(paymentData);
57
+ const paymentUrl = `${this.URL}?${params.toString()}`;
58
+
59
+ return {
60
+ status: 'success',
61
+ data: {
62
+ url: paymentUrl,
63
+ orderId: orderId,
64
+ merchantId: this.merchantId
65
+ }
66
+ };
67
+ } catch (error) {
68
+ throw new Error(`Payment creation error: ${error.message}`);
69
+ }
70
+ }
71
+
72
+ async handleCallback(callbackData) {
73
+ try {
74
+ const verification = await this.verifyCallback(callbackData);
75
+
76
+ if (!verification.status) {
77
+ throw new Error(verification.error.message);
78
+ }
79
+
80
+ const data = verification.data;
81
+
82
+ // Status mapping
83
+ const statusMapping = {
84
+ 'SUCCESS': 'success',
85
+ 'PENDING': 'pending',
86
+ 'FAIL': 'failed'
87
+ };
88
+
89
+ return {
90
+ status: statusMapping[data.v_status] || 'unknown',
91
+ orderId: data.v_order_id,
92
+ transactionId: data.v_transaction_id,
93
+ amount: parseFloat(data.v_amount),
94
+ currency: data.v_currency,
95
+ paymentStatus: data.v_status,
96
+ paymentMethod: data.v_payment_method
97
+ };
98
+ } catch (error) {
99
+ throw new Error(`Error in Volet callback handling: ${error.message}`);
100
+ }
101
+ }
102
+
103
+ async verifyCallback(data) {
104
+ try {
105
+ const receivedSign = data.v_sign;
106
+ const dataToVerify = { ...data };
107
+ delete dataToVerify.v_sign;
108
+
109
+ const expectedSign = this.generateSignature(dataToVerify);
110
+
111
+ if (receivedSign !== expectedSign) {
112
+ return {
113
+ status: false,
114
+ error: {
115
+ code: 401,
116
+ message: 'Invalid signature'
117
+ }
118
+ };
119
+ }
120
+
121
+ if (data.v_status === 'FAIL') {
122
+ return {
123
+ status: false,
124
+ error: {
125
+ code: 400,
126
+ message: 'Payment failed'
127
+ }
128
+ };
129
+ }
130
+
131
+ return {
132
+ status: true,
133
+ data: data
134
+ };
135
+ } catch (error) {
136
+ return {
137
+ status: false,
138
+ error: {
139
+ code: 500,
140
+ message: error.message
141
+ }
142
+ };
143
+ }
144
+ }
145
+ }
146
+
147
+ module.exports = VoletClient;