@tonder.io/ionic-full-sdk 0.0.33-beta → 0.0.35-beta

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.
@@ -39,3 +39,17 @@ export type PaymentData = {
39
39
  items: OrderItem[];
40
40
  };
41
41
  };
42
+ export type TonderAPM = {
43
+ pk: string;
44
+ payment_method: string;
45
+ priority: number;
46
+ category: string;
47
+ unavailable_countries: string[];
48
+ status: string;
49
+ };
50
+ export type APM = {
51
+ id: string;
52
+ payment_method: string;
53
+ priority: number;
54
+ category: string;
55
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonder.io/ionic-full-sdk",
3
- "version": "0.0.33-beta",
3
+ "version": "0.0.35-beta",
4
4
  "description": "Tonder ionic full SDK",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.js",
@@ -10,7 +10,7 @@
10
10
  "author": "",
11
11
  "license": "ISC",
12
12
  "dependencies": {
13
- "@tonder.io/ionic-lite-sdk": "^0.0.32-beta",
13
+ "@tonder.io/ionic-lite-sdk": "^0.0.34-beta",
14
14
  "crypto-js": "^4.1.1",
15
15
  "skyflow-js": "^1.34.1"
16
16
  },
@@ -65,6 +65,19 @@ export class ThreeDSHandler {
65
65
  }
66
66
  }
67
67
 
68
+ saveCheckoutId(checkoutId: any) {
69
+ localStorage.setItem('checkout_id', JSON.stringify(checkoutId))
70
+ }
71
+
72
+ removeCheckoutId() {
73
+ localStorage.removeItem("checkout_id")
74
+ }
75
+
76
+ getCurrentCheckoutId() {
77
+ const checkout_id = localStorage.getItem("checkout_id")
78
+ return checkout_id ? JSON.parse(checkout_id):null; // TODO: JSON.parse de una string?
79
+ }
80
+
68
81
  getUrlWithExpiration() {
69
82
  const status = this.getStorageItem();
70
83
  if(status) {
@@ -154,14 +167,13 @@ export class ThreeDSHandler {
154
167
 
155
168
  handleSuccessTransaction(response: any) {
156
169
  this.removeVerifyTransactionUrl();
157
- console.log('Transacción autorizada exitosamente.');
170
+ console.log('Transacción autorizada.');
158
171
  return response;
159
172
  }
160
173
 
161
174
  handleDeclinedTransaction(response: any) {
162
175
  this.removeVerifyTransactionUrl();
163
- console.log('Transacción rechazada.');
164
- throw new Error("Transacción rechazada.");
176
+ return response;
165
177
  }
166
178
 
167
179
  // TODO: the method below needs to be tested with a real 3DS challenge
@@ -193,14 +205,16 @@ export class ThreeDSHandler {
193
205
  await this.verifyTransactionStatus();
194
206
  }
195
207
 
208
+ // TODO: This method could be removed
196
209
  async handleTransactionResponse(response: any) {
197
210
  const response_json = await response.json();
198
- if (response_json.status === "Pending") {
211
+ if (response_json.status === "Pending" && response_json.redirect_post_url) {
199
212
  return await this.handle3dsChallenge(response_json);
200
213
  } else if (["Success", "Authorized"].includes(response_json.status)) {
201
- return this.handleSuccessTransaction(response);
214
+ return this.handleSuccessTransaction(response_json);
202
215
  } else {
203
- return this.handleDeclinedTransaction(response);
216
+ this.handleDeclinedTransaction(response);
217
+ return response_json
204
218
  }
205
219
  }
206
220
 
@@ -221,17 +235,21 @@ export class ThreeDSHandler {
221
235
 
222
236
  if (response.status !== 200) {
223
237
  console.error('La verificación de la transacción falló.');
224
- return
238
+ this.removeVerifyTransactionUrl();
239
+ return response
225
240
  }
226
241
 
227
242
  return await this.handleTransactionResponse(response);
228
243
  } catch (error) {
229
244
  console.error('Error al verificar la transacción:', error);
230
- return error;
245
+ this.removeVerifyTransactionUrl();
231
246
  }
232
247
  } else {
233
248
  console.log('No verify_transaction_status_url found');
234
249
  }
235
250
  }
236
251
 
252
+ setPayload = (payload: any) => {
253
+ this.payload = payload
254
+ }
237
255
  }
@@ -1,4 +1,4 @@
1
- import { Card, cardItemsTemplate, cardTemplate, CollectorIds } from '../helpers/template'
1
+ import { apmItemsTemplate, Card, cardItemsTemplate, cardTemplate, CollectorIds } from '../helpers/template'
2
2
  import { LiteCheckout } from '@tonder.io/ionic-lite-sdk';
3
3
  import {
4
4
  showError,
@@ -13,6 +13,7 @@ import { Business, Customer, PaymentData, OrderItem } from '@tonder.io/ionic-lit
13
13
  import { CustomerRegisterResponse, StartCheckoutResponse } from '@tonder.io/ionic-lite-sdk/dist/types/responses';
14
14
  import { StartCheckoutRequest, CreatePaymentRequest, CreateOrderRequest } from '@tonder.io/ionic-lite-sdk/dist/types/requests';
15
15
  import { InCollectorContainer } from '../helpers/skyflow';
16
+ import { APM } from 'src/types/commons';
16
17
 
17
18
  export type InlineCheckoutConstructor = {
18
19
  returnUrl: string,
@@ -59,6 +60,8 @@ export class InlineCheckout {
59
60
  containerId: string
60
61
  injected: boolean
61
62
  cardsInjected: boolean
63
+ apmsInjected = false
64
+ apmsData: APM[] = []
62
65
  collectorIds: CollectorIds
63
66
  platforms?: string[]
64
67
  liteCheckout: LiteCheckout
@@ -118,7 +121,8 @@ export class InlineCheckout {
118
121
  tonderPayButton: "tonderPayButton",
119
122
  msgError: "msgError",
120
123
  msgNotification: "msgNotification",
121
- tonderSaveCardButton: "tonderSaveCardButton"
124
+ tonderSaveCardButton: "tonderSaveCardButton",
125
+ apmsListContainer: "apmsListContainer"
122
126
  }
123
127
  this.clientCards = []
124
128
  this.radioChecked = "new"
@@ -172,7 +176,7 @@ export class InlineCheckout {
172
176
  if (!this.renderSaveCardButton) return;
173
177
 
174
178
  const saveButton: HTMLElement | null = document.querySelector(`#${this.collectorIds.tonderSaveCardButton}`);
175
-
179
+
176
180
  if (!saveButton) {
177
181
  console.error("Save button not found");
178
182
  return;
@@ -180,9 +184,9 @@ export class InlineCheckout {
180
184
 
181
185
 
182
186
  saveButton.style.display = "block";
183
-
187
+
184
188
  saveButton.textContent = `Guardar`;
185
-
189
+
186
190
  saveButton.onclick = async (event) => {
187
191
  event.preventDefault();
188
192
  await this.#handleSaveCardClick(saveButton);
@@ -215,6 +219,31 @@ export class InlineCheckout {
215
219
  this.card = data?.card
216
220
  }
217
221
 
222
+ async handle3dsRedirect(response: ErrorResponse | StartCheckoutResponse | false | undefined) {
223
+ const iframe = response && 'next_action' in response ? response?.next_action?.iframe_resources?.iframe:null
224
+
225
+ if (iframe) {
226
+ this.process3ds.loadIframe()!.then(() => {
227
+ //TODO: Check if this will be necessary on the frontend side
228
+ // after some the tests in production, since the 3DS process
229
+ // doesn't works properly on the sandbox environment
230
+ // setTimeout(() => {
231
+ // process3ds.verifyTransactionStatus();
232
+ // }, 10000);
233
+ this.process3ds.verifyTransactionStatus();
234
+ }).catch((error) => {
235
+ console.log('Error loading iframe:', error)
236
+ })
237
+ } else {
238
+ const redirectUrl = this.process3ds.getRedirectUrl()
239
+ if (redirectUrl) {
240
+ this.process3ds.redirectToChallenge()
241
+ } else {
242
+ return response;
243
+ }
244
+ }
245
+ }
246
+
218
247
  payment(data: any) {
219
248
  return new Promise(async (resolve, reject) => {
220
249
  try {
@@ -225,37 +254,12 @@ export class InlineCheckout {
225
254
  this.#handleCurrency(data)
226
255
  this.#handleCard(data)
227
256
  const response: ErrorResponse | StartCheckoutResponse | false | undefined = await this.#checkout()
228
- if (response) {
229
- const process3ds = new ThreeDSHandler({
230
- payload: response,
231
- baseUrl: this.baseUrl,
232
- apiKey: this.apiKeyTonder,
233
- successUrl: this.successUrl
234
- });
235
- this.callBack(response);
236
- if("next_action" in response) {
237
- const iframe = response?.next_action?.iframe_resources?.iframe
238
- if (iframe) {
239
- process3ds.loadIframe()?.then(() => {
240
- //TODO: Check if this will be necessary on the frontend side
241
- // after some the tests in production, since the 3DS process
242
- // doesn't works properly on the sandbox environment
243
- // setTimeout(() => {
244
- // process3ds.verifyTransactionStatus();
245
- // }, 10000);
246
- process3ds.verifyTransactionStatus();
247
- }).catch((error) => {
248
- console.log('Error loading iframe:', error)
249
- })
250
- } else {
251
- const redirectUrl = process3ds.getRedirectUrl()
252
- if (redirectUrl) {
253
- process3ds.redirectToChallenge()
254
- } else {
255
- resolve(response);
256
- }
257
- }
258
- }
257
+ this.process3ds.setPayload(response)
258
+ this.process3ds.saveCheckoutId(response && 'checkout_id' in response ? response.checkout_id:"")
259
+ this.callBack(response);
260
+ const payload = await this.handle3dsRedirect(response)
261
+ if (payload) {
262
+ resolve(response);
259
263
  }
260
264
  } catch (error) {
261
265
  reject(error);
@@ -263,7 +267,7 @@ export class InlineCheckout {
263
267
  });
264
268
  }
265
269
 
266
- #mountRadioButtons (token: string) {
270
+ #mountRadioButtons (token: string = "") {
267
271
  const radioButtons: NodeListOf<HTMLElement> = document.getElementsByName(`card_selected`);
268
272
  for (const radio of radioButtons) {
269
273
  radio.style.display = "block";
@@ -358,11 +362,10 @@ export class InlineCheckout {
358
362
 
359
363
  injectCheckout() {
360
364
  if (this.injected) return
361
- this.process3ds.verifyTransactionStatus()
362
365
  const injectInterval = setInterval(() => {
363
366
  const queryElement = document.querySelector(`#${this.containerId}`)
364
367
  if (queryElement) {
365
- queryElement.innerHTML = cardTemplate(this.customStyles ? true : false, this.collectorIds, this.isEnrollmentCard)
368
+ queryElement.innerHTML = cardTemplate(this.customStyles ? true : false, this.collectorIds, this.isEnrollmentCard, { renderPaymentButton: this.renderPaymentButton })
366
369
  this.#mountTonder();
367
370
  clearInterval(injectInterval);
368
371
  this.injected = true
@@ -370,6 +373,30 @@ export class InlineCheckout {
370
373
  }, 500);
371
374
  }
372
375
 
376
+ async verify3dsTransaction () {
377
+ const result3ds = await this.process3ds.verifyTransactionStatus()
378
+ const resultCheckout = await this.resumeCheckout(result3ds)
379
+ this.process3ds.setPayload(resultCheckout)
380
+ if (resultCheckout && 'is_route_finished' in resultCheckout && 'provider' in resultCheckout && resultCheckout.provider === 'tonder') {
381
+ return resultCheckout
382
+ }
383
+ return this.handle3dsRedirect(resultCheckout)
384
+ }
385
+
386
+ async resumeCheckout(response: any) {
387
+ if (["Failed", "Declined", "Cancelled"].includes(response?.status)) {
388
+ const routerItems = {
389
+ // TODO: Replace this with reponse.checkout_id
390
+ checkout_id: this.process3ds.getCurrentCheckoutId(),
391
+ };
392
+ const routerResponse = await this.liteCheckout.handleCheckoutRouter(
393
+ routerItems
394
+ );
395
+ return routerResponse
396
+ }
397
+ return response
398
+ }
399
+
373
400
  loadCardsList (cards: Card[], token: string) {
374
401
  if(this.cardsInjected) return;
375
402
  const injectInterval = setInterval(() => {
@@ -392,6 +419,31 @@ export class InlineCheckout {
392
419
  return await this.liteCheckout.customerRegister(email);
393
420
  }
394
421
 
422
+ async #mountAPMs(){
423
+ try{
424
+ const apms: APM[] = await this.liteCheckout.getActiveAPMs();
425
+ if(apms.length > 0){
426
+ this.apmsData = apms;
427
+ this.#loadAPMList(apms)
428
+ }
429
+ }catch(e){
430
+ console.warn("Error getting APMS")
431
+ }
432
+ }
433
+
434
+ #loadAPMList(apms: APM[]) {
435
+ if (this.apmsInjected) return;
436
+ const injectInterval = setInterval(() => {
437
+ const queryElement = document.querySelector(`#${this.collectorIds.apmsListContainer}`);
438
+ if (queryElement && this.injected) {
439
+ queryElement.innerHTML = apmItemsTemplate(this.customStyles ? true : false, apms);
440
+ clearInterval(injectInterval);
441
+ this.#mountRadioButtons();
442
+ this.apmsInjected = true;
443
+ }
444
+ }, 500);
445
+ }
446
+
395
447
  async #mountTonder() {
396
448
  if(this.isEnrollmentCard){
397
449
  this.#mountSaveCardButton()
@@ -426,6 +478,8 @@ export class InlineCheckout {
426
478
  }
427
479
 
428
480
  }
481
+
482
+ await this.#mountAPMs();
429
483
 
430
484
  this.collectContainer = await initSkyflow(
431
485
  vault_id,
@@ -445,6 +499,7 @@ export class InlineCheckout {
445
499
 
446
500
  this.injected = false
447
501
  this.cardsInjected = false
502
+ this.apmsInjected = false
448
503
  // Cancel all requests
449
504
  this.abortController.abort();
450
505
  this.abortController = new AbortController();
@@ -490,7 +545,6 @@ export class InlineCheckout {
490
545
  }
491
546
 
492
547
  async #getCardTokens(tonderButton: string){
493
- console.log("this.collectContainer: ", this.collectContainer)
494
548
  if(this.collectContainer && "container" in this.collectContainer && "collect" in this.collectContainer.container) {
495
549
  try {
496
550
  const collectResponseSkyflowTonder: any = await this.collectContainer?.container.collect();
@@ -507,7 +561,7 @@ export class InlineCheckout {
507
561
  try {
508
562
 
509
563
  const selector: any = document.querySelector(`#${this.collectorIds.tonderSaveCardButton}`);
510
-
564
+
511
565
  if(selector){
512
566
  selector.disabled = disabled;
513
567
  selector.innerHTML = text
@@ -522,7 +576,7 @@ export class InlineCheckout {
522
576
  if(this.merchantData && "openpay_keys" in this.merchantData) {
523
577
  const cardTokensSkyflowTonder: any = await this.#getCardTokens(this.collectorIds.tonderSaveCardButton!);
524
578
  const customerResponse : CustomerRegisterResponse | ErrorResponse = await this.getCustomer(this.email);
525
-
579
+
526
580
  if("auth_token" in customerResponse) {
527
581
  const { auth_token, id: cutomerId } = customerResponse;
528
582
  console.log("cardTokensSkyflowTonder: ", cardTokensSkyflowTonder)
@@ -674,10 +728,11 @@ export class InlineCheckout {
674
728
  const jsonResponsePayment = await this.liteCheckout.createPayment(
675
729
  paymentItems
676
730
  );
677
-
731
+
732
+ const selected_apm: APM | undefined | null = this.apmsData ? this.apmsData.find((iapm) => iapm.id === this.radioChecked):null;
733
+
678
734
  // Checkout router
679
735
  const routerItems: StartCheckoutRequest = {
680
- card: cardTokensSkyflowTonder,
681
736
  name: this.firstName,
682
737
  last_name: this.lastName ?? "",
683
738
  email_client: this.email,
@@ -698,10 +753,14 @@ export class InlineCheckout {
698
753
  source: 'sdk',
699
754
  metadata: this.metadata,
700
755
  browser_info: getBrowserInfo(),
701
- currency: this.currency
756
+ currency: this.currency,
757
+ ...( !!selected_apm
758
+ ? {payment_method: selected_apm.payment_method}
759
+ : {card: cardTokensSkyflowTonder}
760
+ )
702
761
  };
703
762
 
704
- const jsonResponseRouter = await this.liteCheckout.startCheckoutRouter(
763
+ const jsonResponseRouter = await this.liteCheckout.handleCheckoutRouter(
705
764
  routerItems
706
765
  );
707
766
 
@@ -1,4 +1,6 @@
1
+ import { APM } from 'src/types/commons';
1
2
  import { getCardType } from './utils';
3
+ import { getPaymentMethodDetails } from '@tonder.io/ionic-lite-sdk/dist/helpers/utils';
2
4
 
3
5
  export type CollectorIds = {
4
6
  holderName: string,
@@ -10,7 +12,8 @@ export type CollectorIds = {
10
12
  tonderSaveCardButton?: string,
11
13
  msgError: string,
12
14
  msgNotification: string,
13
- cardsListContainer: string
15
+ cardsListContainer: string,
16
+ apmsListContainer?: string
14
17
  }
15
18
 
16
19
  export type Card = {
@@ -22,7 +25,7 @@ export type Card = {
22
25
  skyflow_id: string
23
26
  }
24
27
 
25
- export const cardTemplate = (external: boolean, collectorIds: CollectorIds, isEnrollmentCard: boolean = false) => `
28
+ export const cardTemplate = (external: boolean, collectorIds: CollectorIds, isEnrollmentCard: boolean = false, data: {renderPaymentButton?: boolean} = {}) => `
26
29
  <div class="container-tonder">
27
30
  <div id="${collectorIds.cardsListContainer}" class="cards-list-container"></div>
28
31
  ${!isEnrollmentCard ? `
@@ -53,8 +56,11 @@ export const cardTemplate = (external: boolean, collectorIds: CollectorIds, isEn
53
56
  <div id="${collectorIds.msgError}"></div>
54
57
  <div id="${collectorIds.msgNotification}"></div>
55
58
  </div>
56
- <button id="${collectorIds.tonderPayButton}" class="pay-button">Pagar</button>
57
- <button id="${collectorIds.tonderSaveCardButton ? collectorIds.tonderSaveCardButton:''}" class="save-card-button">Guardar</button>
59
+ <div id="apmsListContainer" class="apms-list-container"></div>
60
+ <div class="container-pay-button">
61
+ <button id="${collectorIds.tonderPayButton}" class="pay-button">Pagar</button>
62
+ <button id="${collectorIds.tonderSaveCardButton ? collectorIds.tonderSaveCardButton:''}" class="save-card-button">Guardar</button>
63
+ </div>
58
64
  </div>
59
65
 
60
66
  ${external ? `` : `<style>
@@ -93,6 +99,10 @@ ${external ? `` : `<style>
93
99
  border: solid 1px #e3e3e3;
94
100
  }
95
101
 
102
+ .container-pay-button{
103
+ padding: ${!!data['renderPaymentButton'] ? '30px 25px':''};
104
+ }
105
+
96
106
  .collect-row {
97
107
  display: flex !important;
98
108
  justify-content: space-between !important;
@@ -224,6 +234,14 @@ ${external ? `` : `<style>
224
234
  gap: 33% 20px;
225
235
  }
226
236
 
237
+ .apms-list-container {
238
+ display: flex;
239
+ flex-direction: column;
240
+ gap: 33% 20px;
241
+ max-height: 300px;
242
+ overflow-y: auto;
243
+ }
244
+
227
245
  .checkbox label {
228
246
  margin-left: 10px;
229
247
  font-size: '12px';
@@ -518,4 +536,164 @@ export const cardItemsTemplate = (external: boolean, cards: Card[]) => {
518
536
  ${cardItemStyle}
519
537
  `
520
538
  return cardItem;
539
+ }
540
+
541
+ export const apmItemsTemplate = (external: boolean, apms: APM[]) => {
542
+
543
+ const apmItemsHTML = apms.reduce((_, apm) => {
544
+ const apm_data = getPaymentMethodDetails(apm.payment_method);
545
+ return `
546
+ <div class="apm-item" id="card_container-${apm.id}">
547
+ <input id="${apm.id}" class="card_selected" name="card_selected" type="radio"/>
548
+ <label class="apm-item-label" for="${apm.id}">
549
+ <div class="apm-image">
550
+ <div class="apm-image-border"></div>
551
+ <img src="${apm_data.icon}" />
552
+ </div>
553
+ <div class="apm-name">${apm_data.label}</div>
554
+ </label>
555
+ </div>`
556
+ }, ``);
557
+
558
+ const apmItemStyle = external ? '' :`
559
+ <style>
560
+ .apm-item-label {
561
+ display: flex;
562
+ justify-content: flex-start;
563
+ align-items: center;
564
+ color: #1D1D1D;
565
+ gap: 33% 10px;
566
+ margin-top: 15px;
567
+ margin-bottom: 15px;
568
+ width: 100%;
569
+ }
570
+
571
+ .apm-item {
572
+ position: relative;
573
+ display: flex;
574
+ justify-content: start;
575
+ align-items: center;
576
+ gap: 33% 15px;
577
+ border-bottom: 1px solid #e2e8f0;
578
+ padding: 0px 30px;
579
+ }
580
+
581
+ .apm-item:first-child {
582
+ border-top: 1px solid #e2e8f0;
583
+ }
584
+
585
+ .apm-item .apm-name {
586
+ font-size: 16px;
587
+ }
588
+ .apm-image {
589
+ width: 30px;
590
+ height: 30px;
591
+ position: relative;
592
+ display: flex;
593
+ justify-content: center;
594
+ align-items: center;
595
+ }
596
+ .apm-image img {
597
+ width: auto;
598
+ height: 30px;
599
+ }
600
+ .apm-image-border{
601
+ position: absolute;
602
+ border: 1px solid #bababa36;
603
+ border-radius: 4px;
604
+ pointer-events: none;
605
+ box-sizing: border-box;
606
+ width: 100%;
607
+ height: 97%;
608
+ }
609
+
610
+ .card_selected {
611
+ position: relative;
612
+ width: 16px;
613
+ min-width: 16px;
614
+ height: 16px;
615
+ appearance: none;
616
+ cursor: pointer;
617
+ border-radius: 100%;
618
+ border: 1px #bababa solid;
619
+ color: #3bc635;
620
+ transition-property: all;
621
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
622
+ transition-duration: 150ms;
623
+ }
624
+
625
+ .card_selected:before {
626
+ width: 8px;
627
+ height: 8px;
628
+ content: "";
629
+ position: absolute;
630
+ top: 50%;
631
+ left: 50%;
632
+ display: block;
633
+ transform: translate(-50%, -50%);
634
+ border-radius: 100%;
635
+ background-color: #3bc635;
636
+ opacity: 0;
637
+ transition-property: opacity;
638
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
639
+ transition-duration: 150ms;
640
+ }
641
+
642
+ .card_selected:checked {
643
+ border: 1px #3bc635 solid;
644
+ position: relative;
645
+ width: 16px;
646
+ height: 16px;
647
+ min-width: 16px;
648
+ appearance: none;
649
+ cursor: pointer;
650
+ border-radius: 100%;
651
+ color: #3bc635;
652
+ transition-property: all;
653
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
654
+ transition-duration: 150ms;
655
+ }
656
+
657
+ .card_selected:checked:before {
658
+ content: "";
659
+ border: 1px #3bc635 solid;
660
+ width: 8px;
661
+ height: 8px;
662
+ position: absolute;
663
+ top: 50%;
664
+ left: 50%;
665
+ display: block;
666
+ transform: translate(-50%, -50%);
667
+ border-radius: 100%;
668
+ background-color: #3bc635;
669
+ opacity: 50;
670
+ transition-property: opacity;
671
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
672
+ transition-duration: 150ms;
673
+ }
674
+
675
+ .card_selected:hover:before {
676
+ width: 8px;
677
+ height: 8px;
678
+ content: "";
679
+ position: absolute;
680
+ top: 50%;
681
+ left: 50%;
682
+ display: block;
683
+ transform: translate(-50%, -50%);
684
+ border-radius: 100%;
685
+ background-color: #3bc635;
686
+ transition-property: opacity;
687
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
688
+ transition-duration: 150ms;
689
+ opacity: 10;
690
+ }
691
+
692
+ </style>
693
+ `
694
+ const apmItem = `
695
+ ${apmItemsHTML}
696
+ ${apmItemStyle}
697
+ `
698
+ return apmItem;
521
699
  }
package/src/index-dev.js CHANGED
@@ -102,7 +102,9 @@ const inlineCheckout = new InlineCheckout({
102
102
  });
103
103
 
104
104
  inlineCheckout.injectCheckout();
105
-
105
+ inlineCheckout.verify3dsTransaction().then(response => {
106
+ console.log('Verify 3ds response', response)
107
+ })
106
108
  document.addEventListener('DOMContentLoaded', function() {
107
109
  const payButton = document.getElementById('pay-button');
108
110
  payButton.addEventListener('click', async function() {
@@ -41,4 +41,20 @@ export type PaymentData = {
41
41
  total: string | number,
42
42
  items: OrderItem[]
43
43
  }
44
+ }
45
+
46
+ export type TonderAPM = {
47
+ pk: string;
48
+ payment_method: string;
49
+ priority: number;
50
+ category: string;
51
+ unavailable_countries: string[];
52
+ status: string;
53
+ }
54
+
55
+ export type APM = {
56
+ id: string;
57
+ payment_method: string;
58
+ priority: number;
59
+ category: string;
44
60
  }