vxgate 1.0.0
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/README.md +174 -0
- package/package.json +26 -0
- package/src/index.js +272 -0
- package/src/index.mjs +3 -0
package/README.md
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# vxgate
|
|
2
|
+
|
|
3
|
+
Violetics Payment Gateway SDK — terima pembayaran QRIS via Orderkuota dengan 3 baris kode.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install vxgate
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
import { VioleticsPayment } from 'vxgate';
|
|
15
|
+
|
|
16
|
+
const pay = new VioleticsPayment('vlt_YOUR_API_KEY');
|
|
17
|
+
|
|
18
|
+
// Buat order + poll sampai lunas
|
|
19
|
+
const { payment, result } = await pay.createAndWait({
|
|
20
|
+
amount: 15000,
|
|
21
|
+
referenceId: `ORDER-${Date.now()}`,
|
|
22
|
+
description: 'Pembelian Premium',
|
|
23
|
+
expireMinutes: 30,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
if (result.paid) {
|
|
27
|
+
console.log(`✅ Lunas via ${result.payerBrand}`);
|
|
28
|
+
console.log(`📱 QR URL: ${payment.qrisUrl}`);
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## API
|
|
33
|
+
|
|
34
|
+
### `new VioleticsPayment(apiKey, [baseUrl])`
|
|
35
|
+
|
|
36
|
+
| Param | Type | Description |
|
|
37
|
+
|-------|------|-------------|
|
|
38
|
+
| `apiKey` | string | API Key kamu (format `vlt_xxx`) |
|
|
39
|
+
| `baseUrl` | string | Custom base URL (default: `https://pg.vltcx.eu.cc/api`) |
|
|
40
|
+
|
|
41
|
+
### `.create(opts)` → `Promise<PaymentData>`
|
|
42
|
+
|
|
43
|
+
Buat order pembayaran baru.
|
|
44
|
+
|
|
45
|
+
```js
|
|
46
|
+
const payment = await pay.create({
|
|
47
|
+
amount: 15000, // wajib, nominal dalam Rupiah
|
|
48
|
+
referenceId: 'ORDER-001', // opsional, auto-generate jika kosong
|
|
49
|
+
description: 'Premium Plan', // opsional
|
|
50
|
+
expireMinutes: 60, // opsional, default 60 menit
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// payment.qrisUrl → URL gambar QR siap tampil ke customer
|
|
54
|
+
// payment.amount → nominal actual (mungkin ada suffix unik +1 s/d +500)
|
|
55
|
+
// payment.referenceId → simpan ini untuk check/poll
|
|
56
|
+
// payment.expiresAtHuman → "2026-06-03 15:00:00"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### `.check(referenceId)` → `Promise<PaymentResult>`
|
|
60
|
+
|
|
61
|
+
Cek status pembayaran satu kali.
|
|
62
|
+
|
|
63
|
+
```js
|
|
64
|
+
const result = await pay.check('ORDER-001');
|
|
65
|
+
// result.status → 'pending' | 'paid' | 'expired'
|
|
66
|
+
// result.paid → boolean shortcut
|
|
67
|
+
// result.payerBrand → 'GOPAY' | 'OVO' | 'DANA' | ...
|
|
68
|
+
// result.paidAt → "2026-06-03 14:42:17"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### `.poll(referenceId, [opts])` → `Promise<PaymentResult>`
|
|
72
|
+
|
|
73
|
+
Poll sampai paid/expired atau timeout.
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
const result = await pay.poll('ORDER-001', {
|
|
77
|
+
intervalMs: 3000, // cek tiap 3 detik (default: 5000)
|
|
78
|
+
timeoutMs: 600_000, // timeout 10 menit (default: 300000)
|
|
79
|
+
onPoll: (n, status) => console.log(`[#${n}] ${status}`),
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### `.createAndWait(paymentOpts, [pollOpts])` → `Promise<{payment, result}>`
|
|
84
|
+
|
|
85
|
+
Shortcut: buat + poll sekaligus.
|
|
86
|
+
|
|
87
|
+
```js
|
|
88
|
+
const { payment, result } = await pay.createAndWait(
|
|
89
|
+
{ amount: 15000, referenceId: 'ORDER-001' },
|
|
90
|
+
{ intervalMs: 3000, timeoutMs: 300_000 }
|
|
91
|
+
);
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### `.list([opts])` → `Promise<Transaction[]>`
|
|
95
|
+
|
|
96
|
+
Daftar transaksi.
|
|
97
|
+
|
|
98
|
+
```js
|
|
99
|
+
const txs = await pay.list({ limit: 20, offset: 0 });
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### `.requestOtp(username, password)` / `.verifyOtp(otp)`
|
|
103
|
+
|
|
104
|
+
Login Orderkuota via API.
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
await pay.requestOtp('08xxxx', 'password');
|
|
108
|
+
await pay.verifyOtp('123456');
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### `.setWebhook(url)` → `Promise<{webhookUrl, webhookSecret}>`
|
|
112
|
+
|
|
113
|
+
Konfigurasi webhook URL.
|
|
114
|
+
|
|
115
|
+
```js
|
|
116
|
+
const { webhookSecret } = await pay.setWebhook('https://yourapp.com/webhook');
|
|
117
|
+
// Simpan webhookSecret untuk verifikasi signature
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### `VioleticsPayment.verifyWebhook(rawBody, signature, secret)` → `boolean`
|
|
121
|
+
|
|
122
|
+
Verifikasi HMAC-SHA256 webhook signature (Node.js).
|
|
123
|
+
|
|
124
|
+
```js
|
|
125
|
+
// Express handler
|
|
126
|
+
app.post('/webhook', express.raw({ type: '*/*' }), (req, res) => {
|
|
127
|
+
const sig = req.headers['x-violetics-signature'];
|
|
128
|
+
if (!VioleticsPayment.verifyWebhook(req.body, sig, process.env.WEBHOOK_SECRET))
|
|
129
|
+
return res.sendStatus(401);
|
|
130
|
+
|
|
131
|
+
const event = JSON.parse(req.body);
|
|
132
|
+
if (event.event === 'payment.success') {
|
|
133
|
+
fulfillOrder(event.reference_id);
|
|
134
|
+
}
|
|
135
|
+
res.sendStatus(200);
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### `VioleticsPayment.verifyWebhookAsync(rawBody, signature, secret)` → `Promise<boolean>`
|
|
140
|
+
|
|
141
|
+
Verifikasi webhook (browser-compatible, Web Crypto API).
|
|
142
|
+
|
|
143
|
+
## Error Handling
|
|
144
|
+
|
|
145
|
+
```js
|
|
146
|
+
import { VioleticsPayment, VioleticsError, VioleticsTimeoutError } from 'vxgate';
|
|
147
|
+
|
|
148
|
+
try {
|
|
149
|
+
const result = await pay.poll('ORDER-001', { timeoutMs: 60_000 });
|
|
150
|
+
} catch (err) {
|
|
151
|
+
if (err instanceof VioleticsTimeoutError) {
|
|
152
|
+
console.log('Payment belum masuk setelah 60 detik');
|
|
153
|
+
} else if (err instanceof VioleticsError) {
|
|
154
|
+
console.log(`API Error ${err.statusCode}: ${err.message}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## ESM & CJS
|
|
160
|
+
|
|
161
|
+
Package support keduanya:
|
|
162
|
+
|
|
163
|
+
```js
|
|
164
|
+
// ESM
|
|
165
|
+
import { VioleticsPayment } from 'vxgate';
|
|
166
|
+
|
|
167
|
+
// CJS
|
|
168
|
+
const { VioleticsPayment } = require('vxgate');
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Links
|
|
172
|
+
|
|
173
|
+
- [Documentation](https://pg.vltcx.eu.cc/docs)
|
|
174
|
+
- [Dashboard](https://pg.vltcx.eu.cc/dashboard)
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vxgate",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Violetics Payment Gateway SDK — QRIS payment via Orderkuota API",
|
|
5
|
+
"keywords": ["qris", "payment", "orderkuota", "violetics", "indonesia", "payment-gateway"],
|
|
6
|
+
"author": "Violetics",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"homepage": "https://pg.vltcx.eu.cc/docs",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/cv3inx/pg"
|
|
12
|
+
},
|
|
13
|
+
"main": "./src/index.js",
|
|
14
|
+
"module": "./src/index.mjs",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"import": "./src/index.mjs",
|
|
18
|
+
"require": "./src/index.js",
|
|
19
|
+
"default": "./src/index.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": ["src/", "README.md"],
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18.0.0"
|
|
25
|
+
}
|
|
26
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_BASE_URL = 'https://pg.vltcx.eu.cc/api';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {object} PaymentData
|
|
7
|
+
* @property {number} transactionId
|
|
8
|
+
* @property {string} referenceId
|
|
9
|
+
* @property {number} amount
|
|
10
|
+
* @property {number} amountRequested
|
|
11
|
+
* @property {string} qrisUrl
|
|
12
|
+
* @property {string} qrisString
|
|
13
|
+
* @property {number} expiresAt
|
|
14
|
+
* @property {string} expiresAtHuman
|
|
15
|
+
* @property {string} status
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @typedef {object} PaymentResult
|
|
20
|
+
* @property {string} status
|
|
21
|
+
* @property {boolean} paid
|
|
22
|
+
* @property {boolean} expired
|
|
23
|
+
* @property {string|null} paidAt
|
|
24
|
+
* @property {string|null} payerBrand
|
|
25
|
+
* @property {string|null} payerInfo
|
|
26
|
+
* @property {boolean} webhookSent
|
|
27
|
+
* @property {object} raw
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @typedef {object} CreateOptions
|
|
32
|
+
* @property {number} amount
|
|
33
|
+
* @property {string} [referenceId]
|
|
34
|
+
* @property {string} [description]
|
|
35
|
+
* @property {number} [expireMinutes=60]
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @typedef {object} PollOptions
|
|
40
|
+
* @property {number} [intervalMs=5000]
|
|
41
|
+
* @property {number} [timeoutMs=300000]
|
|
42
|
+
* @property {function} [onPoll] (attempt: number, status: string) => void
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
class VioleticsPayment {
|
|
46
|
+
/**
|
|
47
|
+
* @param {string} apiKey - Violetics API Key (format: vlt_xxx)
|
|
48
|
+
* @param {string} [baseUrl]
|
|
49
|
+
*/
|
|
50
|
+
constructor(apiKey, baseUrl = DEFAULT_BASE_URL) {
|
|
51
|
+
if (!apiKey) throw new Error('apiKey is required');
|
|
52
|
+
this._apiKey = apiKey;
|
|
53
|
+
this._baseUrl = baseUrl.replace(/\/$/, '');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ── Internal ────────────────────────────────────────────────────────────
|
|
57
|
+
|
|
58
|
+
async _get(action, params = {}) {
|
|
59
|
+
const qs = new URLSearchParams({ apikey: this._apiKey, action, ...params });
|
|
60
|
+
const res = await fetch(`${this._baseUrl}?${qs}`);
|
|
61
|
+
const data = await res.json();
|
|
62
|
+
if (!data.status && !data.success)
|
|
63
|
+
throw new VioleticsError(data.message ?? `HTTP ${res.status}`, res.status, data);
|
|
64
|
+
return data;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async _post(action, body = {}) {
|
|
68
|
+
const url = `${this._baseUrl}?apikey=${encodeURIComponent(this._apiKey)}&action=${action}`;
|
|
69
|
+
const res = await fetch(url, {
|
|
70
|
+
method: 'POST',
|
|
71
|
+
body: new URLSearchParams(body),
|
|
72
|
+
});
|
|
73
|
+
const data = await res.json();
|
|
74
|
+
if (!data.status && !data.success)
|
|
75
|
+
throw new VioleticsError(data.message ?? `HTTP ${res.status}`, res.status, data);
|
|
76
|
+
return data;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// ── Payment ─────────────────────────────────────────────────────────────
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Buat order pembayaran baru.
|
|
83
|
+
* @param {CreateOptions} opts
|
|
84
|
+
* @returns {Promise<PaymentData>}
|
|
85
|
+
*/
|
|
86
|
+
async create({ amount, referenceId, description, expireMinutes = 60 } = {}) {
|
|
87
|
+
if (!amount || amount <= 0) throw new Error('amount harus lebih dari 0');
|
|
88
|
+
|
|
89
|
+
const params = { amount, expire_minutes: expireMinutes };
|
|
90
|
+
if (referenceId) params.reference_id = referenceId;
|
|
91
|
+
if (description) params.description = description;
|
|
92
|
+
|
|
93
|
+
const { data: d } = await this._get('create_payment', params);
|
|
94
|
+
return {
|
|
95
|
+
transactionId: d.transaction_id,
|
|
96
|
+
referenceId: d.reference_id,
|
|
97
|
+
amount: d.amount,
|
|
98
|
+
amountRequested: d.amount_requested,
|
|
99
|
+
qrisUrl: d.qris_url,
|
|
100
|
+
qrisString: d.qris_string,
|
|
101
|
+
expiresAt: d.expires_at,
|
|
102
|
+
expiresAtHuman: d.expires_at_human,
|
|
103
|
+
status: d.status,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Cek status pembayaran satu kali.
|
|
109
|
+
* @param {string} referenceId
|
|
110
|
+
* @returns {Promise<PaymentResult>}
|
|
111
|
+
*/
|
|
112
|
+
async check(referenceId) {
|
|
113
|
+
if (!referenceId) throw new Error('referenceId is required');
|
|
114
|
+
const { data: d } = await this._get('check_payment', { reference_id: referenceId });
|
|
115
|
+
return {
|
|
116
|
+
status: d.status,
|
|
117
|
+
paid: d.status === 'paid',
|
|
118
|
+
expired: d.status === 'expired',
|
|
119
|
+
paidAt: d.paid_at ?? null,
|
|
120
|
+
payerBrand: d.payer_brand ?? null,
|
|
121
|
+
payerInfo: d.payer_info ?? null,
|
|
122
|
+
webhookSent: Boolean(d.webhook_sent),
|
|
123
|
+
raw: d,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Poll pembayaran sampai paid/expired atau timeout.
|
|
129
|
+
* @param {string} referenceId
|
|
130
|
+
* @param {PollOptions} [opts]
|
|
131
|
+
* @returns {Promise<PaymentResult>}
|
|
132
|
+
*/
|
|
133
|
+
async poll(referenceId, { intervalMs = 5000, timeoutMs = 300_000, onPoll } = {}) {
|
|
134
|
+
if (!referenceId) throw new Error('referenceId is required');
|
|
135
|
+
|
|
136
|
+
const deadline = Date.now() + timeoutMs;
|
|
137
|
+
let attempt = 0;
|
|
138
|
+
|
|
139
|
+
while (Date.now() < deadline) {
|
|
140
|
+
attempt++;
|
|
141
|
+
const result = await this.check(referenceId);
|
|
142
|
+
|
|
143
|
+
if (typeof onPoll === 'function') onPoll(attempt, result.status);
|
|
144
|
+
if (result.paid || result.expired) return result;
|
|
145
|
+
|
|
146
|
+
const wait = Math.min(intervalMs, deadline - Date.now());
|
|
147
|
+
if (wait <= 0) break;
|
|
148
|
+
await new Promise(r => setTimeout(r, wait));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
throw new VioleticsTimeoutError(
|
|
152
|
+
`Polling timeout setelah ${timeoutMs / 1000}s`,
|
|
153
|
+
referenceId,
|
|
154
|
+
timeoutMs,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Shortcut: buat order + poll sampai selesai.
|
|
160
|
+
* @param {CreateOptions} paymentOpts
|
|
161
|
+
* @param {PollOptions} [pollOpts]
|
|
162
|
+
* @returns {Promise<{payment: PaymentData, result: PaymentResult}>}
|
|
163
|
+
*/
|
|
164
|
+
async createAndWait(paymentOpts, pollOpts = {}) {
|
|
165
|
+
const payment = await this.create(paymentOpts);
|
|
166
|
+
const result = await this.poll(payment.referenceId, pollOpts);
|
|
167
|
+
return { payment, result };
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Ambil daftar transaksi.
|
|
172
|
+
* @param {{limit?: number, offset?: number}} [opts]
|
|
173
|
+
*/
|
|
174
|
+
async list({ limit = 20, offset = 0 } = {}) {
|
|
175
|
+
const res = await this._get('list_payments', { limit, offset });
|
|
176
|
+
return res.data;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// ── Orderkuota auth ──────────────────────────────────────────────────────
|
|
180
|
+
|
|
181
|
+
/** Login Orderkuota langkah 1 — kirim OTP ke email. */
|
|
182
|
+
async requestOtp(username, password) {
|
|
183
|
+
return this._post('request_otp', { username, password });
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** Login Orderkuota langkah 2 — verifikasi OTP. */
|
|
187
|
+
async verifyOtp(otp) {
|
|
188
|
+
return this._post('verify_otp', { otp });
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// ── Account ──────────────────────────────────────────────────────────────
|
|
192
|
+
|
|
193
|
+
/** Set webhook URL. Returns { webhookUrl, webhookSecret }. */
|
|
194
|
+
async setWebhook(webhookUrl) {
|
|
195
|
+
const res = await this._post('set_webhook', { webhook_url: webhookUrl });
|
|
196
|
+
return {
|
|
197
|
+
webhookUrl: res.data.webhook_url,
|
|
198
|
+
webhookSecret: res.data.webhook_secret,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** Regenerate API Key. Key lama langsung tidak berlaku. */
|
|
203
|
+
async regenerateKey() {
|
|
204
|
+
const res = await this._post('regenerate_key', {});
|
|
205
|
+
return res.data.new_api_key;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// ── Static helpers ───────────────────────────────────────────────────────
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Verifikasi HMAC-SHA256 webhook signature.
|
|
212
|
+
* @param {Buffer|string} rawBody - Raw request body
|
|
213
|
+
* @param {string} signature - X-Violetics-Signature header value
|
|
214
|
+
* @param {string} secret - Webhook secret dari setWebhook()
|
|
215
|
+
* @returns {boolean}
|
|
216
|
+
*/
|
|
217
|
+
static verifyWebhook(rawBody, signature, secret) {
|
|
218
|
+
// Node.js
|
|
219
|
+
if (typeof require !== 'undefined') {
|
|
220
|
+
const { createHmac, timingSafeEqual } = require('crypto');
|
|
221
|
+
const expected = createHmac('sha256', secret)
|
|
222
|
+
.update(typeof rawBody === 'string' ? rawBody : rawBody)
|
|
223
|
+
.digest('hex');
|
|
224
|
+
try {
|
|
225
|
+
return timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
|
|
226
|
+
} catch {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
// Browser (Web Crypto — async, use verifyWebhookAsync instead)
|
|
231
|
+
throw new Error('Use VioleticsPayment.verifyWebhookAsync() in browser environments');
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Verifikasi webhook signature (async, browser-compatible).
|
|
236
|
+
*/
|
|
237
|
+
static async verifyWebhookAsync(rawBody, signature, secret) {
|
|
238
|
+
const enc = new TextEncoder();
|
|
239
|
+
const key = await crypto.subtle.importKey(
|
|
240
|
+
'raw', enc.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign'],
|
|
241
|
+
);
|
|
242
|
+
const sig = await crypto.subtle.sign('HMAC', key,
|
|
243
|
+
typeof rawBody === 'string' ? enc.encode(rawBody) : rawBody,
|
|
244
|
+
);
|
|
245
|
+
const expected = Array.from(new Uint8Array(sig))
|
|
246
|
+
.map(b => b.toString(16).padStart(2, '0')).join('');
|
|
247
|
+
return expected === signature;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// ── Custom errors ─────────────────────────────────────────────────────────
|
|
252
|
+
|
|
253
|
+
class VioleticsError extends Error {
|
|
254
|
+
constructor(message, statusCode, response) {
|
|
255
|
+
super(message);
|
|
256
|
+
this.name = 'VioleticsError';
|
|
257
|
+
this.statusCode = statusCode;
|
|
258
|
+
this.response = response;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
class VioleticsTimeoutError extends Error {
|
|
263
|
+
constructor(message, referenceId, timeoutMs) {
|
|
264
|
+
super(message);
|
|
265
|
+
this.name = 'VioleticsTimeoutError';
|
|
266
|
+
this.referenceId = referenceId;
|
|
267
|
+
this.timeoutMs = timeoutMs;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
module.exports = { VioleticsPayment, VioleticsError, VioleticsTimeoutError };
|
|
272
|
+
module.exports.default = VioleticsPayment;
|
package/src/index.mjs
ADDED