@yosle/tropipayjs 0.2.3 → 0.3.1
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 +69 -9
- package/index.d.ts +358 -76
- package/index.js +421 -342
- package/index.js.map +1 -0
- package/package.json +21 -8
- package/.nvmrc +0 -1
- package/.vscode/launch.json +0 -18
- package/SECURITY.md +0 -43
- package/api/TropipayAPI.d.ts +0 -133
- package/config/TropipayConfig.d.ts +0 -2
- package/constants/TropipayConstants.d.ts +0 -2
- package/depositAccount/depositAccounts.d.ts +0 -36
- package/docs/readme.md +0 -3
- package/globals.d.ts +0 -75
- package/hooks/TropipayHooks.d.ts +0 -38
- package/interfaces/countries/index.d.ts +0 -1
- package/interfaces/depositaccounts/index.d.ts +0 -68
- package/interfaces/index.d.ts +0 -176
- package/interfaces/mediation/index.d.ts +0 -22
- package/interfaces/paymentlink/index.d.ts +0 -87
- package/jest.config.js +0 -5
- package/mediationPaymentCard/MediationPaymentCard.d.ts +0 -17
- package/paymentcard/PaymentCard.d.ts +0 -37
- package/paymentcard/paymentcard.spec.d.ts +0 -1
- package/rollup.config.js +0 -23
- package/src/api/TropipayAPI.ts +0 -459
- package/src/config/TropipayConfig.ts +0 -2
- package/src/constants/TropipayConstants.ts +0 -2
- package/src/depositAccount/depositAccounts.ts +0 -139
- package/src/hooks/TropipayHooks.ts +0 -154
- package/src/index.ts +0 -29
- package/src/interfaces/depositaccounts/index.ts +0 -70
- package/src/interfaces/index.js +0 -2
- package/src/interfaces/index.ts +0 -212
- package/src/interfaces/mediation/index.ts +0 -23
- package/src/interfaces/paymentlink/index.d.ts +0 -36
- package/src/interfaces/paymentlink/index.js +0 -3
- package/src/interfaces/paymentlink/index.ts +0 -91
- package/src/mediationPaymentCard/MediationPaymentCard.ts +0 -42
- package/src/mocks/tropipay.ts +0 -0
- package/src/paymentcard/PaymentCard.ts +0 -123
- package/src/paymentcard/paymentcard.spec.ts +0 -79
- package/src/utils/TropipayUtils.ts +0 -126
- package/src/utils/errors.ts +0 -92
- package/tsconfig.json +0 -96
- package/utils/TropipayUtils.d.ts +0 -45
- package/utils/errors.d.ts +0 -16
package/index.js
CHANGED
|
@@ -23,7 +23,17 @@ function _interopNamespaceDefault(e) {
|
|
|
23
23
|
|
|
24
24
|
var crypto__namespace = /*#__PURE__*/_interopNamespaceDefault(crypto);
|
|
25
25
|
|
|
26
|
+
const MAX_IMAGE_SIZE_MB = 2;
|
|
27
|
+
/**
|
|
28
|
+
* Base path for the Tropipay API. All SDK endpoints target API v3
|
|
29
|
+
* (v2 is deprecated).
|
|
30
|
+
*/
|
|
31
|
+
const API_BASE = "/api/v3";
|
|
32
|
+
|
|
26
33
|
function handleExceptions(error) {
|
|
34
|
+
// already mapped (e.g. thrown by login() inside the request interceptor)
|
|
35
|
+
if (error instanceof TropipayJSException)
|
|
36
|
+
return error;
|
|
27
37
|
if (error instanceof axios.AxiosError) {
|
|
28
38
|
if (error.response) {
|
|
29
39
|
const axiosResponse = error.response;
|
|
@@ -79,7 +89,7 @@ class TropipayHooks {
|
|
|
79
89
|
* you must select from the list of available events, otherwise
|
|
80
90
|
* it will not produce an error but it will not be executed.
|
|
81
91
|
* For get full list of available events see endpoint
|
|
82
|
-
* GET /api/
|
|
92
|
+
* GET /api/v3/user/hooks/events.
|
|
83
93
|
* @param target String representing the type of event supported.
|
|
84
94
|
* It is currently available: 'web' (allows to receive information in a url),
|
|
85
95
|
* 'email' (allows to receive information in an email address).
|
|
@@ -90,20 +100,11 @@ class TropipayHooks {
|
|
|
90
100
|
* @returns
|
|
91
101
|
*/
|
|
92
102
|
async subscribe({ eventType, target, value, }) {
|
|
93
|
-
if (!Tropipay.accessToken) {
|
|
94
|
-
await this.tropipay.login();
|
|
95
|
-
}
|
|
96
103
|
try {
|
|
97
|
-
const hooks = await this.tropipay.request.post(
|
|
104
|
+
const hooks = await this.tropipay.request.post(`${API_BASE}/user/hooks`, {
|
|
98
105
|
event: eventType,
|
|
99
106
|
target: target,
|
|
100
107
|
value: value,
|
|
101
|
-
}, {
|
|
102
|
-
headers: {
|
|
103
|
-
"Content-Type": "application/json",
|
|
104
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
105
|
-
Accept: "application/json",
|
|
106
|
-
},
|
|
107
108
|
});
|
|
108
109
|
return hooks.data;
|
|
109
110
|
}
|
|
@@ -119,17 +120,8 @@ class TropipayHooks {
|
|
|
119
120
|
* @returns All subscribed hooks or empty Array if none exist.
|
|
120
121
|
*/
|
|
121
122
|
async list(eventType) {
|
|
122
|
-
if (!Tropipay.accessToken) {
|
|
123
|
-
await this.tropipay.login();
|
|
124
|
-
}
|
|
125
123
|
try {
|
|
126
|
-
const hooks = await this.tropipay.request.get(
|
|
127
|
-
headers: {
|
|
128
|
-
"Content-Type": "application/json",
|
|
129
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
130
|
-
Accept: "application/json",
|
|
131
|
-
},
|
|
132
|
-
});
|
|
124
|
+
const hooks = await this.tropipay.request.get(`${API_BASE}/user/hooks/${eventType || ""}`);
|
|
133
125
|
return hooks.data;
|
|
134
126
|
}
|
|
135
127
|
catch (error) {
|
|
@@ -137,20 +129,11 @@ class TropipayHooks {
|
|
|
137
129
|
}
|
|
138
130
|
}
|
|
139
131
|
async update(eventType, target, value) {
|
|
140
|
-
if (!Tropipay.accessToken) {
|
|
141
|
-
await this.tropipay.login();
|
|
142
|
-
}
|
|
143
132
|
try {
|
|
144
|
-
const hooks = await this.tropipay.request.put(
|
|
133
|
+
const hooks = await this.tropipay.request.put(`${API_BASE}/user/hooks`, {
|
|
145
134
|
event: eventType,
|
|
146
135
|
target: target,
|
|
147
136
|
value: value,
|
|
148
|
-
}, {
|
|
149
|
-
headers: {
|
|
150
|
-
"Content-Type": "application/json",
|
|
151
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
152
|
-
Accept: "application/json",
|
|
153
|
-
},
|
|
154
137
|
});
|
|
155
138
|
return hooks.data;
|
|
156
139
|
}
|
|
@@ -159,36 +142,17 @@ class TropipayHooks {
|
|
|
159
142
|
}
|
|
160
143
|
}
|
|
161
144
|
async delete(eventType, target) {
|
|
162
|
-
if (!Tropipay.accessToken) {
|
|
163
|
-
await this.tropipay.login();
|
|
164
|
-
}
|
|
165
145
|
try {
|
|
166
|
-
const hooks = await this.tropipay.request.delete(
|
|
167
|
-
headers: {
|
|
168
|
-
"Content-Type": "application/json",
|
|
169
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
170
|
-
Accept: "application/json",
|
|
171
|
-
},
|
|
172
|
-
});
|
|
146
|
+
const hooks = await this.tropipay.request.delete(`${API_BASE}/user/hooks/${eventType}/${target}`);
|
|
173
147
|
return hooks.data;
|
|
174
148
|
}
|
|
175
149
|
catch (error) {
|
|
176
|
-
console.trace(error);
|
|
177
150
|
throw handleExceptions(error);
|
|
178
151
|
}
|
|
179
152
|
}
|
|
180
153
|
async events() {
|
|
181
|
-
if (!Tropipay.accessToken) {
|
|
182
|
-
await this.tropipay.login();
|
|
183
|
-
}
|
|
184
154
|
try {
|
|
185
|
-
const hooks = await this.tropipay.request.get(
|
|
186
|
-
headers: {
|
|
187
|
-
"Content-Type": "application/json",
|
|
188
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
189
|
-
Accept: "application/json",
|
|
190
|
-
},
|
|
191
|
-
});
|
|
155
|
+
const hooks = await this.tropipay.request.get(`${API_BASE}/user/hooks/events`);
|
|
192
156
|
return hooks.data;
|
|
193
157
|
}
|
|
194
158
|
catch (error) {
|
|
@@ -204,22 +168,15 @@ class PaymentCard {
|
|
|
204
168
|
}
|
|
205
169
|
/**
|
|
206
170
|
* Create a paymentLink with the specified options.
|
|
171
|
+
* Supports multi-account via the optional `accountId` field of the
|
|
172
|
+
* payload (defaults to the user's default account).
|
|
207
173
|
* @param payload PaymentLinkPayload Object.
|
|
208
174
|
* @returns Promise<PaymentLink> or throws an Exception.
|
|
209
|
-
* @see https://
|
|
175
|
+
* @see https://doc.tropipay.com/docs/api-reference/payment-cards
|
|
210
176
|
*/
|
|
211
177
|
async create(payload) {
|
|
212
|
-
if (!Tropipay.accessToken) {
|
|
213
|
-
await this.tropipay.login();
|
|
214
|
-
}
|
|
215
178
|
try {
|
|
216
|
-
const paylink = await this.tropipay.request.post(
|
|
217
|
-
headers: {
|
|
218
|
-
"Content-Type": "application/json",
|
|
219
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
220
|
-
Accept: "application/json",
|
|
221
|
-
},
|
|
222
|
-
});
|
|
179
|
+
const paylink = await this.tropipay.request.post(`${API_BASE}/paymentcards`, payload);
|
|
223
180
|
return paylink.data;
|
|
224
181
|
}
|
|
225
182
|
catch (error) {
|
|
@@ -232,21 +189,12 @@ class PaymentCard {
|
|
|
232
189
|
* @returns Array of paymentlinks
|
|
233
190
|
*/
|
|
234
191
|
async list() {
|
|
235
|
-
if (!Tropipay.accessToken) {
|
|
236
|
-
await this.tropipay.login();
|
|
237
|
-
}
|
|
238
192
|
try {
|
|
239
|
-
const paymentcards = await this.tropipay.request.get(
|
|
240
|
-
headers: {
|
|
241
|
-
"Content-Type": "application/json",
|
|
242
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
243
|
-
Accept: "application/json",
|
|
244
|
-
},
|
|
245
|
-
});
|
|
193
|
+
const paymentcards = await this.tropipay.request.get(`${API_BASE}/paymentcards`);
|
|
246
194
|
return paymentcards.data;
|
|
247
195
|
}
|
|
248
196
|
catch (error) {
|
|
249
|
-
throw
|
|
197
|
+
throw handleExceptions(error);
|
|
250
198
|
}
|
|
251
199
|
}
|
|
252
200
|
/**
|
|
@@ -257,17 +205,25 @@ class PaymentCard {
|
|
|
257
205
|
* @throws {Error} If an error occurs while retrieving the payment card.
|
|
258
206
|
*/
|
|
259
207
|
async get(id) {
|
|
260
|
-
|
|
261
|
-
await this.tropipay.
|
|
208
|
+
try {
|
|
209
|
+
const paymentcard = await this.tropipay.request.get(`${API_BASE}/paymentcards/${id}`);
|
|
210
|
+
return paymentcard.data;
|
|
262
211
|
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
throw handleExceptions(error);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Updates a payment card. Send the card id in `cardId` plus the
|
|
218
|
+
* fields to modify.
|
|
219
|
+
*
|
|
220
|
+
* @param payload Object with `cardId` and the fields to update.
|
|
221
|
+
* @return {Promise<any>} A Promise that resolves to the updated payment card data.
|
|
222
|
+
* @throws {Error} If an error occurs while updating the payment card.
|
|
223
|
+
*/
|
|
224
|
+
async update(payload) {
|
|
263
225
|
try {
|
|
264
|
-
const paymentcard = await this.tropipay.request.
|
|
265
|
-
headers: {
|
|
266
|
-
"Content-Type": "application/json",
|
|
267
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
268
|
-
Accept: "application/json",
|
|
269
|
-
},
|
|
270
|
-
});
|
|
226
|
+
const paymentcard = await this.tropipay.request.put(`${API_BASE}/paymentcards/`, payload);
|
|
271
227
|
return paymentcard.data;
|
|
272
228
|
}
|
|
273
229
|
catch (error) {
|
|
@@ -283,16 +239,8 @@ class PaymentCard {
|
|
|
283
239
|
* @throws {Error} If an error occurs while deleting the payment card.
|
|
284
240
|
*/
|
|
285
241
|
async delete(id) {
|
|
286
|
-
if (!Tropipay.accessToken) {
|
|
287
|
-
await this.tropipay.login();
|
|
288
|
-
}
|
|
289
242
|
try {
|
|
290
|
-
const paymentcard = await this.tropipay.request.delete(
|
|
291
|
-
headers: {
|
|
292
|
-
"Content-Type": "application/json",
|
|
293
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
294
|
-
Accept: "application/json",
|
|
295
|
-
},
|
|
243
|
+
const paymentcard = await this.tropipay.request.delete(`${API_BASE}/paymentcards/`, {
|
|
296
244
|
data: {
|
|
297
245
|
cardId: id,
|
|
298
246
|
},
|
|
@@ -305,40 +253,6 @@ class PaymentCard {
|
|
|
305
253
|
}
|
|
306
254
|
}
|
|
307
255
|
|
|
308
|
-
class MediationPaymentCard {
|
|
309
|
-
tropipay;
|
|
310
|
-
constructor(tropipayInstance) {
|
|
311
|
-
this.tropipay = tropipayInstance;
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
|
-
* (ONLY FOR BUSINESS ACCOUNTS) Create a mediation paymentcard (an escrow payment link) with the specified options.
|
|
315
|
-
* This allows a payment to be made to persons belonging or not to the TropiPay platform with the
|
|
316
|
-
* particularity that the payment will be held in custody or retained until it is released with
|
|
317
|
-
* the approval of the payer.
|
|
318
|
-
* @param payload PaymentLinkPayload Object.
|
|
319
|
-
* @returns Promise<PaymentLink> or throws an Exception.
|
|
320
|
-
* @see https://tpp.stoplight.io/docs/tropipay-api-doc/12a128ff971e4-creating-a-mediation-payment-card
|
|
321
|
-
*/
|
|
322
|
-
async create(payload) {
|
|
323
|
-
if (!Tropipay.accessToken) {
|
|
324
|
-
await this.tropipay.login();
|
|
325
|
-
}
|
|
326
|
-
try {
|
|
327
|
-
const paylink = await this.tropipay.request.post("/api/v2/paymentcards/mediation", payload, {
|
|
328
|
-
headers: {
|
|
329
|
-
"Content-Type": "application/json",
|
|
330
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
331
|
-
Accept: "application/json",
|
|
332
|
-
},
|
|
333
|
-
});
|
|
334
|
-
return paylink.data;
|
|
335
|
-
}
|
|
336
|
-
catch (error) {
|
|
337
|
-
throw handleExceptions(error);
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
|
|
342
256
|
class DepositAccounts {
|
|
343
257
|
tropipay;
|
|
344
258
|
constructor(tropipayInstance) {
|
|
@@ -349,44 +263,28 @@ class DepositAccounts {
|
|
|
349
263
|
* @returns Array of DepositAccounts
|
|
350
264
|
*/
|
|
351
265
|
async list() {
|
|
352
|
-
if (!Tropipay.accessToken) {
|
|
353
|
-
await this.tropipay.login();
|
|
354
|
-
}
|
|
355
266
|
try {
|
|
356
|
-
const deposit = await this.tropipay.request.get(
|
|
357
|
-
headers: {
|
|
358
|
-
"Content-Type": "application/json",
|
|
359
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
360
|
-
Accept: "application/json",
|
|
361
|
-
},
|
|
362
|
-
});
|
|
267
|
+
const deposit = await this.tropipay.request.get(`${API_BASE}/deposit_accounts`);
|
|
363
268
|
return deposit.data;
|
|
364
269
|
}
|
|
365
270
|
catch (error) {
|
|
366
|
-
|
|
271
|
+
throw handleExceptions(error);
|
|
367
272
|
}
|
|
368
273
|
}
|
|
369
274
|
/**
|
|
370
275
|
* Adds a new beneficiary to the user account.
|
|
276
|
+
* For crypto wallet beneficiaries use `beneficiaryType: 3`, put the
|
|
277
|
+
* wallet address in `accountNumber` and set the `network`.
|
|
371
278
|
* @param payload
|
|
372
279
|
* @returns
|
|
373
280
|
*/
|
|
374
281
|
async create(depositAccountObj) {
|
|
375
|
-
if (!Tropipay.accessToken) {
|
|
376
|
-
await this.tropipay.login();
|
|
377
|
-
}
|
|
378
282
|
try {
|
|
379
|
-
const deposit = await this.tropipay.request.post(
|
|
380
|
-
headers: {
|
|
381
|
-
"Content-Type": "application/json",
|
|
382
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
383
|
-
Accept: "application/json",
|
|
384
|
-
},
|
|
385
|
-
});
|
|
283
|
+
const deposit = await this.tropipay.request.post(`${API_BASE}/deposit_accounts`, depositAccountObj);
|
|
386
284
|
return deposit.data;
|
|
387
285
|
}
|
|
388
286
|
catch (error) {
|
|
389
|
-
|
|
287
|
+
throw handleExceptions(error);
|
|
390
288
|
}
|
|
391
289
|
}
|
|
392
290
|
/**
|
|
@@ -396,67 +294,192 @@ class DepositAccounts {
|
|
|
396
294
|
* @returns
|
|
397
295
|
*/
|
|
398
296
|
async get(id) {
|
|
399
|
-
if (!Tropipay.accessToken) {
|
|
400
|
-
await this.tropipay.login();
|
|
401
|
-
}
|
|
402
297
|
try {
|
|
403
|
-
const deposit = await this.tropipay.request.get(
|
|
404
|
-
headers: {
|
|
405
|
-
"Content-Type": "application/json",
|
|
406
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
407
|
-
Accept: "application/json",
|
|
408
|
-
},
|
|
409
|
-
});
|
|
298
|
+
const deposit = await this.tropipay.request.get(`${API_BASE}/deposit_accounts/${id}`);
|
|
410
299
|
return deposit.data;
|
|
411
300
|
}
|
|
412
301
|
catch (error) {
|
|
413
|
-
|
|
302
|
+
throw handleExceptions(error);
|
|
414
303
|
}
|
|
415
304
|
}
|
|
416
305
|
/**
|
|
417
306
|
* Updates certain beneficiary data.
|
|
418
|
-
* @param depositAccountObj
|
|
307
|
+
* @param depositAccountObj Object with the beneficiary id and the fields to update.
|
|
419
308
|
* @returns
|
|
420
309
|
*/
|
|
421
310
|
async update(depositAccountObj) {
|
|
422
|
-
if (!Tropipay.accessToken) {
|
|
423
|
-
await this.tropipay.login();
|
|
424
|
-
}
|
|
425
311
|
try {
|
|
426
|
-
const deposit = await this.tropipay.request.put(
|
|
427
|
-
headers: {
|
|
428
|
-
"Content-Type": "application/json",
|
|
429
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
430
|
-
Accept: "application/json",
|
|
431
|
-
},
|
|
432
|
-
});
|
|
312
|
+
const deposit = await this.tropipay.request.put(`${API_BASE}/deposit_accounts`, depositAccountObj);
|
|
433
313
|
return deposit.data;
|
|
434
314
|
}
|
|
435
315
|
catch (error) {
|
|
436
|
-
|
|
316
|
+
throw handleExceptions(error);
|
|
437
317
|
}
|
|
438
318
|
}
|
|
439
319
|
/**
|
|
440
|
-
*
|
|
320
|
+
* Deletes the beneficiary indicated by id
|
|
441
321
|
* @param id
|
|
442
322
|
* @returns
|
|
443
323
|
*/
|
|
444
324
|
async delete(id) {
|
|
445
|
-
|
|
446
|
-
await this.tropipay.
|
|
325
|
+
try {
|
|
326
|
+
const deposit = await this.tropipay.request.delete(`${API_BASE}/deposit_accounts/${id}`);
|
|
327
|
+
return deposit.data;
|
|
447
328
|
}
|
|
329
|
+
catch (error) {
|
|
330
|
+
throw handleExceptions(error);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Validates a beneficiary account number (bank account, card or
|
|
335
|
+
* crypto wallet address) before creating it.
|
|
336
|
+
* @param payload Account number data to validate (e.g. { accountNumber, paymentType, network, currency })
|
|
337
|
+
* @returns
|
|
338
|
+
*/
|
|
339
|
+
async validateAccountNumber(payload) {
|
|
448
340
|
try {
|
|
449
|
-
const
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
341
|
+
const validation = await this.tropipay.request.post(`${API_BASE}/deposit_accounts/validate_account_number`, payload);
|
|
342
|
+
return validation.data;
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
throw handleExceptions(error);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Multi-account support. A Tropipay user can hold several accounts
|
|
352
|
+
* (one per currency). Use `list()` to discover the `accountId` values
|
|
353
|
+
* accepted by `paymentCards.create()` and `transfers.payout()`.
|
|
354
|
+
*/
|
|
355
|
+
class Accounts {
|
|
356
|
+
tropipay;
|
|
357
|
+
constructor(tropipayInstance) {
|
|
358
|
+
this.tropipay = tropipayInstance;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* List all the accounts of the current user with their id,
|
|
362
|
+
* accountNumber, currency, balance and enabled payment methods.
|
|
363
|
+
* @param type Optional comma-separated account types filter.
|
|
364
|
+
* @returns Array of Account objects.
|
|
365
|
+
*/
|
|
366
|
+
async list(type) {
|
|
367
|
+
try {
|
|
368
|
+
const accounts = await this.tropipay.request.get(`${API_BASE}/accounts`, {
|
|
369
|
+
params: type ? { type } : undefined,
|
|
455
370
|
});
|
|
456
|
-
|
|
371
|
+
// accept both a plain array and a paginated { count, rows } body
|
|
372
|
+
const data = accounts.data;
|
|
373
|
+
return Array.isArray(data) ? data : data?.rows ?? [];
|
|
374
|
+
}
|
|
375
|
+
catch (error) {
|
|
376
|
+
throw handleExceptions(error);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Get the balance of every account of the user.
|
|
381
|
+
* @returns Balances for all accounts.
|
|
382
|
+
*/
|
|
383
|
+
async allBalances() {
|
|
384
|
+
try {
|
|
385
|
+
const balances = await this.tropipay.request.get(`${API_BASE}/accounts/allBalance`);
|
|
386
|
+
return balances.data;
|
|
457
387
|
}
|
|
458
388
|
catch (error) {
|
|
459
|
-
|
|
389
|
+
throw handleExceptions(error);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Get the balance of one account by its account number
|
|
394
|
+
* (note: accountNumber, not account id — get it from `list()`).
|
|
395
|
+
* @param accountNumber The account number.
|
|
396
|
+
*/
|
|
397
|
+
async balance(accountNumber) {
|
|
398
|
+
try {
|
|
399
|
+
const balance = await this.tropipay.request.get(`${API_BASE}/accounts/balance/${accountNumber}`);
|
|
400
|
+
return balance.data;
|
|
401
|
+
}
|
|
402
|
+
catch (error) {
|
|
403
|
+
throw handleExceptions(error);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* List the movements of one account.
|
|
408
|
+
* @param accountId The account id (from `list()`).
|
|
409
|
+
* @param options Pagination: limit (max 50, default 20) and offset.
|
|
410
|
+
*/
|
|
411
|
+
async movements(accountId, options = {}) {
|
|
412
|
+
try {
|
|
413
|
+
const movements = await this.tropipay.request.get(`${API_BASE}/accounts/${accountId}/movements`, {
|
|
414
|
+
params: { limit: options.limit ?? 20, offset: options.offset ?? 0 },
|
|
415
|
+
});
|
|
416
|
+
return movements.data;
|
|
417
|
+
}
|
|
418
|
+
catch (error) {
|
|
419
|
+
throw handleExceptions(error);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Money transfers (payouts) to beneficiaries. Requires 2FA and the
|
|
426
|
+
* ALLOW_EXTERNAL_TRANSFER permission on the Tropipay account.
|
|
427
|
+
*
|
|
428
|
+
* Typical flow:
|
|
429
|
+
* 1. `simulate(payload)` to preview amounts and fees.
|
|
430
|
+
* 2. `requestSecurityCode()` to receive the 2FA code (SMS/email).
|
|
431
|
+
* 3. `payout({ ...payload, securityCode })` to execute the transfer.
|
|
432
|
+
*/
|
|
433
|
+
class Transfers {
|
|
434
|
+
tropipay;
|
|
435
|
+
constructor(tropipayInstance) {
|
|
436
|
+
this.tropipay = tropipayInstance;
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Simulate a payout without executing it: returns the resulting
|
|
440
|
+
* amounts, rates and fees for the given payload.
|
|
441
|
+
* Note the payload shape differs from `payout()`: it uses
|
|
442
|
+
* `currencyToPay`/`currencyToGet`, `amountToPay`/`amountToGet` and
|
|
443
|
+
* requires `accountId`.
|
|
444
|
+
* @param payload Simulation data (no securityCode needed).
|
|
445
|
+
*/
|
|
446
|
+
async simulate(payload) {
|
|
447
|
+
try {
|
|
448
|
+
const simulation = await this.tropipay.request.post(`${API_BASE}/booking/payout/simulate`, payload);
|
|
449
|
+
return simulation.data;
|
|
450
|
+
}
|
|
451
|
+
catch (error) {
|
|
452
|
+
throw handleExceptions(error);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Execute a payout (external transfer) to a beneficiary.
|
|
457
|
+
* Requires the 2FA `securityCode` in the payload (use
|
|
458
|
+
* `requestSecurityCode()` first; in Development mode "123456" works).
|
|
459
|
+
* Supports multi-account via the optional `accountId` field.
|
|
460
|
+
* @param payload Payout data including securityCode.
|
|
461
|
+
*/
|
|
462
|
+
async payout(payload) {
|
|
463
|
+
try {
|
|
464
|
+
const booking = await this.tropipay.request.post(`${API_BASE}/booking/payout`, payload);
|
|
465
|
+
return booking.data;
|
|
466
|
+
}
|
|
467
|
+
catch (error) {
|
|
468
|
+
throw handleExceptions(error);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Request the 2FA security code needed to confirm a payout.
|
|
473
|
+
* The code is delivered by SMS or email depending on the user's
|
|
474
|
+
* 2FA settings.
|
|
475
|
+
*/
|
|
476
|
+
async requestSecurityCode() {
|
|
477
|
+
try {
|
|
478
|
+
const response = await this.tropipay.request.post(`${API_BASE}/booking/sendSecurityCode`, {});
|
|
479
|
+
return response.data;
|
|
480
|
+
}
|
|
481
|
+
catch (error) {
|
|
482
|
+
throw handleExceptions(error);
|
|
460
483
|
}
|
|
461
484
|
}
|
|
462
485
|
}
|
|
@@ -467,19 +490,22 @@ class DepositAccounts {
|
|
|
467
490
|
* @author Yosleivy Baez Acosta
|
|
468
491
|
*
|
|
469
492
|
*/
|
|
493
|
+
const TOKEN_URL = `${API_BASE}/access/token`;
|
|
470
494
|
class Tropipay {
|
|
471
495
|
clientId;
|
|
472
496
|
clientSecret;
|
|
473
497
|
scopes;
|
|
474
498
|
request;
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
499
|
+
// Per instance, so several credentials (or environments) never share a token
|
|
500
|
+
accessToken = null;
|
|
501
|
+
refreshToken = null;
|
|
502
|
+
expiresIn = null;
|
|
478
503
|
serverMode;
|
|
479
504
|
hooks;
|
|
480
505
|
paymentCards;
|
|
481
506
|
depositAccounts;
|
|
482
|
-
|
|
507
|
+
accounts;
|
|
508
|
+
transfers;
|
|
483
509
|
/**
|
|
484
510
|
* Initializes a new instance of the Tropipay class.
|
|
485
511
|
*
|
|
@@ -512,87 +538,77 @@ class Tropipay {
|
|
|
512
538
|
this.serverMode = config.serverMode || "Development";
|
|
513
539
|
const tpp_env = this.serverMode === "Production"
|
|
514
540
|
? "https://www.tropipay.com"
|
|
515
|
-
: "https://tropipay
|
|
541
|
+
: "https://sandbox.tropipay.me";
|
|
516
542
|
this.request = axios.create({
|
|
517
543
|
baseURL: config.customTropipayUrl || tpp_env,
|
|
518
544
|
headers: {
|
|
519
545
|
"Content-Type": "application/json",
|
|
520
546
|
Accept: "application/json",
|
|
521
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
522
547
|
},
|
|
523
548
|
});
|
|
524
|
-
//
|
|
549
|
+
// Log in (or refresh an expired token) and attach the current token to
|
|
550
|
+
// every request. The token endpoint itself is skipped, otherwise login()
|
|
551
|
+
// would re-enter this interceptor forever.
|
|
525
552
|
this.request.interceptors.request.use(async (config) => {
|
|
553
|
+
if (config.url === TOKEN_URL)
|
|
554
|
+
return config;
|
|
526
555
|
const currentTimestamp = Math.floor(Date.now() / 1000); // Current time in seconds
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
await this.login();
|
|
531
|
-
}
|
|
532
|
-
catch (error) {
|
|
533
|
-
// Handle token refresh error
|
|
534
|
-
Tropipay.accessToken = null;
|
|
535
|
-
Tropipay.refreshToken = null;
|
|
536
|
-
throw handleExceptions(error);
|
|
537
|
-
}
|
|
556
|
+
const expired = this.expiresIn !== null && this.expiresIn < currentTimestamp;
|
|
557
|
+
if (!this.accessToken || expired) {
|
|
558
|
+
await this.login();
|
|
538
559
|
}
|
|
560
|
+
config.headers.Authorization = `Bearer ${this.accessToken}`;
|
|
539
561
|
return config;
|
|
540
562
|
}, (error) => {
|
|
541
563
|
return Promise.reject(error);
|
|
542
564
|
});
|
|
543
565
|
this.hooks = new TropipayHooks(this);
|
|
544
566
|
this.paymentCards = new PaymentCard(this);
|
|
545
|
-
this.mediationPaymentCard = new MediationPaymentCard(this);
|
|
546
567
|
this.depositAccounts = new DepositAccounts(this);
|
|
568
|
+
this.accounts = new Accounts(this);
|
|
569
|
+
this.transfers = new Transfers(this);
|
|
547
570
|
}
|
|
548
571
|
async login() {
|
|
549
572
|
try {
|
|
550
|
-
if (
|
|
551
|
-
const { data } = await this.request.post(
|
|
573
|
+
if (this.refreshToken) {
|
|
574
|
+
const { data } = await this.request.post(TOKEN_URL, {
|
|
552
575
|
client_id: this.clientId,
|
|
553
576
|
client_secret: this.clientSecret,
|
|
554
577
|
grant_type: "refresh_token",
|
|
555
|
-
refresh_token:
|
|
556
|
-
}, {
|
|
557
|
-
headers: {
|
|
558
|
-
"Content-Type": "application/json",
|
|
559
|
-
Accept: "application/json",
|
|
560
|
-
},
|
|
578
|
+
refresh_token: this.refreshToken,
|
|
561
579
|
});
|
|
580
|
+
this.accessToken = data.access_token;
|
|
581
|
+
this.refreshToken = data.refresh_token;
|
|
582
|
+
this.expiresIn = data.expires_in;
|
|
562
583
|
return data;
|
|
563
584
|
}
|
|
564
585
|
// normal credetials login
|
|
565
|
-
const { data } = await this.request.post(
|
|
586
|
+
const { data } = await this.request.post(TOKEN_URL, {
|
|
566
587
|
client_id: this.clientId,
|
|
567
588
|
client_secret: this.clientSecret,
|
|
568
589
|
grant_type: "client_credentials",
|
|
569
590
|
scope: this.scopes.join(" "), // "ALLOW_GET_PROFILE_DATA ALLOW_PAYMENT_IN ALLOW_EXTERNAL_CHARGE KYC3_FULL_ALLOW ALLOW_PAYMENT_OUT ALLOW_MARKET_PURCHASES ALLOW_GET_BALANCE ALLOW_GET_MOVEMENT_LIST ALLOW_GET_CREDENTIAL",
|
|
570
|
-
}, {
|
|
571
|
-
headers: {
|
|
572
|
-
"Content-Type": "application/json",
|
|
573
|
-
Accept: "application/json",
|
|
574
|
-
},
|
|
575
591
|
});
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
592
|
+
this.accessToken = data.access_token;
|
|
593
|
+
this.refreshToken = data.refresh_token;
|
|
594
|
+
this.expiresIn = data.expires_in;
|
|
579
595
|
return data;
|
|
580
596
|
}
|
|
581
597
|
catch (error) {
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
598
|
+
this.accessToken = null;
|
|
599
|
+
this.refreshToken = null;
|
|
600
|
+
this.expiresIn = null;
|
|
585
601
|
throw handleExceptions(error);
|
|
586
602
|
}
|
|
587
603
|
}
|
|
588
604
|
/**
|
|
589
605
|
* Get the list of all supported countries by Tropipay.
|
|
590
606
|
* @returns Array of Countries Data
|
|
591
|
-
* @see https://
|
|
607
|
+
* @see https://doc.tropipay.com/docs/api-reference/countries
|
|
592
608
|
*/
|
|
593
609
|
async countries() {
|
|
594
610
|
try {
|
|
595
|
-
const countries = await this.request.get(
|
|
611
|
+
const countries = await this.request.get(`${API_BASE}/countries`);
|
|
596
612
|
return countries.data;
|
|
597
613
|
}
|
|
598
614
|
catch (error) {
|
|
@@ -600,21 +616,14 @@ class Tropipay {
|
|
|
600
616
|
}
|
|
601
617
|
}
|
|
602
618
|
/**
|
|
603
|
-
* Get user
|
|
619
|
+
* Get balance of the user's default account.
|
|
620
|
+
* For per-account balances use `accounts.balance()` or
|
|
621
|
+
* `accounts.allBalances()`.
|
|
604
622
|
* @returns balance Object { balance: number, pendingIn: number, pendingOut: number }
|
|
605
623
|
*/
|
|
606
624
|
async getBalance() {
|
|
607
|
-
if (!Tropipay.accessToken) {
|
|
608
|
-
await this.login();
|
|
609
|
-
}
|
|
610
625
|
try {
|
|
611
|
-
const balance = await this.request.get(
|
|
612
|
-
headers: {
|
|
613
|
-
"Content-Type": "application/json",
|
|
614
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
615
|
-
Accept: "application/json",
|
|
616
|
-
},
|
|
617
|
-
});
|
|
626
|
+
const balance = await this.request.get(`${API_BASE}/users/balance`);
|
|
618
627
|
return balance.data;
|
|
619
628
|
}
|
|
620
629
|
catch (error) {
|
|
@@ -627,15 +636,15 @@ class Tropipay {
|
|
|
627
636
|
* when adding new beneficiaries to some user.
|
|
628
637
|
*
|
|
629
638
|
* @returns Array of Country Objects
|
|
630
|
-
* @see https://
|
|
639
|
+
* @see https://doc.tropipay.com/docs/api-reference/countries
|
|
631
640
|
*/
|
|
632
641
|
async destinations() {
|
|
633
642
|
try {
|
|
634
|
-
const countries = await this.request.get(
|
|
643
|
+
const countries = await this.request.get(`${API_BASE}/countries/destinations`);
|
|
635
644
|
return countries.data;
|
|
636
645
|
}
|
|
637
646
|
catch (error) {
|
|
638
|
-
throw
|
|
647
|
+
throw handleExceptions(error);
|
|
639
648
|
}
|
|
640
649
|
}
|
|
641
650
|
/**
|
|
@@ -643,16 +652,9 @@ class Tropipay {
|
|
|
643
652
|
* @returns Array of account Object or throws an error
|
|
644
653
|
*/
|
|
645
654
|
async favorites() {
|
|
646
|
-
if (!Tropipay.accessToken) {
|
|
647
|
-
await this.login();
|
|
648
|
-
}
|
|
649
655
|
try {
|
|
650
|
-
const favoritesList = await this.request.get(
|
|
651
|
-
|
|
652
|
-
"Content-Type": "application/json",
|
|
653
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
654
|
-
Accept: "application/json",
|
|
655
|
-
},
|
|
656
|
+
const favoritesList = await this.request.get(`${API_BASE}/paymentcards/filters`, {
|
|
657
|
+
params: { favorite: true },
|
|
656
658
|
});
|
|
657
659
|
return favoritesList?.data?.rows;
|
|
658
660
|
}
|
|
@@ -662,20 +664,16 @@ class Tropipay {
|
|
|
662
664
|
}
|
|
663
665
|
/**
|
|
664
666
|
* List all account movements. You can optionaly specify
|
|
665
|
-
* offset and limit params for pagination
|
|
667
|
+
* offset and limit params for pagination (limit is capped
|
|
668
|
+
* to 50 by the API).
|
|
669
|
+
* For the movements of one specific account use
|
|
670
|
+
* `accounts.movements(accountId)`.
|
|
666
671
|
* @returns
|
|
667
672
|
*/
|
|
668
673
|
async movements(offset = 0, limit = 10) {
|
|
669
|
-
if (!Tropipay.accessToken)
|
|
670
|
-
await this.login();
|
|
671
674
|
try {
|
|
672
|
-
const movements = await this.request.get(
|
|
675
|
+
const movements = await this.request.get(`${API_BASE}/movements`, {
|
|
673
676
|
params: { limit: limit, offset: offset },
|
|
674
|
-
headers: {
|
|
675
|
-
"Content-Type": "application/json",
|
|
676
|
-
Accept: "application/json",
|
|
677
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
678
|
-
},
|
|
679
677
|
});
|
|
680
678
|
return movements.data;
|
|
681
679
|
}
|
|
@@ -688,10 +686,8 @@ class Tropipay {
|
|
|
688
686
|
* @returns account object
|
|
689
687
|
*/
|
|
690
688
|
async profile() {
|
|
691
|
-
if (!Tropipay.accessToken)
|
|
692
|
-
await this.login();
|
|
693
689
|
try {
|
|
694
|
-
const profile = await this.request.get(
|
|
690
|
+
const profile = await this.request.get(`${API_BASE}/users/profile`);
|
|
695
691
|
return profile.data;
|
|
696
692
|
}
|
|
697
693
|
catch (error) {
|
|
@@ -704,51 +700,16 @@ class Tropipay {
|
|
|
704
700
|
* @param originCurrency Target currency code supported by Tropipay.
|
|
705
701
|
* @param targetCurrency Must be 'EUR'? (not documented by Tropipay)
|
|
706
702
|
* @returns Conversion rate (number)
|
|
707
|
-
* @see https://
|
|
703
|
+
* @see https://doc.tropipay.com/docs/api-reference/movements
|
|
708
704
|
*/
|
|
709
705
|
async rates(originCurrency, targetCurrency = "EUR") {
|
|
710
|
-
if (!Tropipay.accessToken) {
|
|
711
|
-
await this.login();
|
|
712
|
-
}
|
|
713
706
|
try {
|
|
714
|
-
const rates = await this.request.post(
|
|
707
|
+
const rates = await this.request.post(`${API_BASE}/movements/get_rate`, {
|
|
715
708
|
currencyFrom: originCurrency,
|
|
716
709
|
currencyTo: targetCurrency,
|
|
717
|
-
}, {
|
|
718
|
-
headers: {
|
|
719
|
-
"Content-Type": "application/json",
|
|
720
|
-
Accept: "application/json",
|
|
721
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
722
|
-
},
|
|
723
710
|
});
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
catch (error) {
|
|
727
|
-
throw handleExceptions(error);
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
/**
|
|
731
|
-
* (ONLY in Bussiness Accounts)
|
|
732
|
-
* An escrow payment link. This allows a payment to be made to persons
|
|
733
|
-
* belonging or not to the TropiPay platform with the particularity
|
|
734
|
-
* that the payment will be held in custody or retained until it is
|
|
735
|
-
* released with the approval of the payer.
|
|
736
|
-
* @deprecated This method is no longer supported and may be removed in a future release.
|
|
737
|
-
* @see https://tpp.stoplight.io/docs/tropipay-api-doc/12a128ff971e4-creating-a-mediation-payment-card
|
|
738
|
-
* @param config Payload with the payment details
|
|
739
|
-
*/
|
|
740
|
-
async createMediationPaymentCard(config) {
|
|
741
|
-
if (!Tropipay.accessToken)
|
|
742
|
-
await this.login();
|
|
743
|
-
try {
|
|
744
|
-
const mediation = await this.request.post("/api/v2/paymentcards/mediation", config, {
|
|
745
|
-
headers: {
|
|
746
|
-
"Content-Type": "application/json",
|
|
747
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
748
|
-
Accept: "application/json",
|
|
749
|
-
},
|
|
750
|
-
});
|
|
751
|
-
return mediation.data;
|
|
711
|
+
// the v3 API returns the rate as a numeric string
|
|
712
|
+
return Number(rates.data.rate);
|
|
752
713
|
}
|
|
753
714
|
catch (error) {
|
|
754
715
|
throw handleExceptions(error);
|
|
@@ -769,20 +730,11 @@ class Tropipay {
|
|
|
769
730
|
* the code received via SMS in Production (obtained via requestSecurityCode()).
|
|
770
731
|
*/
|
|
771
732
|
async refundMovement(orderCode, amount, securityCode) {
|
|
772
|
-
if (!Tropipay.accessToken) {
|
|
773
|
-
await this.login();
|
|
774
|
-
}
|
|
775
733
|
if (!this.scopes.includes("ALLOW_REFUND")) {
|
|
776
734
|
throw new TropipayJSException("The credential does not have the ALLOW_REFUND scope required to perform refunds. If you believe your account should have this permission, please contact Tropipay support.", 403, null);
|
|
777
735
|
}
|
|
778
736
|
try {
|
|
779
|
-
const response = await this.request.post(
|
|
780
|
-
headers: {
|
|
781
|
-
"Content-Type": "application/json",
|
|
782
|
-
Accept: "application/json",
|
|
783
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
784
|
-
},
|
|
785
|
-
});
|
|
737
|
+
const response = await this.request.post(`${API_BASE}/movements/in/refund`, { orderCode, amount, securityCode });
|
|
786
738
|
return response.data;
|
|
787
739
|
}
|
|
788
740
|
catch (error) {
|
|
@@ -802,17 +754,8 @@ class Tropipay {
|
|
|
802
754
|
* @returns The API response confirming the code was sent
|
|
803
755
|
*/
|
|
804
756
|
async requestSecurityCode(type = "sms") {
|
|
805
|
-
if (!Tropipay.accessToken) {
|
|
806
|
-
await this.login();
|
|
807
|
-
}
|
|
808
757
|
try {
|
|
809
|
-
const response = await this.request.post(
|
|
810
|
-
headers: {
|
|
811
|
-
"Content-Type": "application/json",
|
|
812
|
-
Accept: "application/json",
|
|
813
|
-
Authorization: `Bearer ${Tropipay.accessToken}`,
|
|
814
|
-
},
|
|
815
|
-
});
|
|
758
|
+
const response = await this.request.post(`${API_BASE}/users/sendSecurityCode`, { type });
|
|
816
759
|
return response.data;
|
|
817
760
|
}
|
|
818
761
|
catch (error) {
|
|
@@ -820,13 +763,6 @@ class Tropipay {
|
|
|
820
763
|
}
|
|
821
764
|
}
|
|
822
765
|
}
|
|
823
|
-
class ClientSideUtils {
|
|
824
|
-
constructor(tropipayInstance) {
|
|
825
|
-
throw Error(`Not implemented yet`);
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
const MAX_IMAGE_SIZE_MB = 1;
|
|
830
766
|
|
|
831
767
|
class ServerSideUtils {
|
|
832
768
|
tropipay;
|
|
@@ -853,23 +789,71 @@ class ServerSideUtils {
|
|
|
853
789
|
}
|
|
854
790
|
/**
|
|
855
791
|
* Checks if the provided base64 string represents a square image.
|
|
792
|
+
* Supports PNG and JPEG images (dimensions are read directly from
|
|
793
|
+
* the binary header, no DOM required).
|
|
856
794
|
*
|
|
857
795
|
* @param {string} base64String - The base64 string of the image
|
|
858
796
|
* @return {Promise<boolean>} A Promise that resolves to a boolean indicating whether the image is square
|
|
859
797
|
*/
|
|
860
798
|
static async isBase64ImageSquare(base64String) {
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
799
|
+
const dimensions = ServerSideUtils.getImageDimensions(base64String);
|
|
800
|
+
return dimensions.width === dimensions.height;
|
|
801
|
+
}
|
|
802
|
+
/**
|
|
803
|
+
* Reads the width/height of a base64 encoded PNG or JPEG image
|
|
804
|
+
* from its binary header.
|
|
805
|
+
*
|
|
806
|
+
* @param {string} base64String - base64 image, with or without the data: prefix
|
|
807
|
+
* @return {{width: number, height: number}} the image dimensions
|
|
808
|
+
*/
|
|
809
|
+
static getImageDimensions(base64String) {
|
|
810
|
+
const base64Data = base64String.replace(/^data:image\/\w+;base64,/, "");
|
|
811
|
+
const buffer = Buffer.from(base64Data, "base64");
|
|
812
|
+
// PNG signature: 89 50 4E 47, IHDR width/height at offsets 16/20
|
|
813
|
+
if (buffer.length > 24 &&
|
|
814
|
+
buffer[0] === 0x89 &&
|
|
815
|
+
buffer[1] === 0x50 &&
|
|
816
|
+
buffer[2] === 0x4e &&
|
|
817
|
+
buffer[3] === 0x47) {
|
|
818
|
+
return {
|
|
819
|
+
width: buffer.readUInt32BE(16),
|
|
820
|
+
height: buffer.readUInt32BE(20),
|
|
870
821
|
};
|
|
871
|
-
|
|
872
|
-
|
|
822
|
+
}
|
|
823
|
+
// JPEG signature: FF D8. Scan segments for a SOFn marker with the frame size.
|
|
824
|
+
if (buffer.length > 4 && buffer[0] === 0xff && buffer[1] === 0xd8) {
|
|
825
|
+
let offset = 2;
|
|
826
|
+
while (offset + 9 < buffer.length) {
|
|
827
|
+
if (buffer[offset] !== 0xff) {
|
|
828
|
+
offset++;
|
|
829
|
+
continue;
|
|
830
|
+
}
|
|
831
|
+
const marker = buffer[offset + 1];
|
|
832
|
+
// 0xFF fill bytes may pad the stream before a marker
|
|
833
|
+
if (marker === 0xff) {
|
|
834
|
+
offset++;
|
|
835
|
+
continue;
|
|
836
|
+
}
|
|
837
|
+
// standalone markers (TEM, RST0-RST7) carry no length field
|
|
838
|
+
if (marker === 0x01 || (marker >= 0xd0 && marker <= 0xd7)) {
|
|
839
|
+
offset += 2;
|
|
840
|
+
continue;
|
|
841
|
+
}
|
|
842
|
+
// SOF0-SOF15 markers except DHT (C4), JPG (C8) and DAC (CC)
|
|
843
|
+
if (marker >= 0xc0 &&
|
|
844
|
+
marker <= 0xcf &&
|
|
845
|
+
marker !== 0xc4 &&
|
|
846
|
+
marker !== 0xc8 &&
|
|
847
|
+
marker !== 0xcc) {
|
|
848
|
+
return {
|
|
849
|
+
height: buffer.readUInt16BE(offset + 5),
|
|
850
|
+
width: buffer.readUInt16BE(offset + 7),
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
offset += 2 + buffer.readUInt16BE(offset + 2);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
throw new Error("Unsupported image format: only PNG and JPEG are allowed");
|
|
873
857
|
}
|
|
874
858
|
/**
|
|
875
859
|
* Takes a local file path and returns a base64 representation of the file content.
|
|
@@ -910,11 +894,10 @@ class ServerSideUtils {
|
|
|
910
894
|
console.error("Not a valid base64 image");
|
|
911
895
|
throw new Error("Not a valid base64 image");
|
|
912
896
|
}
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
throw new Error(`The image should be less than 2mb`);
|
|
897
|
+
const isSizeValid = base64Image.length * 0.75 <= MAX_IMAGE_SIZE_MB * 1024 * 1024;
|
|
898
|
+
if (!isSizeValid) {
|
|
899
|
+
console.error(`The image should be less than ${MAX_IMAGE_SIZE_MB}mb`);
|
|
900
|
+
throw new Error(`The image should be less than ${MAX_IMAGE_SIZE_MB}mb`);
|
|
918
901
|
}
|
|
919
902
|
// all is fine
|
|
920
903
|
return true;
|
|
@@ -926,6 +909,97 @@ class ServerSideUtils {
|
|
|
926
909
|
}
|
|
927
910
|
}
|
|
928
911
|
|
|
912
|
+
/**
|
|
913
|
+
* Payment reasons accepted in the `reasonId` field.
|
|
914
|
+
*/
|
|
915
|
+
exports.Reasons = void 0;
|
|
916
|
+
(function (Reasons) {
|
|
917
|
+
Reasons[Reasons["HOUSING_ARRANGEMENT"] = 1] = "HOUSING_ARRANGEMENT";
|
|
918
|
+
Reasons[Reasons["FINANCIAL_AID"] = 2] = "FINANCIAL_AID";
|
|
919
|
+
Reasons[Reasons["FAMILY_SUPPORT"] = 3] = "FAMILY_SUPPORT";
|
|
920
|
+
Reasons[Reasons["TRAVEL_FUND"] = 4] = "TRAVEL_FUND";
|
|
921
|
+
Reasons[Reasons["REAL_ESTATE_PURCHASE"] = 5] = "REAL_ESTATE_PURCHASE";
|
|
922
|
+
Reasons[Reasons["FURNITURE_PURCHASE"] = 6] = "FURNITURE_PURCHASE";
|
|
923
|
+
Reasons[Reasons["EDUCATION"] = 7] = "EDUCATION";
|
|
924
|
+
Reasons[Reasons["MEDICAL_EXPENSES"] = 8] = "MEDICAL_EXPENSES";
|
|
925
|
+
Reasons[Reasons["OTHER"] = 9] = "OTHER";
|
|
926
|
+
Reasons[Reasons["DEBT_PAYMENT"] = 10] = "DEBT_PAYMENT";
|
|
927
|
+
Reasons[Reasons["TOURISM"] = 11] = "TOURISM";
|
|
928
|
+
Reasons[Reasons["SELF_SHIPPING"] = 12] = "SELF_SHIPPING";
|
|
929
|
+
Reasons[Reasons["ACCOUNT_ACTIVATION"] = 13] = "ACCOUNT_ACTIVATION";
|
|
930
|
+
Reasons[Reasons["SPORTS_ACTIVITIES"] = 14] = "SPORTS_ACTIVITIES";
|
|
931
|
+
Reasons[Reasons["DONATION"] = 15] = "DONATION";
|
|
932
|
+
Reasons[Reasons["AFFILIATE_COMMISSION"] = 16] = "AFFILIATE_COMMISSION";
|
|
933
|
+
Reasons[Reasons["SALARY"] = 17] = "SALARY";
|
|
934
|
+
Reasons[Reasons["SAVINGS"] = 18] = "SAVINGS";
|
|
935
|
+
Reasons[Reasons["RENT_AND_LEASING"] = 19] = "RENT_AND_LEASING";
|
|
936
|
+
Reasons[Reasons["SHARED_EXPENSES"] = 20] = "SHARED_EXPENSES";
|
|
937
|
+
Reasons[Reasons["SERVICE_PAYMENT"] = 21] = "SERVICE_PAYMENT";
|
|
938
|
+
Reasons[Reasons["GIFT"] = 22] = "GIFT";
|
|
939
|
+
Reasons[Reasons["CRYPTOCURRENCY_PURCHASE"] = 23] = "CRYPTOCURRENCY_PURCHASE";
|
|
940
|
+
Reasons[Reasons["OPERATING_EXPENSES"] = 24] = "OPERATING_EXPENSES";
|
|
941
|
+
Reasons[Reasons["CURRENCY_EXCHANGE"] = 25] = "CURRENCY_EXCHANGE";
|
|
942
|
+
Reasons[Reasons["ACCOMMODATION"] = 26] = "ACCOMMODATION";
|
|
943
|
+
Reasons[Reasons["EQUIPMENT_PURCHASE"] = 27] = "EQUIPMENT_PURCHASE";
|
|
944
|
+
Reasons[Reasons["CONSULTING"] = 28] = "CONSULTING";
|
|
945
|
+
Reasons[Reasons["SOFTWARE_DEVELOPMENT"] = 29] = "SOFTWARE_DEVELOPMENT";
|
|
946
|
+
Reasons[Reasons["REFUND"] = 30] = "REFUND";
|
|
947
|
+
Reasons[Reasons["PACKAGE_DELIVERY"] = 31] = "PACKAGE_DELIVERY";
|
|
948
|
+
Reasons[Reasons["PERSONAL_EXPENSES"] = 32] = "PERSONAL_EXPENSES";
|
|
949
|
+
Reasons[Reasons["INVESTMENT"] = 33] = "INVESTMENT";
|
|
950
|
+
Reasons[Reasons["BILL_PAYMENT"] = 34] = "BILL_PAYMENT";
|
|
951
|
+
Reasons[Reasons["HOST_PAYMENT"] = 35] = "HOST_PAYMENT";
|
|
952
|
+
Reasons[Reasons["TRANSPORTATION"] = 36] = "TRANSPORTATION";
|
|
953
|
+
Reasons[Reasons["LOAN"] = 37] = "LOAN";
|
|
954
|
+
Reasons[Reasons["BONUS"] = 38] = "BONUS";
|
|
955
|
+
Reasons[Reasons["HALLOWEEN_REMITTANCE"] = 39] = "HALLOWEEN_REMITTANCE";
|
|
956
|
+
Reasons[Reasons["PLINK_REMITTANCE"] = 41] = "PLINK_REMITTANCE";
|
|
957
|
+
Reasons[Reasons["R1_2023"] = 78] = "R1_2023";
|
|
958
|
+
Reasons[Reasons["HAPPYWEEK"] = 79] = "HAPPYWEEK";
|
|
959
|
+
Reasons[Reasons["SENDING_YOU_A_KISS"] = 80] = "SENDING_YOU_A_KISS";
|
|
960
|
+
})(exports.Reasons || (exports.Reasons = {}));
|
|
961
|
+
|
|
962
|
+
const DepositAccountTypesList = {
|
|
963
|
+
/**
|
|
964
|
+
* Banco Metropolitano (Cuba) Bank Account
|
|
965
|
+
*/
|
|
966
|
+
BANMET_BANK_ACCOUNT: 0,
|
|
967
|
+
/**
|
|
968
|
+
* Banco Popular de Ahorro
|
|
969
|
+
*/
|
|
970
|
+
BPA_BANK_ACCOUNT: 1,
|
|
971
|
+
/**
|
|
972
|
+
* Banco de Credito y Comercio (Cuba) Bank Account
|
|
973
|
+
*/
|
|
974
|
+
BANDEC_BANK_ACCOUNT: 2,
|
|
975
|
+
/**
|
|
976
|
+
* Banco Metropilitano (Cuba) card
|
|
977
|
+
*/
|
|
978
|
+
BANMET_CARD: 3,
|
|
979
|
+
/**
|
|
980
|
+
* Banco Popular de Ahorro (Cuba) card
|
|
981
|
+
*/
|
|
982
|
+
BPA_CARD: 4,
|
|
983
|
+
/**
|
|
984
|
+
* Not available anymore
|
|
985
|
+
* @deprecated
|
|
986
|
+
*/
|
|
987
|
+
AIS_CUC_CARD: 5,
|
|
988
|
+
/**
|
|
989
|
+
* Not available
|
|
990
|
+
* @deprecated
|
|
991
|
+
*/
|
|
992
|
+
AIS_USD_CARD: 6,
|
|
993
|
+
/**
|
|
994
|
+
* For international bank accounts
|
|
995
|
+
*/
|
|
996
|
+
OTHER: 7,
|
|
997
|
+
/**
|
|
998
|
+
* Banco de Credito y comercio card
|
|
999
|
+
*/
|
|
1000
|
+
BANDEC_CARD: 8,
|
|
1001
|
+
};
|
|
1002
|
+
|
|
929
1003
|
const SERVER_MODE = "Development"; // Move the constant here
|
|
930
1004
|
|
|
931
1005
|
/**
|
|
@@ -936,7 +1010,6 @@ const SERVER_MODE = "Development"; // Move the constant here
|
|
|
936
1010
|
* Developed by Yosleivy Baez Acosta
|
|
937
1011
|
* GitHub: https://github.com/yosle/tropipayjs
|
|
938
1012
|
*
|
|
939
|
-
* @version 0.1.11
|
|
940
1013
|
* @license MIT
|
|
941
1014
|
*/
|
|
942
1015
|
if (typeof window !== "undefined") {
|
|
@@ -945,9 +1018,15 @@ if (typeof window !== "undefined") {
|
|
|
945
1018
|
throw new Error(err_msg);
|
|
946
1019
|
}
|
|
947
1020
|
|
|
948
|
-
exports.
|
|
1021
|
+
exports.API_BASE = API_BASE;
|
|
1022
|
+
exports.Accounts = Accounts;
|
|
1023
|
+
exports.DepositAccountTypesList = DepositAccountTypesList;
|
|
1024
|
+
exports.DepositAccounts = DepositAccounts;
|
|
949
1025
|
exports.MAX_IMAGE_SIZE_MB = MAX_IMAGE_SIZE_MB;
|
|
1026
|
+
exports.PaymentCard = PaymentCard;
|
|
950
1027
|
exports.SERVER_MODE = SERVER_MODE;
|
|
951
1028
|
exports.ServerSideUtils = ServerSideUtils;
|
|
1029
|
+
exports.Transfers = Transfers;
|
|
952
1030
|
exports.Tropipay = Tropipay;
|
|
1031
|
+
exports.TropipayHooks = TropipayHooks;
|
|
953
1032
|
//# sourceMappingURL=index.js.map
|