tonder-web-sdk 1.11.12 → 1.12.0-beta.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/.idea/prettier.xml +6 -0
- package/.idea/workspace.xml +96 -11
- package/README.md +0 -3
- package/package.json +3 -1
- package/src/classes/3dsHandler.js +1 -4
- package/src/classes/BaseInlineCheckout.js +298 -0
- package/src/classes/LiteInlineCheckout.js +109 -0
- package/src/classes/inlineCheckout.js +64 -286
- package/src/data/apmApi.js +44 -0
- package/src/data/businessApi.js +19 -0
- package/src/data/cardApi.js +116 -0
- package/src/data/checkoutApi.js +81 -0
- package/src/data/customerApi.js +37 -0
- package/src/data/index.js +17 -0
- package/src/data/openPayApi.js +16 -0
- package/src/data/skyflowApi.js +18 -0
- package/src/helpers/skyflow.js +76 -15
- package/src/helpers/template.js +7 -1
- package/src/helpers/utils.js +64 -79
- package/src/index-dev.js +96 -14
- package/src/index.html +119 -8
- package/src/shared/constants/paymentMethodAPM.js +63 -0
- package/src/shared/constants/tonderUrl.js +8 -0
- package/types/index.d.ts +79 -0
- package/v1/bundle.min.js +3 -3
- package/src/data/api.js +0 -193
- package/src/helpers/constants.js +0 -64
|
@@ -1,31 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { cardTemplateSkeleton } from '../helpers/template-skeleton.js'
|
|
1
|
+
import {apmItemsTemplate, cardItemsTemplate, cardTemplate} from '../helpers/template.js'
|
|
3
2
|
import {
|
|
4
|
-
getBusiness,
|
|
5
|
-
customerRegister,
|
|
6
|
-
createOrder,
|
|
7
|
-
createPayment,
|
|
8
|
-
startCheckoutRouter,
|
|
9
|
-
getOpenpayDeviceSessionID,
|
|
10
|
-
getCustomerCards,
|
|
11
|
-
registerCard,
|
|
12
|
-
deleteCustomerCard,
|
|
13
|
-
getCustomerAPMs
|
|
14
|
-
} from '../data/api';
|
|
15
|
-
import {
|
|
16
|
-
showError,
|
|
17
|
-
getBrowserInfo,
|
|
18
|
-
mapCards,
|
|
19
|
-
showMessage,
|
|
20
3
|
clearSpace,
|
|
21
|
-
injectMercadoPagoSecurity
|
|
4
|
+
injectMercadoPagoSecurity,
|
|
5
|
+
mapCards,
|
|
6
|
+
showError,
|
|
7
|
+
showMessage
|
|
22
8
|
} from '../helpers/utils';
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
|
|
9
|
+
import {initSkyflow} from '../helpers/skyflow'
|
|
10
|
+
import {globalLoader} from './globalLoader.js';
|
|
11
|
+
import {BaseInlineCheckout} from "./BaseInlineCheckout";
|
|
12
|
+
import {
|
|
13
|
+
fetchCustomerCards,
|
|
14
|
+
removeCustomerCard,
|
|
15
|
+
saveCustomerCard,
|
|
16
|
+
fetchCustomerAPMs
|
|
17
|
+
} from "../data";
|
|
27
18
|
|
|
28
|
-
export class InlineCheckout {
|
|
19
|
+
export class InlineCheckout extends BaseInlineCheckout{
|
|
29
20
|
static injected = false;
|
|
30
21
|
static cardsInjected = false
|
|
31
22
|
static apmsInjected = false
|
|
@@ -33,7 +24,6 @@ export class InlineCheckout {
|
|
|
33
24
|
deletingCards = [];
|
|
34
25
|
customer = {}
|
|
35
26
|
items = []
|
|
36
|
-
baseUrl = null
|
|
37
27
|
collectContainer = null
|
|
38
28
|
merchantData = {}
|
|
39
29
|
cartTotal = null
|
|
@@ -56,36 +46,14 @@ export class InlineCheckout {
|
|
|
56
46
|
mode = "stage",
|
|
57
47
|
apiKey,
|
|
58
48
|
returnUrl,
|
|
59
|
-
successUrl,
|
|
60
49
|
renderPaymentButton = false,
|
|
61
50
|
callBack = () => { },
|
|
62
51
|
styles
|
|
63
52
|
}) {
|
|
64
|
-
|
|
65
|
-
this.returnUrl = returnUrl;
|
|
66
|
-
this.successUrl = successUrl;
|
|
53
|
+
super({ mode, apiKey, returnUrl, callBack });
|
|
67
54
|
this.renderPaymentButton = renderPaymentButton;
|
|
68
|
-
this.callBack = callBack;
|
|
69
55
|
this.customStyles = styles
|
|
70
|
-
this.mode = mode
|
|
71
|
-
this.baseUrl = this.#getBaseUrl()
|
|
72
|
-
|
|
73
|
-
this.abortController = new AbortController()
|
|
74
56
|
this.abortRefreshCardsController = new AbortController()
|
|
75
|
-
this.process3ds = new ThreeDSHandler(
|
|
76
|
-
{ apiKey: apiKey, baseUrl: this.baseUrl, successUrl: successUrl }
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
#getBaseUrl() {
|
|
81
|
-
const modeUrls = {
|
|
82
|
-
'production': 'https://app.tonder.io',
|
|
83
|
-
'sandbox': 'https://sandbox.tonder.io',
|
|
84
|
-
'stage': 'https://stage.tonder.io',
|
|
85
|
-
'development': 'http://localhost:8000',
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
return modeUrls[this.mode] || modeUrls['stage']
|
|
89
57
|
}
|
|
90
58
|
|
|
91
59
|
#mountPayButton() {
|
|
@@ -118,90 +86,7 @@ export class InlineCheckout {
|
|
|
118
86
|
}
|
|
119
87
|
}
|
|
120
88
|
|
|
121
|
-
|
|
122
|
-
const iframe = response?.next_action?.iframe_resources?.iframe
|
|
123
|
-
|
|
124
|
-
if (iframe) {
|
|
125
|
-
this.process3ds.loadIframe().then(() => {
|
|
126
|
-
//TODO: Check if this will be necessary on the frontend side
|
|
127
|
-
// after some the tests in production, since the 3DS process
|
|
128
|
-
// doesn't works properly on the sandbox environment
|
|
129
|
-
// setTimeout(() => {
|
|
130
|
-
// process3ds.verifyTransactionStatus();
|
|
131
|
-
// }, 10000);
|
|
132
|
-
this.process3ds.verifyTransactionStatus();
|
|
133
|
-
}).catch((error) => {
|
|
134
|
-
console.log('Error loading iframe:', error)
|
|
135
|
-
})
|
|
136
|
-
} else {
|
|
137
|
-
const redirectUrl = this.process3ds.getRedirectUrl()
|
|
138
|
-
if (redirectUrl) {
|
|
139
|
-
this.process3ds.redirectToChallenge()
|
|
140
|
-
} else {
|
|
141
|
-
return response;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
payment(data) {
|
|
147
|
-
return new Promise(async (resolve, reject) => {
|
|
148
|
-
try {
|
|
149
|
-
this.#handleCustomer(data.customer)
|
|
150
|
-
this.setCartTotal(data.cart?.total)
|
|
151
|
-
this.setCartItems(data.cart?.items)
|
|
152
|
-
this.#handleMetadata(data)
|
|
153
|
-
this.#handleCurrency(data)
|
|
154
|
-
this.#handleCard(data)
|
|
155
|
-
const response = await this.#checkout()
|
|
156
|
-
this.process3ds.setPayload(response)
|
|
157
|
-
this.callBack(response);
|
|
158
|
-
const payload = await this.handle3dsRedirect(response)
|
|
159
|
-
if (payload) {
|
|
160
|
-
resolve(response);
|
|
161
|
-
}
|
|
162
|
-
} catch (error) {
|
|
163
|
-
reject(error);
|
|
164
|
-
}
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
#handleCustomer(customer) {
|
|
169
|
-
if (!customer) return
|
|
170
|
-
|
|
171
|
-
this.firstName = customer?.firstName
|
|
172
|
-
this.lastName = customer?.lastName
|
|
173
|
-
this.country = customer?.country
|
|
174
|
-
this.address = customer?.street
|
|
175
|
-
this.city = customer?.city
|
|
176
|
-
this.state = customer?.state
|
|
177
|
-
this.postCode = customer?.postCode
|
|
178
|
-
this.email = customer?.email
|
|
179
|
-
this.phone = customer?.phone
|
|
180
|
-
this.customer = customer
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
#handleMetadata(data) {
|
|
184
|
-
this.metadata = data?.metadata
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
#handleCurrency(data) {
|
|
188
|
-
this.currency = data?.currency
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
#handleCard(data) {
|
|
192
|
-
this.card = data?.card
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
setCartItems(items) {
|
|
196
|
-
this.cartItems = items
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
configureCheckout(data) {
|
|
200
|
-
if ('customer' in data)
|
|
201
|
-
this.#handleCustomer(data['customer'])
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
setCartTotal(total) {
|
|
89
|
+
_setCartTotal(total) {
|
|
205
90
|
this.cartTotal = total
|
|
206
91
|
this.#updatePayButton()
|
|
207
92
|
}
|
|
@@ -217,6 +102,7 @@ export class InlineCheckout {
|
|
|
217
102
|
}
|
|
218
103
|
|
|
219
104
|
injectCheckout() {
|
|
105
|
+
console.log("HERE: 1", InlineCheckout.injected)
|
|
220
106
|
if (InlineCheckout.injected) return
|
|
221
107
|
const containerTonderCheckout = document.querySelector("#tonder-checkout");
|
|
222
108
|
if (containerTonderCheckout) {
|
|
@@ -237,47 +123,6 @@ export class InlineCheckout {
|
|
|
237
123
|
});
|
|
238
124
|
}
|
|
239
125
|
|
|
240
|
-
async verify3dsTransaction () {
|
|
241
|
-
globalLoader.show()
|
|
242
|
-
const result3ds = await this.process3ds.verifyTransactionStatus()
|
|
243
|
-
const resultCheckout = await this.resumeCheckout(result3ds)
|
|
244
|
-
this.process3ds.setPayload(resultCheckout)
|
|
245
|
-
globalLoader.remove()
|
|
246
|
-
return this.handle3dsRedirect(resultCheckout)
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
async resumeCheckout(response) {
|
|
251
|
-
// Stop the routing process if the transaction is either hard declined or successful
|
|
252
|
-
if (response?.decline?.error_type === "Hard") {
|
|
253
|
-
return response
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
if (["Success", "Authorized"].includes(response?.transaction_status)) {
|
|
257
|
-
return response;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
if (response) {
|
|
261
|
-
globalLoader.show()
|
|
262
|
-
const routerItems = {
|
|
263
|
-
checkout_id: response?.checkout?.id,
|
|
264
|
-
};
|
|
265
|
-
try {
|
|
266
|
-
const routerResponse = await startCheckoutRouter(
|
|
267
|
-
this.baseUrl,
|
|
268
|
-
this.apiKeyTonder,
|
|
269
|
-
routerItems
|
|
270
|
-
);
|
|
271
|
-
return routerResponse
|
|
272
|
-
} catch (error) {
|
|
273
|
-
// throw error
|
|
274
|
-
} finally {
|
|
275
|
-
globalLoader.remove()
|
|
276
|
-
}
|
|
277
|
-
return response
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
126
|
#mount(containerTonderCheckout) {
|
|
282
127
|
containerTonderCheckout.innerHTML = cardTemplate({renderPaymentButton: this.renderPaymentButton, customStyles: this.customStyles});
|
|
283
128
|
globalLoader.show()
|
|
@@ -285,22 +130,9 @@ export class InlineCheckout {
|
|
|
285
130
|
InlineCheckout.injected = true;
|
|
286
131
|
}
|
|
287
132
|
|
|
288
|
-
async #fetchMerchantData() {
|
|
289
|
-
this.merchantData = await getBusiness(
|
|
290
|
-
this.baseUrl,
|
|
291
|
-
this.apiKeyTonder,
|
|
292
|
-
this.abortController.signal
|
|
293
|
-
);
|
|
294
|
-
return this.merchantData
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
async getCustomer(customer, signal) {
|
|
298
|
-
return await customerRegister(this.baseUrl, this.apiKeyTonder, customer, signal);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
133
|
async #mountAPMs() {
|
|
302
134
|
try{
|
|
303
|
-
const apms = await
|
|
135
|
+
const apms = await fetchCustomerAPMs(this.baseUrl, this.apiKeyTonder);
|
|
304
136
|
if(apms && apms['results'] && apms['results'].length > 0){
|
|
305
137
|
this.apmsData = apms['results']
|
|
306
138
|
this.#loadAPMList(apms['results'])
|
|
@@ -310,19 +142,23 @@ export class InlineCheckout {
|
|
|
310
142
|
}
|
|
311
143
|
}
|
|
312
144
|
|
|
313
|
-
async #mountTonder(getCards =
|
|
145
|
+
async #mountTonder(getCards = true) {
|
|
314
146
|
this.#mountPayButton()
|
|
147
|
+
await this._initializeCheckout()
|
|
315
148
|
try {
|
|
316
149
|
const {
|
|
317
150
|
vault_id,
|
|
318
|
-
vault_url
|
|
319
|
-
|
|
320
|
-
} = await this.#fetchMerchantData();
|
|
151
|
+
vault_url
|
|
152
|
+
} = this.merchantData;
|
|
321
153
|
if (this.email && getCards) {
|
|
322
|
-
const customerResponse = await this.
|
|
154
|
+
const customerResponse = await this._getCustomer({ email: this.email });
|
|
323
155
|
if ("auth_token" in customerResponse) {
|
|
324
156
|
const { auth_token } = customerResponse
|
|
325
|
-
const cards = await
|
|
157
|
+
const cards = await fetchCustomerCards(
|
|
158
|
+
this.baseUrl,
|
|
159
|
+
auth_token,
|
|
160
|
+
this.merchantData.business.pk
|
|
161
|
+
);
|
|
326
162
|
|
|
327
163
|
if ("cards" in cards) {
|
|
328
164
|
const cardsMapped = cards.cards.map(mapCards)
|
|
@@ -330,9 +166,6 @@ export class InlineCheckout {
|
|
|
330
166
|
}
|
|
331
167
|
}
|
|
332
168
|
}
|
|
333
|
-
if (!!mercado_pago && !!mercado_pago.active){
|
|
334
|
-
injectMercadoPagoSecurity()
|
|
335
|
-
}
|
|
336
169
|
|
|
337
170
|
await this.#mountAPMs();
|
|
338
171
|
|
|
@@ -380,16 +213,14 @@ export class InlineCheckout {
|
|
|
380
213
|
}
|
|
381
214
|
}
|
|
382
215
|
|
|
383
|
-
async
|
|
216
|
+
async _checkout() {
|
|
384
217
|
try {
|
|
385
218
|
document.querySelector("#tonderPayButton").disabled = true;
|
|
386
219
|
} catch (error) {
|
|
387
220
|
}
|
|
221
|
+
const { business } = this.merchantData
|
|
222
|
+
let cardTokens;
|
|
388
223
|
|
|
389
|
-
const { openpay_keys, reference, business } = this.merchantData
|
|
390
|
-
const total = Number(this.cartTotal)
|
|
391
|
-
|
|
392
|
-
let cardTokens = null;
|
|
393
224
|
if (this.radioChecked === "new" || this.radioChecked === undefined) {
|
|
394
225
|
cardTokens = await this.#getCardTokens();
|
|
395
226
|
} else {
|
|
@@ -398,107 +229,47 @@ export class InlineCheckout {
|
|
|
398
229
|
}
|
|
399
230
|
}
|
|
400
231
|
try {
|
|
401
|
-
|
|
402
|
-
if (openpay_keys.merchant_id && openpay_keys.public_key) {
|
|
403
|
-
deviceSessionIdTonder = await getOpenpayDeviceSessionID(
|
|
404
|
-
openpay_keys.merchant_id,
|
|
405
|
-
openpay_keys.public_key,
|
|
406
|
-
this.abortController.signal
|
|
407
|
-
);
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
const { id, auth_token } = await this.getCustomer(
|
|
232
|
+
const customerData = await this._getCustomer(
|
|
411
233
|
this.customer,
|
|
412
234
|
this.abortController.signal
|
|
413
235
|
)
|
|
236
|
+
const { auth_token } = customerData;
|
|
414
237
|
if (auth_token && this.email) {
|
|
415
238
|
const saveCard = document.getElementById("save-checkout-card");
|
|
416
239
|
if (saveCard && "checked" in saveCard && saveCard.checked) {
|
|
417
|
-
|
|
240
|
+
try {
|
|
241
|
+
await saveCustomerCard(this.baseUrl, auth_token, business.pk, {
|
|
242
|
+
skyflow_id: cardTokens.skyflow_id,
|
|
243
|
+
});
|
|
244
|
+
showMessage("Tarjeta registrada con éxito", this.collectorIds.msgNotification);
|
|
245
|
+
} catch (error) {
|
|
246
|
+
if (error?.message) {
|
|
247
|
+
showError(error.message)
|
|
248
|
+
}
|
|
249
|
+
}
|
|
418
250
|
|
|
419
251
|
this.cardsInjected = false;
|
|
420
252
|
|
|
421
|
-
const cards = await
|
|
253
|
+
const cards = await fetchCustomerCards(
|
|
254
|
+
this.baseUrl,
|
|
255
|
+
auth_token,
|
|
256
|
+
this.merchantData.business.pk,
|
|
257
|
+
);
|
|
422
258
|
if ("cards" in cards) {
|
|
423
259
|
const cardsMapped = cards.cards.map((card) => mapCards(card))
|
|
424
260
|
this.#loadCardsList(cardsMapped, auth_token)
|
|
425
261
|
}
|
|
426
|
-
|
|
427
|
-
showMessage("Tarjeta registrada con éxito", this.collectorIds.msgNotification);
|
|
428
|
-
|
|
429
262
|
}
|
|
430
263
|
}
|
|
431
|
-
var orderItems = {
|
|
432
|
-
business: this.apiKeyTonder,
|
|
433
|
-
client: auth_token,
|
|
434
|
-
billing_address_id: null,
|
|
435
|
-
shipping_address_id: null,
|
|
436
|
-
amount: total,
|
|
437
|
-
status: "A",
|
|
438
|
-
reference: reference,
|
|
439
|
-
is_oneclick: true,
|
|
440
|
-
items: this.cartItems,
|
|
441
|
-
};
|
|
442
|
-
const jsonResponseOrder = await createOrder(
|
|
443
|
-
this.baseUrl,
|
|
444
|
-
this.apiKeyTonder,
|
|
445
|
-
orderItems
|
|
446
|
-
);
|
|
447
|
-
|
|
448
|
-
// Create payment
|
|
449
|
-
const now = new Date();
|
|
450
|
-
const dateString = now.toISOString();
|
|
451
|
-
|
|
452
|
-
var paymentItems = {
|
|
453
|
-
business_pk: business.pk,
|
|
454
|
-
client_id: id,
|
|
455
|
-
amount: total,
|
|
456
|
-
date: dateString,
|
|
457
|
-
order_id: jsonResponseOrder.id,
|
|
458
|
-
};
|
|
459
|
-
const jsonResponsePayment = await createPayment(
|
|
460
|
-
this.baseUrl,
|
|
461
|
-
this.apiKeyTonder,
|
|
462
|
-
paymentItems
|
|
463
|
-
);
|
|
464
264
|
|
|
465
265
|
const selected_apm = this.apmsData ? this.apmsData.find((iapm) => iapm.pk === this.radioChecked):{};
|
|
466
|
-
|
|
467
|
-
// Checkout router
|
|
468
|
-
const routerItems = {
|
|
469
|
-
name: this.firstName || "",
|
|
470
|
-
last_name: this.lastName || "",
|
|
471
|
-
email_client: this.email,
|
|
472
|
-
phone_number: this.phone,
|
|
473
|
-
return_url: this.returnUrl,
|
|
474
|
-
id_product: "no_id",
|
|
475
|
-
quantity_product: 1,
|
|
476
|
-
id_ship: "0",
|
|
477
|
-
instance_id_ship: "0",
|
|
478
|
-
amount: total,
|
|
479
|
-
title_ship: "shipping",
|
|
480
|
-
description: "transaction",
|
|
481
|
-
device_session_id: deviceSessionIdTonder ? deviceSessionIdTonder : null,
|
|
482
|
-
token_id: "",
|
|
483
|
-
order_id: jsonResponseOrder.id,
|
|
484
|
-
business_id: business.pk,
|
|
485
|
-
payment_id: jsonResponsePayment.pk,
|
|
486
|
-
source: 'sdk',
|
|
487
|
-
metadata: this.metadata,
|
|
488
|
-
browser_info: getBrowserInfo(),
|
|
489
|
-
currency: this.currency,
|
|
490
|
-
...( selected_apm && Object.keys(selected_apm).length > 0
|
|
491
|
-
? {payment_method: selected_apm.payment_method}
|
|
492
|
-
: {card: cardTokens}
|
|
493
|
-
),
|
|
494
|
-
...(typeof MP_DEVICE_SESSION_ID !== "undefined" ? {mp_device_session_id: MP_DEVICE_SESSION_ID}:{})
|
|
495
|
-
};
|
|
496
266
|
|
|
497
|
-
const jsonResponseRouter = await
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
267
|
+
const jsonResponseRouter = await this._handleCheckout({
|
|
268
|
+
...( selected_apm && Object.keys(selected_apm).length > 0
|
|
269
|
+
? {payment_method: selected_apm.payment_method}
|
|
270
|
+
: {card: cardTokens}),
|
|
271
|
+
customer: customerData
|
|
272
|
+
});
|
|
502
273
|
|
|
503
274
|
if (jsonResponseRouter) {
|
|
504
275
|
try {
|
|
@@ -559,6 +330,7 @@ export class InlineCheckout {
|
|
|
559
330
|
for (const cardButton of cardsButtons) {
|
|
560
331
|
cardButton.addEventListener("click", (event) => {
|
|
561
332
|
event.preventDefault();
|
|
333
|
+
event.stopImmediatePropagation();
|
|
562
334
|
this.#handleDeleteCardButtonClick(token, cardButton)
|
|
563
335
|
}, false);
|
|
564
336
|
}
|
|
@@ -596,7 +368,8 @@ export class InlineCheckout {
|
|
|
596
368
|
this.abortRefreshCardsController.abort();
|
|
597
369
|
this.abortRefreshCardsController = new AbortController();
|
|
598
370
|
}
|
|
599
|
-
|
|
371
|
+
const businessId = this.merchantData.business.pk
|
|
372
|
+
await removeCustomerCard(this.baseUrl, customerToken, skyflow_id, businessId)
|
|
600
373
|
} catch {
|
|
601
374
|
} finally {
|
|
602
375
|
this.deletingCards = this.deletingCards.filter(id => id !== skyflow_id);
|
|
@@ -607,7 +380,12 @@ export class InlineCheckout {
|
|
|
607
380
|
async #refreshCardOnDelete(customerToken) {
|
|
608
381
|
if (this.deletingCards.length > 0) return;
|
|
609
382
|
this.cardsInjected = false
|
|
610
|
-
const cards = await
|
|
383
|
+
const cards = await fetchCustomerCards(
|
|
384
|
+
this.baseUrl,
|
|
385
|
+
customerToken,
|
|
386
|
+
this.merchantData.business.pk,
|
|
387
|
+
this.abortRefreshCardsController.signal
|
|
388
|
+
)
|
|
611
389
|
if ("cards" in cards) {
|
|
612
390
|
const cardsMapped = cards.cards.map(mapCards)
|
|
613
391
|
this.#loadCardsList(cardsMapped, customerToken)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildErrorResponse,
|
|
3
|
+
buildErrorResponseFromCatch,
|
|
4
|
+
} from "../helpers/utils";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Fetches Alternative Payment Methods (APMs) of a customer.
|
|
8
|
+
* @param {string} baseUrl - The base URL of the API.
|
|
9
|
+
* @param {string} apiKey - The API key for authentication.
|
|
10
|
+
* @param params - The query params to filter APMs
|
|
11
|
+
* @param {AbortSignal} signal - The abort signal to cancel the request.
|
|
12
|
+
* @returns {Promise<Object>} The available APMs.
|
|
13
|
+
*/
|
|
14
|
+
export async function fetchCustomerAPMs(
|
|
15
|
+
baseUrl,
|
|
16
|
+
apiKey,
|
|
17
|
+
params = {
|
|
18
|
+
status: "active",
|
|
19
|
+
pagesize: "10000",
|
|
20
|
+
},
|
|
21
|
+
signal = null,
|
|
22
|
+
) {
|
|
23
|
+
try {
|
|
24
|
+
const queryString = new URLSearchParams(params).toString();
|
|
25
|
+
|
|
26
|
+
const response = await fetch(
|
|
27
|
+
`${baseUrl}/api/v1/payment_methods?${queryString}`,
|
|
28
|
+
{
|
|
29
|
+
method: "GET",
|
|
30
|
+
headers: {
|
|
31
|
+
Authorization: `Token ${apiKey}`,
|
|
32
|
+
"Content-Type": "application/json",
|
|
33
|
+
},
|
|
34
|
+
signal,
|
|
35
|
+
},
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
if (response.ok) return await response.json();
|
|
39
|
+
const res_json = await response.json();
|
|
40
|
+
throw await buildErrorResponse(response, res_json);
|
|
41
|
+
} catch (error) {
|
|
42
|
+
throw buildErrorResponseFromCatch(error);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetches business information.
|
|
3
|
+
* @param {string} baseUrl - The base URL of the Tonder API.
|
|
4
|
+
* @param {string} apiKey - The API key for authentication.
|
|
5
|
+
* @param {AbortSignal} signal - The abort signal to cancel the request.
|
|
6
|
+
* @returns {Promise<Object>} The business information.
|
|
7
|
+
*/
|
|
8
|
+
export async function fetchBusiness(baseUrl, apiKey, signal) {
|
|
9
|
+
const getBusiness = await fetch(
|
|
10
|
+
`${baseUrl}/api/v1/payments/business/${apiKey}`,
|
|
11
|
+
{
|
|
12
|
+
headers: {
|
|
13
|
+
Authorization: `Token ${apiKey}`,
|
|
14
|
+
},
|
|
15
|
+
signal: signal,
|
|
16
|
+
},
|
|
17
|
+
);
|
|
18
|
+
return await getBusiness.json();
|
|
19
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildErrorResponse,
|
|
3
|
+
buildErrorResponseFromCatch,
|
|
4
|
+
} from "../helpers/utils";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Saves/Update a customer's card information.
|
|
8
|
+
* @param {string} baseUrl - The base URL of the API.
|
|
9
|
+
* @param {string} customerToken - The customer's authentication token.
|
|
10
|
+
* @param {string} businessId - The business ID.
|
|
11
|
+
* @param {Object} data - The card information to be saved.
|
|
12
|
+
* @returns {Promise<Object>} The saved card data.
|
|
13
|
+
*/
|
|
14
|
+
export async function saveCustomerCard(
|
|
15
|
+
baseUrl,
|
|
16
|
+
customerToken,
|
|
17
|
+
businessId,
|
|
18
|
+
data,
|
|
19
|
+
) {
|
|
20
|
+
try {
|
|
21
|
+
const url = `${baseUrl}/api/v1/business/${businessId}/cards/`;
|
|
22
|
+
const response = await fetch(url, {
|
|
23
|
+
method: "POST",
|
|
24
|
+
headers: {
|
|
25
|
+
Authorization: `Token ${customerToken}`,
|
|
26
|
+
"Content-Type": "application/json",
|
|
27
|
+
},
|
|
28
|
+
body: JSON.stringify(data),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (response.ok) return await response.json();
|
|
32
|
+
|
|
33
|
+
const res_json = await response.json();
|
|
34
|
+
|
|
35
|
+
if (response.status === 409) {
|
|
36
|
+
if ((res_json.error = "Card number already exists.")) {
|
|
37
|
+
return {
|
|
38
|
+
code: 200,
|
|
39
|
+
body: res_json,
|
|
40
|
+
name: "",
|
|
41
|
+
message: res_json.error,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
throw await buildErrorResponse(response, res_json);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
throw buildErrorResponseFromCatch(error);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Removes a customer's card.
|
|
53
|
+
* @param {string} baseUrl - The base URL of the API.
|
|
54
|
+
* @param {string} customerToken - The customer's authentication token.
|
|
55
|
+
* @param {string} skyflowId - The Skyflow ID of the card to be removed.
|
|
56
|
+
* @param {string} businessId - The business ID.
|
|
57
|
+
* @returns {Promise<Object>} The result of the card removal operation.
|
|
58
|
+
*/
|
|
59
|
+
export async function removeCustomerCard(
|
|
60
|
+
baseUrl,
|
|
61
|
+
customerToken,
|
|
62
|
+
skyflowId = "",
|
|
63
|
+
businessId,
|
|
64
|
+
) {
|
|
65
|
+
try {
|
|
66
|
+
const url = `${baseUrl}/api/v1/business/${businessId}/cards/${skyflowId}`;
|
|
67
|
+
|
|
68
|
+
const response = await fetch(url, {
|
|
69
|
+
method: "DELETE",
|
|
70
|
+
headers: {
|
|
71
|
+
Authorization: `Token ${customerToken}`,
|
|
72
|
+
"Content-Type": "application/json",
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
if (response.ok) return await response.json();
|
|
77
|
+
const res_json = await response.json();
|
|
78
|
+
|
|
79
|
+
throw await buildErrorResponse(response, res_json);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
throw buildErrorResponseFromCatch(error);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Fetches a customer's saved cards.
|
|
87
|
+
* @param {string} baseUrl - The base URL of the API.
|
|
88
|
+
* @param {string} customerToken - The customer's authentication token.
|
|
89
|
+
* @param {string} businessId - The business ID.
|
|
90
|
+
* @param {AbortSignal} signal - The abort signal to cancel the request.
|
|
91
|
+
* @returns {Promise<Object>} The customer's saved cards.
|
|
92
|
+
*/
|
|
93
|
+
export async function fetchCustomerCards(
|
|
94
|
+
baseUrl,
|
|
95
|
+
customerToken,
|
|
96
|
+
businessId,
|
|
97
|
+
signal= null,
|
|
98
|
+
) {
|
|
99
|
+
try {
|
|
100
|
+
const url = `${baseUrl}/api/v1/business/${businessId}/cards/`;
|
|
101
|
+
const response = await fetch(url, {
|
|
102
|
+
method: "GET",
|
|
103
|
+
headers: {
|
|
104
|
+
Authorization: `Token ${customerToken}`,
|
|
105
|
+
"Content-Type": "application/json",
|
|
106
|
+
},
|
|
107
|
+
signal,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
if (response.ok) return await response.json();
|
|
111
|
+
const res_json = await response.json();
|
|
112
|
+
throw await buildErrorResponse(response, res_json);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
throw buildErrorResponseFromCatch(error);
|
|
115
|
+
}
|
|
116
|
+
}
|