tonder-web-sdk 1.9.3-beta.1 → 1.11.0-beta.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 CHANGED
@@ -139,6 +139,7 @@ const checkoutData = {
139
139
  const apiKey = "4c87c36e697e65ddfe288be0afbe7967ea0ab865";
140
140
  const returnUrl = "http://my-website:8080/checkout"
141
141
  const successUrl = "http://my-website:8080/success"
142
+
142
143
  // if using script tag, it should be initialized like this
143
144
  // new TonderSdk.InlineCheckout
144
145
  const inlineCheckout = new InlineCheckout({
@@ -148,8 +149,22 @@ const inlineCheckout = new InlineCheckout({
148
149
  styles: customStyles
149
150
  });
150
151
 
152
+ // The configureCheckout function allows you to set initial information,
153
+ // such as the customer's email, which is used to retrieve a list of saved cards.
154
+ inlineCheckout.configureCheckout({customer: {email: "example@email.com"}});
155
+
156
+
151
157
  inlineCheckout.injectCheckout();
152
158
 
159
+ // To verify a 3ds transaction you can use the following method
160
+ // It should be called after the injectCheckout method
161
+ // The response status will be one of the following
162
+ // ['Declined', 'Cancelled', 'Failed', 'Success', 'Pending', 'Authorized']
163
+
164
+ inlineCheckout.verify3dsTransaction().then(response => {
165
+ console.log('Verify 3ds response', response)
166
+ })
167
+
153
168
  const response = await inlineCheckout.payment(checkoutData);
154
169
  ```
155
170
 
@@ -163,7 +178,7 @@ const response = await inlineCheckout.payment(checkoutData);
163
178
  | mode | string | 'stage' 'production' 'sandbox', default 'stage' |
164
179
  | apiKey | string | You can take this from you Tonder Dashboard |
165
180
  | backgroundColor | string | Hex color #000000 |
166
- | returnUrl | string | |
181
+ | returnUrl | string | url where the checkout form is mounted (3ds) |
167
182
  | successUrl | string | |
168
183
  | backgroundColor | string | |
169
184
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tonder-web-sdk",
3
- "version": "1.9.3-beta.1",
3
+ "version": "1.11.0-beta.0",
4
4
  "description": "tonder sdk for integrations",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -39,6 +39,18 @@ export class ThreeDSHandler {
39
39
  }
40
40
  }
41
41
 
42
+ saveCheckoutId(checkoutId) {
43
+ localStorage.setItem('checkout_id', JSON.stringify(checkoutId))
44
+ }
45
+
46
+ removeCheckoutId() {
47
+ localStorage.removeItem("checkout_id")
48
+ }
49
+
50
+ getCurrentCheckoutId() {
51
+ return JSON.parse(localStorage.getItem("checkout_id"));
52
+ }
53
+
42
54
  getUrlWithExpiration() {
43
55
  const item = JSON.parse(localStorage.getItem("verify_transaction_status"))
44
56
  if (!item) return
@@ -117,17 +129,17 @@ export class ThreeDSHandler {
117
129
  return parameters;
118
130
  }
119
131
 
132
+ // TODO: Remove this duplication
120
133
  handleSuccessTransaction(response) {
121
134
  this.removeVerifyTransactionUrl();
122
- window.location = this.successUrl
123
- console.log('Transacción autorizada exitosamente.');
135
+ // window.location = this.successUrl
136
+ console.log('Transacción autorizada');
124
137
  return response;
125
138
  }
126
139
 
127
140
  handleDeclinedTransaction(response) {
128
141
  this.removeVerifyTransactionUrl();
129
- console.log('Transacción rechazada.');
130
- throw new Error("Transacción rechazada.");
142
+ return response;
131
143
  }
132
144
 
133
145
  // TODO: the method below needs to be tested with a real 3DS challenge
@@ -159,15 +171,18 @@ export class ThreeDSHandler {
159
171
  await this.verifyTransactionStatus();
160
172
  }
161
173
 
174
+ // TODO: This method could be removed
162
175
  async handleTransactionResponse(response) {
163
176
  const response_json = await response.json();
164
177
 
165
- if (response_json.status === "Pending") {
178
+ // Azul property
179
+ if (response_json.status === "Pending" && response_json.redirect_post_url) {
166
180
  return await this.handle3dsChallenge(response_json);
167
181
  } else if (["Success", "Authorized"].includes(response_json.status)) {
168
- return this.handleSuccessTransaction(response);
182
+ return this.handleSuccessTransaction(response_json);
169
183
  } else {
170
- return this.handleDeclinedTransaction(response);
184
+ this.handleDeclinedTransaction();
185
+ return response_json
171
186
  }
172
187
  }
173
188
 
@@ -185,19 +200,23 @@ export class ThreeDSHandler {
185
200
  },
186
201
  // body: JSON.stringify(data),
187
202
  });
188
-
189
203
  if (response.status !== 200) {
190
204
  console.error('La verificación de la transacción falló.');
191
- return
205
+ this.removeVerifyTransactionUrl();
206
+ return response
192
207
  }
193
208
 
194
209
  return await this.handleTransactionResponse(response);
195
210
  } catch (error) {
196
211
  console.error('Error al verificar la transacción:', error);
197
- return error;
212
+ this.removeVerifyTransactionUrl();
198
213
  }
199
214
  } else {
200
215
  console.log('No verify_transaction_status_url found');
201
216
  }
202
217
  }
218
+
219
+ setPayload = (payload) => {
220
+ this.payload = payload
221
+ }
203
222
  }
@@ -1,4 +1,4 @@
1
- import { cardItemsTemplate, cardTemplate } from '../helpers/template.js'
1
+ import { apmItemsTemplate, cardItemsTemplate, cardTemplate } from '../helpers/template.js'
2
2
  import { cardTemplateSkeleton } from '../helpers/template-skeleton.js'
3
3
  import {
4
4
  getBusiness,
@@ -9,13 +9,15 @@ import {
9
9
  getOpenpayDeviceSessionID,
10
10
  getCustomerCards,
11
11
  registerCard,
12
- deleteCustomerCard
12
+ deleteCustomerCard,
13
+ getCustomerAPMs
13
14
  } from '../data/api';
14
15
  import {
15
16
  showError,
16
17
  getBrowserInfo,
17
18
  mapCards,
18
19
  showMessage,
20
+ clearSpace
19
21
  } from '../helpers/utils';
20
22
  import { initSkyflow } from '../helpers/skyflow'
21
23
  import { ThreeDSHandler } from './3dsHandler.js';
@@ -24,6 +26,8 @@ import { ThreeDSHandler } from './3dsHandler.js';
24
26
  export class InlineCheckout {
25
27
  static injected = false;
26
28
  static cardsInjected = false
29
+ static apmsInjected = false
30
+ static apmsData = [];
27
31
  deletingCards = [];
28
32
  customer = {}
29
33
  items = []
@@ -42,8 +46,8 @@ export class InlineCheckout {
42
46
  cvv: "collectCvv",
43
47
  tonderPayButton: "tonderPayButton",
44
48
  msgError: "msgError",
45
- msgNotification: "msgNotification"
46
-
49
+ msgNotification: "msgNotification",
50
+ apmsListContainer: "apmsListContainer"
47
51
  }
48
52
 
49
53
  constructor({
@@ -78,7 +82,7 @@ export class InlineCheckout {
78
82
  'stage': 'https://stage.tonder.io',
79
83
  'development': 'http://localhost:8000',
80
84
  };
81
-
85
+
82
86
  return modeUrls[this.mode] || modeUrls['stage']
83
87
  }
84
88
 
@@ -112,6 +116,31 @@ export class InlineCheckout {
112
116
  }
113
117
  }
114
118
 
119
+ async handle3dsRedirect(response) {
120
+ const iframe = response?.next_action?.iframe_resources?.iframe
121
+
122
+ if (iframe) {
123
+ this.process3ds.loadIframe().then(() => {
124
+ //TODO: Check if this will be necessary on the frontend side
125
+ // after some the tests in production, since the 3DS process
126
+ // doesn't works properly on the sandbox environment
127
+ // setTimeout(() => {
128
+ // process3ds.verifyTransactionStatus();
129
+ // }, 10000);
130
+ this.process3ds.verifyTransactionStatus();
131
+ }).catch((error) => {
132
+ console.log('Error loading iframe:', error)
133
+ })
134
+ } else {
135
+ const redirectUrl = this.process3ds.getRedirectUrl()
136
+ if (redirectUrl) {
137
+ this.process3ds.redirectToChallenge()
138
+ } else {
139
+ return response;
140
+ }
141
+ }
142
+ }
143
+
115
144
  payment(data) {
116
145
  return new Promise(async (resolve, reject) => {
117
146
  try {
@@ -122,36 +151,12 @@ export class InlineCheckout {
122
151
  this.#handleCurrency(data)
123
152
  this.#handleCard(data)
124
153
  const response = await this.#checkout()
125
- if (response) {
126
- const process3ds = new ThreeDSHandler({
127
- baseUrl: this.baseUrl,
128
- apiKey: this.apiKeyTonder,
129
- payload: response,
130
- });
131
- this.callBack(response);
132
-
133
- const iframe = response?.next_action?.iframe_resources?.iframe
134
-
135
- if (iframe) {
136
- process3ds.loadIframe().then(() => {
137
- //TODO: Check if this will be necessary on the frontend side
138
- // after some the tests in production, since the 3DS process
139
- // doesn't works properly on the sandbox environment
140
- // setTimeout(() => {
141
- // process3ds.verifyTransactionStatus();
142
- // }, 10000);
143
- process3ds.verifyTransactionStatus();
144
- }).catch((error) => {
145
- console.log('Error loading iframe:', error)
146
- })
147
- } else {
148
- const redirectUrl = process3ds.getRedirectUrl()
149
- if (redirectUrl) {
150
- process3ds.redirectToChallenge()
151
- } else {
152
- resolve(response);
153
- }
154
- }
154
+ this.process3ds.setPayload(response)
155
+ this.process3ds.saveCheckoutId(response.checkout_id)
156
+ this.callBack(response);
157
+ const payload = await this.handle3dsRedirect(response)
158
+ if (payload) {
159
+ resolve(response);
155
160
  }
156
161
  } catch (error) {
157
162
  reject(error);
@@ -160,7 +165,6 @@ export class InlineCheckout {
160
165
  }
161
166
 
162
167
  #handleCustomer(customer) {
163
- console.log('customer: ', customer)
164
168
  if (!customer) return
165
169
 
166
170
  this.firstName = customer?.firstName
@@ -188,15 +192,15 @@ export class InlineCheckout {
188
192
  }
189
193
 
190
194
  setCartItems(items) {
191
- console.log('items: ', items)
192
195
  this.cartItems = items
193
196
  }
194
197
 
195
- setCustomerEmail (email) {
196
- this.email = email
198
+ configureCheckout(data) {
199
+ if ('customer' in data)
200
+ this.#handleCustomer(data['customer'])
197
201
  }
202
+
198
203
  setCartTotal(total) {
199
- console.log('total: ', total)
200
204
  this.cartTotal = total
201
205
  this.#updatePayButton()
202
206
  }
@@ -213,7 +217,6 @@ export class InlineCheckout {
213
217
 
214
218
  injectCheckout() {
215
219
  if (InlineCheckout.injected) return
216
- this.process3ds.verifyTransactionStatus()
217
220
  const containerTonderCheckout = document.querySelector("#tonder-checkout");
218
221
  if (containerTonderCheckout) {
219
222
  this.#mount(containerTonderCheckout)
@@ -230,15 +233,40 @@ export class InlineCheckout {
230
233
  childList: true,
231
234
  subtree: true,
232
235
  attributeFilter: ['id']
233
- });
236
+ });
237
+ }
238
+
239
+ async verify3dsTransaction () {
240
+ const result3ds = await this.process3ds.verifyTransactionStatus()
241
+ const resultCheckout = await this.resumeCheckout(result3ds)
242
+ this.process3ds.setPayload(resultCheckout)
243
+ if (resultCheckout?.is_route_finished && resultCheckout?.provider === 'tonder') {
244
+ return resultCheckout
245
+ }
246
+ return this.handle3dsRedirect(resultCheckout)
234
247
  }
235
248
 
249
+ async resumeCheckout(response) {
250
+ if (["Failed", "Declined", "Cancelled"].includes(response?.status)) {
251
+ const routerItems = {
252
+ // TODO: Replace this with reponse.checkout_id
253
+ checkout_id: this.process3ds.getCurrentCheckoutId(),
254
+ };
255
+ const routerResponse = await startCheckoutRouter(
256
+ this.baseUrl,
257
+ this.apiKeyTonder,
258
+ routerItems
259
+ );
260
+ return routerResponse
261
+ }
262
+ return response
263
+ }
236
264
 
237
265
  #addGlobalLoader() {
238
266
  let checkoutContainer = document.querySelector("#global-loader");
239
267
  if (checkoutContainer) {
240
- checkoutContainer.innerHTML = cardTemplateSkeleton;
241
- checkoutContainer.style.display = 'block';
268
+ checkoutContainer.innerHTML = cardTemplateSkeleton;
269
+ checkoutContainer.style.display = 'block';
242
270
  }
243
271
  }
244
272
 
@@ -249,8 +277,8 @@ export class InlineCheckout {
249
277
  }
250
278
  }
251
279
 
252
- #mount(containerTonderCheckout){
253
- containerTonderCheckout.innerHTML = cardTemplate;
280
+ #mount(containerTonderCheckout) {
281
+ containerTonderCheckout.innerHTML = cardTemplate({renderPaymentButton: this.renderPaymentButton, customStyles: this.customStyles});
254
282
  this.#addGlobalLoader();
255
283
  this.#mountTonder();
256
284
  InlineCheckout.injected = true;
@@ -269,25 +297,45 @@ export class InlineCheckout {
269
297
  return await customerRegister(this.baseUrl, this.apiKeyTonder, customer, signal);
270
298
  }
271
299
 
300
+ async #mountAPMs(){
301
+ try{
302
+ const apms = await getCustomerAPMs(this.baseUrl, this.apiKeyTonder, "?status=active&page_size=10000");
303
+ if(apms && apms['results'] && apms['results'].length > 0){
304
+ this.apmsData = apms['results']
305
+ this.#loadAPMList(apms['results'])
306
+ }
307
+ }catch(e){
308
+ console.warn("Error getting APMS")
309
+ }
310
+ }
272
311
  async #mountTonder(getCards = true) {
273
312
  this.#mountPayButton()
274
- try{
313
+ try {
275
314
  const {
276
315
  vault_id,
277
316
  vault_url,
278
317
  } = await this.#fetchMerchantData();
279
- if(this.email && getCards){
280
- const customerResponse = await this.getCustomer({email: this.email});
281
- if("auth_token" in customerResponse) {
318
+ if (this.email && getCards) {
319
+ const customerResponse = await this.getCustomer({ email: this.email });
320
+ if ("auth_token" in customerResponse) {
282
321
  const { auth_token } = customerResponse
283
- const cards = await getCustomerCards(this.baseUrl, auth_token);
322
+ const saveCardCheckbox = document.getElementById('save-card-container');
284
323
 
285
- if("cards" in cards) {
286
- const cardsMapped = cards.cards.map(mapCards)
287
- this.#loadCardsList(cardsMapped, auth_token)
324
+ saveCardCheckbox.style.display = 'none';
325
+ if (this.mode !== 'production') {
326
+ const cards = await getCustomerCards(this.baseUrl, auth_token);
327
+ saveCardCheckbox.style.display = '';
328
+
329
+ if ("cards" in cards) {
330
+ const cardsMapped = cards.cards.map(mapCards)
331
+ this.#loadCardsList(cardsMapped, auth_token)
332
+ }
288
333
  }
334
+
335
+
289
336
  }
290
337
  }
338
+ this.#mountAPMs();
291
339
 
292
340
  this.collectContainer = await initSkyflow(
293
341
  vault_id,
@@ -301,7 +349,7 @@ export class InlineCheckout {
301
349
  setTimeout(() => {
302
350
  this.#removeGlobalLoader()
303
351
  }, 800)
304
- }catch(e){
352
+ } catch (e) {
305
353
  if (e && e.name !== 'AbortError') {
306
354
  this.#removeGlobalLoader()
307
355
  showError("No se pudieron cargar los datos del comercio.")
@@ -312,6 +360,7 @@ export class InlineCheckout {
312
360
  removeCheckout() {
313
361
  InlineCheckout.injected = false
314
362
  InlineCheckout.cardsInjected = false
363
+ InlineCheckout.apmsInjected = false
315
364
  // Cancel all requests
316
365
  this.abortController.abort();
317
366
  this.abortController = new AbortController();
@@ -342,9 +391,9 @@ export class InlineCheckout {
342
391
  const total = Number(this.cartTotal)
343
392
 
344
393
  let cardTokens = null;
345
- if(this.radioChecked === "new" || this.radioChecked === undefined){
394
+ if (this.radioChecked === "new" || this.radioChecked === undefined) {
346
395
  cardTokens = await this.#getCardTokens();
347
- }else{
396
+ } else {
348
397
  cardTokens = {
349
398
  skyflow_id: this.radioChecked
350
399
  }
@@ -360,24 +409,24 @@ export class InlineCheckout {
360
409
  }
361
410
 
362
411
  const { id, auth_token } = await this.getCustomer(
363
- this.customer,
412
+ this.customer,
364
413
  this.abortController.signal
365
414
  )
366
- if(auth_token && this.email){
415
+ if (auth_token && this.email) {
367
416
  const saveCard = document.getElementById("save-checkout-card");
368
- if(saveCard && "checked" in saveCard && saveCard.checked){
417
+ if (saveCard && "checked" in saveCard && saveCard.checked) {
369
418
  await registerCard(this.baseUrl, auth_token, { skyflow_id: cardTokens.skyflow_id });
370
-
419
+
371
420
  this.cardsInjected = false;
372
421
 
373
422
  const cards = await getCustomerCards(this.baseUrl, auth_token);
374
- if("cards" in cards) {
423
+ if ("cards" in cards) {
375
424
  const cardsMapped = cards.cards.map((card) => mapCards(card))
376
425
  this.#loadCardsList(cardsMapped, auth_token)
377
426
  }
378
427
 
379
428
  showMessage("Tarjeta registrada con éxito", this.collectorIds.msgNotification);
380
-
429
+
381
430
  }
382
431
  }
383
432
  var orderItems = {
@@ -391,7 +440,6 @@ export class InlineCheckout {
391
440
  is_oneclick: true,
392
441
  items: this.cartItems,
393
442
  };
394
- console.log('orderItems: ', orderItems)
395
443
  const jsonResponseOrder = await createOrder(
396
444
  this.baseUrl,
397
445
  this.apiKeyTonder,
@@ -415,9 +463,10 @@ export class InlineCheckout {
415
463
  paymentItems
416
464
  );
417
465
 
466
+ const selected_apm = this.apmsData ? this.apmsData.find((iapm) => iapm.pk === this.radioChecked):{};
467
+
418
468
  // Checkout router
419
469
  const routerItems = {
420
- card: cardTokens,
421
470
  name: this.firstName || "",
422
471
  last_name: this.lastName || "",
423
472
  email_client: this.email,
@@ -439,6 +488,10 @@ export class InlineCheckout {
439
488
  metadata: this.metadata,
440
489
  browser_info: getBrowserInfo(),
441
490
  currency: this.currency,
491
+ ...( !!selected_apm
492
+ ? {payment_method: selected_apm.payment_method}
493
+ : {card: cardTokens}
494
+ )
442
495
  };
443
496
  const jsonResponseRouter = await startCheckoutRouter(
444
497
  this.baseUrl,
@@ -462,8 +515,8 @@ export class InlineCheckout {
462
515
  }
463
516
  };
464
517
 
465
- #loadCardsList (cards, token) {
466
- if(this.cardsInjected) return;
518
+ #loadCardsList(cards, token) {
519
+ if (this.cardsInjected) return;
467
520
  const injectInterval = setInterval(() => {
468
521
  const queryElement = document.querySelector(`#${this.collectorIds.cardsListContainer}`);
469
522
  if (queryElement && InlineCheckout.injected) {
@@ -475,7 +528,25 @@ export class InlineCheckout {
475
528
  }, 500);
476
529
  }
477
530
 
478
- #mountRadioButtons (token) {
531
+ #loadAPMList(apms) {
532
+ if (this.apmsInjected) return;
533
+ const injectInterval = setInterval(() => {
534
+ const queryElement = document.querySelector(`#${this.collectorIds.apmsListContainer}`);
535
+ if (queryElement && InlineCheckout.injected) {
536
+ const filteredAndSortedApms = apms
537
+ .filter((apm) =>
538
+ clearSpace(apm.category.toLowerCase()) !== 'cards' && apm.status.toLowerCase() === 'active')
539
+ .sort((a, b) => a.priority - b.priority);
540
+
541
+ queryElement.innerHTML = apmItemsTemplate(filteredAndSortedApms);
542
+ clearInterval(injectInterval);
543
+ this.#mountRadioButtons();
544
+ this.apmsInjected = true;
545
+ }
546
+ }, 500);
547
+ }
548
+
549
+ #mountRadioButtons(token = '') {
479
550
  const radioButtons = document.getElementsByName(`card_selected`);
480
551
  for (const radio of radioButtons) {
481
552
  radio.style.display = "block";
@@ -492,14 +563,14 @@ export class InlineCheckout {
492
563
  }
493
564
  }
494
565
 
495
- async #handleRadioButtonClick (radio) {
496
- if(radio.id === this.radioChecked || ( radio.id === "new" && this.radioChecked === undefined)) return;
566
+ async #handleRadioButtonClick(radio) {
567
+ if (radio.id === this.radioChecked || (radio.id === "new" && this.radioChecked === undefined)) return;
497
568
  const containerForm = document.querySelector(".container-form");
498
- if(containerForm) {
569
+ if (containerForm) {
499
570
  containerForm.style.display = radio.id === "new" ? "block" : "none";
500
571
  }
501
- if(radio.id === "new") {
502
- if(this.radioChecked !== radio.id) {
572
+ if (radio.id === "new") {
573
+ if (this.radioChecked !== radio.id) {
503
574
  this.#addGlobalLoader()
504
575
  this.#mountTonder(false);
505
576
  InlineCheckout.injected = true;
@@ -510,45 +581,45 @@ export class InlineCheckout {
510
581
  this.radioChecked = radio.id;
511
582
  }
512
583
 
513
- async #handleDeleteCardButtonClick (customerToken, button) {
584
+ async #handleDeleteCardButtonClick(customerToken, button) {
514
585
  const id = button.attributes.getNamedItem("id")
515
586
  const skyflow_id = id?.value?.split("_")?.[2]
516
- if(skyflow_id) {
587
+ if (skyflow_id) {
517
588
  const cardClicked = document.querySelector(`#card_container-${skyflow_id}`);
518
- if(cardClicked) {
589
+ if (cardClicked) {
519
590
  cardClicked.style.display = "none"
520
591
  }
521
- try{
522
- this.deletingCards.push(skyflow_id);
523
- if (this.abortRefreshCardsController) {
524
- this.abortRefreshCardsController.abort();
525
- this.abortRefreshCardsController = new AbortController();
592
+ try {
593
+ this.deletingCards.push(skyflow_id);
594
+ if (this.abortRefreshCardsController) {
595
+ this.abortRefreshCardsController.abort();
596
+ this.abortRefreshCardsController = new AbortController();
597
+ }
598
+ await deleteCustomerCard(this.baseUrl, customerToken, skyflow_id)
599
+ } catch {
600
+ } finally {
601
+ this.deletingCards = this.deletingCards.filter(id => id !== skyflow_id);
602
+ this.#refreshCardOnDelete(customerToken)
526
603
  }
527
- await deleteCustomerCard(this.baseUrl, customerToken, skyflow_id)
528
- }catch{
529
- } finally {
530
- this.deletingCards = this.deletingCards.filter(id => id !== skyflow_id);
531
- this.#refreshCardOnDelete(customerToken)
532
- }
533
604
  }
534
605
  }
535
- async #refreshCardOnDelete(customerToken){
536
- if(this.deletingCards.length > 0) return;
606
+ async #refreshCardOnDelete(customerToken) {
607
+ if (this.deletingCards.length > 0) return;
537
608
  this.cardsInjected = false
538
609
  const cards = await getCustomerCards(this.baseUrl, customerToken, "", this.abortRefreshCardsController.signal)
539
- if("cards" in cards) {
610
+ if ("cards" in cards) {
540
611
  const cardsMapped = cards.cards.map(mapCards)
541
612
  this.#loadCardsList(cardsMapped, customerToken)
542
613
  }
543
614
  }
544
- #unmountForm () {
615
+ #unmountForm() {
545
616
  InlineCheckout.injected = false
546
- if(this.collectContainer) {
547
- if("unmount" in this.collectContainer.elements.cardHolderNameElement) this.collectContainer.elements.cardHolderNameElement.unmount()
548
- if("unmount" in this.collectContainer.elements.cardNumberElement) this.collectContainer.elements.cardNumberElement.unmount()
549
- if("unmount" in this.collectContainer.elements.expiryYearElement) this.collectContainer.elements.expiryYearElement.unmount()
550
- if("unmount" in this.collectContainer.elements.expiryMonthElement) this.collectContainer.elements.expiryMonthElement.unmount()
551
- if("unmount" in this.collectContainer.elements.cvvElement) this.collectContainer.elements.cvvElement.unmount()
617
+ if (this.collectContainer) {
618
+ if ("unmount" in this.collectContainer.elements.cardHolderNameElement) this.collectContainer.elements.cardHolderNameElement.unmount()
619
+ if ("unmount" in this.collectContainer.elements.cardNumberElement) this.collectContainer.elements.cardNumberElement.unmount()
620
+ if ("unmount" in this.collectContainer.elements.expiryYearElement) this.collectContainer.elements.expiryYearElement.unmount()
621
+ if ("unmount" in this.collectContainer.elements.expiryMonthElement) this.collectContainer.elements.expiryMonthElement.unmount()
622
+ if ("unmount" in this.collectContainer.elements.cvvElement) this.collectContainer.elements.cvvElement.unmount()
552
623
  }
553
624
  }
554
625
  }
package/src/data/api.js CHANGED
@@ -165,6 +165,27 @@ export async function getCustomerCards(baseUrlTonder, customerToken, query = "",
165
165
  signal
166
166
  });
167
167
 
168
+ if (response.ok) return await response.json();
169
+ throw await buildErrorResponse(response);
170
+ } catch (error) {
171
+ throw buildErrorResponseFromCatch(error);
172
+ }
173
+ }
174
+
175
+ export async function getCustomerAPMs(baseUrlTonder, apiKeyTonder, query = "", signal) {
176
+ try {
177
+ const response = await fetch(
178
+ // `${baseUrlTonder}/api/v1/payment_methods${query}`,
179
+ `http://localhost:8000/api/v1/payment_methods${query}`,
180
+ {
181
+ method: 'GET',
182
+ headers: {
183
+ Authorization: `Token ${apiKeyTonder}`,
184
+ 'Content-Type': 'application/json'
185
+ },
186
+ signal
187
+ });
188
+
168
189
  if (response.ok) return await response.json();
169
190
  throw await buildErrorResponse(response);
170
191
  } catch (error) {