@tonder.io/ionic-full-sdk 0.0.3 → 0.0.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonder.io/ionic-full-sdk",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
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.6",
13
+ "@tonder.io/ionic-lite-sdk": "^0.0.12",
14
14
  "crypto-js": "^4.1.1",
15
15
  "skyflow-js": "^1.34.1"
16
16
  },
@@ -42,9 +42,7 @@ export class ThreeDSHandler {
42
42
  redirectTo3DS() {
43
43
  const url = this.payload?.next_action?.redirect_to_url?.url
44
44
  if (url) {
45
- this.saveVerifyTransactionUrl()
46
- window.open('@tonder/ionic-full-sdk://', '_system')
47
- // window.open(url, '_blank');
45
+ this.saveVerifyTransactionUrl();
48
46
  return true
49
47
  } else {
50
48
  console.log('No redirection found');
@@ -10,6 +10,7 @@ import { ErrorResponse } from '@tonder.io/ionic-lite-sdk/dist/classes/errorRespo
10
10
  import { Business, Customer, PaymentData, OrderItem } from '@tonder.io/ionic-lite-sdk/dist/types/commons';
11
11
  import { CustomerRegisterResponse, StartCheckoutResponse } from '@tonder.io/ionic-lite-sdk/dist/types/responses';
12
12
  import { StartCheckoutRequest, CreatePaymentRequest, CreateOrderRequest } from '@tonder.io/ionic-lite-sdk/dist/types/requests';
13
+ import { InCollectorContainer } from '../helpers/skyflow';
13
14
 
14
15
  export type InlineCheckoutConstructor = {
15
16
  returnUrl: string,
@@ -18,18 +19,15 @@ export type InlineCheckoutConstructor = {
18
19
  renderPaymentButton: boolean,
19
20
  callBack?: (params: any) => void,
20
21
  styles?: any,
21
- form?: any,
22
- totalElement?: any,
23
22
  containerId?: string,
24
- collectorIds?: CollectorIds,
25
- platforms?: string[]
23
+ collectorIds?: CollectorIds
26
24
  }
27
25
 
28
26
  export class InlineCheckout {
29
27
  paymentData = {}
30
28
  items = []
31
29
  baseUrl = "https://stage.tonder.io";
32
- collectContainer: any = null
30
+ collectContainer: InCollectorContainer | null = null;
33
31
  cartTotal?: string | null | number
34
32
  apiKeyTonder: string
35
33
  returnUrl?: string
@@ -60,6 +58,7 @@ export class InlineCheckout {
60
58
  liteCheckout: LiteCheckout
61
59
  clientCards: Card[]
62
60
  radioChecked: string | null
61
+ fetchingPayment: boolean
63
62
 
64
63
  constructor ({
65
64
  apiKey,
@@ -69,8 +68,7 @@ export class InlineCheckout {
69
68
  callBack = () => {},
70
69
  styles,
71
70
  containerId,
72
- collectorIds,
73
- platforms
71
+ collectorIds
74
72
  }: InlineCheckoutConstructor) {
75
73
  this.apiKeyTonder = apiKey;
76
74
  this.returnUrl = returnUrl;
@@ -78,7 +76,6 @@ export class InlineCheckout {
78
76
  this.renderPaymentButton = renderPaymentButton;
79
77
  this.callBack = callBack;
80
78
  this.customStyles = styles
81
- this.platforms = platforms
82
79
 
83
80
  this.abortController = new AbortController()
84
81
 
@@ -109,6 +106,9 @@ export class InlineCheckout {
109
106
  }
110
107
  this.clientCards = []
111
108
  this.radioChecked = "new"
109
+ this.collectContainer = null;
110
+
111
+ this.fetchingPayment = false;
112
112
  }
113
113
 
114
114
  #mountPayButton() {
@@ -179,6 +179,11 @@ export class InlineCheckout {
179
179
  if(containerForm) {
180
180
  containerForm.style.display = radio.id === "new" ? "block" : "none";
181
181
  }
182
+ if(radio.id === "new") {
183
+ await this.#mountForm();
184
+ } else {
185
+ this.#unmountForm();
186
+ }
182
187
  this.radioChecked = radio.id;
183
188
  }
184
189
 
@@ -282,7 +287,7 @@ export class InlineCheckout {
282
287
 
283
288
  if("cards" in cards) {
284
289
 
285
- const cardsMapped: Card[] = cards.cards.records.map(record => ({ ...record.fields }))
290
+ const cardsMapped: Card[] = cards.cards.map(card => ({ ...card.fields }))
286
291
 
287
292
  this.loadCardsList(cardsMapped)
288
293
 
@@ -307,53 +312,99 @@ export class InlineCheckout {
307
312
  }
308
313
 
309
314
  removeCheckout() {
315
+
310
316
  this.injected = false
311
317
  this.cardsInjected = false
312
318
  // Cancel all requests
313
319
  this.abortController.abort();
314
320
  this.abortController = new AbortController();
315
-
316
321
  clearInterval(this.injectInterval);
317
322
  console.log("InlineCheckout removed from DOM and cleaned up.");
323
+
318
324
  }
319
325
 
320
- async #checkout() {
321
- try {
322
- const selector: any = document.querySelector(`#${this.collectorIds.tonderPayButton}`);
323
- if(selector){
324
- selector.disabled = true;
325
- }
326
- } catch (error) {
326
+ #unmountForm () {
327
+
328
+ this.injected = false
329
+
330
+ if(this.collectContainer) {
331
+ if("unmount" in this.collectContainer.elements.cardHolderNameElement) this.collectContainer.elements.cardHolderNameElement.unmount()
332
+ if("unmount" in this.collectContainer.elements.cardNumberElement) this.collectContainer.elements.cardNumberElement.unmount()
333
+ if("unmount" in this.collectContainer.elements.expiryYearElement) this.collectContainer.elements.expiryYearElement.unmount()
334
+ if("unmount" in this.collectContainer.elements.expiryMonthElement) this.collectContainer.elements.expiryMonthElement.unmount()
335
+ if("unmount" in this.collectContainer.elements.cvvElement) this.collectContainer.elements.cvvElement.unmount()
327
336
  }
328
337
 
329
- if(this.merchantData) {
338
+ }
330
339
 
331
- if("openpay_keys" in this.merchantData) {
340
+ async #mountForm () {
332
341
 
333
- const { openpay_keys, reference, business } = this.merchantData
342
+ const result = await this.#fetchMerchantData();
334
343
 
335
- const total = Number(this.cartTotal)
344
+ if(result && "vault_id" in result) {
345
+
346
+ const { vault_id, vault_url } = result;
336
347
 
337
- let cardTokensSkyflowTonder: any = null;
348
+ this.collectContainer = await initSkyflow(
349
+ vault_id,
350
+ vault_url,
351
+ this.baseUrl,
352
+ this.abortController.signal,
353
+ this.customStyles,
354
+ this.collectorIds,
355
+ this.apiKeyTonder
356
+ );
338
357
 
339
- if(this.radioChecked === "new") {
340
- try {
341
- const collectResponseSkyflowTonder = await this.collectContainer?.collect();
342
- cardTokensSkyflowTonder = await collectResponseSkyflowTonder["records"][0]["fields"];
343
- } catch (error) {
344
- showError("Por favor, verifica todos los campos de tu tarjeta", this.collectorIds.msgError, this.collectorIds.tonderPayButton)
345
- throw error;
346
- }
347
-
348
- } else {
358
+ }
349
359
 
350
- cardTokensSkyflowTonder = {
351
- skyflow_id: this.radioChecked
352
- }
353
-
360
+ }
361
+
362
+ async #checkout() {
363
+
364
+ try {
365
+
366
+ try {
367
+
368
+ const selector: any = document.querySelector(`#${this.collectorIds.tonderPayButton}`);
369
+
370
+ if(selector){
371
+ selector.disabled = true;
372
+ selector.innerHTML = "Cargando..."
354
373
  }
355
374
 
356
- try {
375
+ } catch (error) { }
376
+
377
+ if(this.merchantData) {
378
+
379
+ if("openpay_keys" in this.merchantData) {
380
+
381
+ const { openpay_keys, reference, business } = this.merchantData
382
+
383
+ const total = Number(this.cartTotal)
384
+
385
+ let cardTokensSkyflowTonder: any = null;
386
+
387
+ if(this.radioChecked === "new") {
388
+
389
+ if(this.collectContainer && "container" in this.collectContainer && "collect" in this.collectContainer.container) {
390
+ try {
391
+ const collectResponseSkyflowTonder: any = await this.collectContainer?.container.collect();
392
+ cardTokensSkyflowTonder = await collectResponseSkyflowTonder["records"][0]["fields"];
393
+ } catch (error) {
394
+ showError("Por favor, verifica todos los campos de tu tarjeta", this.collectorIds.msgError, this.collectorIds.tonderPayButton)
395
+ throw error;
396
+ }
397
+ } else {
398
+ showError("Por favor, verifica todos los campos de tu tarjeta", this.collectorIds.msgError, this.collectorIds.tonderPayButton)
399
+ }
400
+
401
+ } else {
402
+
403
+ cardTokensSkyflowTonder = {
404
+ skyflow_id: this.radioChecked
405
+ }
406
+
407
+ }
357
408
 
358
409
  let deviceSessionIdTonder: any;
359
410
 
@@ -384,7 +435,7 @@ export class InlineCheckout {
384
435
 
385
436
  if("cards" in cards) {
386
437
 
387
- const cardsMapped: Card[] = cards.cards.records.map(record => ({ ...record.fields }))
438
+ const cardsMapped: Card[] = cards.cards.map(card => ({ ...card.fields }))
388
439
 
389
440
  this.loadCardsList(cardsMapped)
390
441
 
@@ -453,7 +504,6 @@ export class InlineCheckout {
453
504
  const jsonResponseRouter = await this.liteCheckout.startCheckoutRouter(
454
505
  routerItems
455
506
  );
456
-
457
507
  if (jsonResponseRouter) {
458
508
  try {
459
509
  const selector: any = document.querySelector(`#${this.collectorIds.tonderPayButton}`);
@@ -469,14 +519,16 @@ export class InlineCheckout {
469
519
  }
470
520
  }
471
521
  }
472
- } catch (error) {
473
- console.log(error);
474
- showError("Ha ocurrido un error", this.collectorIds.msgError, this.collectorIds.tonderPayButton)
475
- throw error;
476
522
  }
477
-
523
+ } else {
524
+ showError("No se han configurado los datos del proveedor de servicio", this.collectorIds.msgError, this.collectorIds.tonderPayButton)
478
525
  }
479
-
526
+ } catch (error) {
527
+ console.log(error);
528
+ showError("Ha ocurrido un error", this.collectorIds.msgError, this.collectorIds.tonderPayButton)
529
+ throw error;
530
+ } finally {
531
+ this.fetchingPayment = false;
480
532
  }
481
533
  };
482
534
  }
@@ -5,6 +5,13 @@ import { CollectorIds } from "./template";
5
5
  import CollectorContainer from "skyflow-js/types/core/external/collect/collect-container"
6
6
  import ComposableContainer from "skyflow-js/types/core/external/collect/compose-collect-container"
7
7
  import RevealContainer from "skyflow-js/types/core/external/reveal/reveal-container"
8
+ import RevealElement from "skyflow-js/types/core/external/reveal/reveal-element";
9
+ import ComposableElement from "skyflow-js/types/core/external/collect/compose-collect-element";
10
+
11
+ export type InCollectorContainer = {
12
+ container: CollectorContainer | ComposableContainer | RevealContainer,
13
+ elements: { [ index: string ]: CollectElement | ComposableElement | RevealElement }
14
+ }
8
15
 
9
16
  export async function initSkyflow(
10
17
  vaultId: string,
@@ -14,7 +21,7 @@ export async function initSkyflow(
14
21
  customStyles: any = {},
15
22
  collectorIds: CollectorIds,
16
23
  apiKey: string
17
- ): Promise <CollectorContainer | ComposableContainer | RevealContainer> {
24
+ ): Promise <InCollectorContainer> {
18
25
  const skyflow = await Skyflow.init({
19
26
  vaultID: vaultId,
20
27
  vaultURL: vaultUrl,
@@ -59,7 +66,7 @@ export async function initSkyflow(
59
66
  },
60
67
  };
61
68
 
62
- const cardHolderNameElement: any = await collectContainer.create({
69
+ const cardHolderNameElement: CollectElement | RevealElement | ComposableElement = await collectContainer.create({
63
70
  table: "cards",
64
71
  column: "cardholder_name",
65
72
  ...collectStylesOptions,
@@ -69,10 +76,12 @@ export async function initSkyflow(
69
76
  validations: [lengthMatchRule],
70
77
  });
71
78
 
72
- cardHolderNameElement.setError('Inválido')
79
+ if("setError" in cardHolderNameElement) {
80
+ cardHolderNameElement.setError('Inválido')
81
+ }
73
82
 
74
83
  // Create collect elements.
75
- const cardNumberElement: any = await collectContainer.create({
84
+ const cardNumberElement: CollectElement | RevealElement | ComposableElement = await collectContainer.create({
76
85
  table: "cards",
77
86
  column: "card_number",
78
87
  ...collectStylesOptions,
@@ -85,9 +94,11 @@ export async function initSkyflow(
85
94
  type: Skyflow.ElementType.CARD_NUMBER,
86
95
  });
87
96
 
88
- cardNumberElement.setError('Inválido')
97
+ if("setError" in cardNumberElement) {
98
+ cardNumberElement.setError('Inválido')
99
+ }
89
100
 
90
- const cvvElement: any = await collectContainer.create({
101
+ const cvvElement: CollectElement | RevealElement | ComposableElement = await collectContainer.create({
91
102
  table: "cards",
92
103
  column: "cvv",
93
104
  ...collectStylesOptions,
@@ -95,10 +106,12 @@ export async function initSkyflow(
95
106
  placeholder: "3-4 dígitos",
96
107
  type: Skyflow.ElementType.CVV,
97
108
  });
109
+
110
+ if("setError" in cvvElement) {
111
+ cvvElement.setError('Inválido')
112
+ }
98
113
 
99
- cvvElement.setError('Inválido')
100
-
101
- const expiryMonthElement: any = await collectContainer.create({
114
+ const expiryMonthElement: CollectElement | RevealElement | ComposableElement = await collectContainer.create({
102
115
  table: "cards",
103
116
  column: "expiration_month",
104
117
  ...collectStylesOptions,
@@ -107,9 +120,11 @@ export async function initSkyflow(
107
120
  type: Skyflow.ElementType.EXPIRATION_MONTH,
108
121
  });
109
122
 
110
- expiryMonthElement.setError('Inválido')
123
+ if("setError" in expiryMonthElement) {
124
+ expiryMonthElement.setError('Inválido')
125
+ }
111
126
 
112
- const expiryYearElement: any = await collectContainer.create({
127
+ const expiryYearElement: CollectElement | RevealElement | ComposableElement = await collectContainer.create({
113
128
  table: "cards",
114
129
  column: "expiration_year",
115
130
  ...collectStylesOptions,
@@ -118,7 +133,9 @@ export async function initSkyflow(
118
133
  type: Skyflow.ElementType.EXPIRATION_YEAR,
119
134
  });
120
135
 
121
- expiryYearElement.setError('Inválido')
136
+ if("setError" in expiryYearElement) {
137
+ expiryYearElement.setError('Inválido')
138
+ }
122
139
 
123
140
  await mountElements(
124
141
  { id: collectorIds.cardNumber, element: cardNumberElement },
@@ -128,7 +145,16 @@ export async function initSkyflow(
128
145
  { id: collectorIds.holderName, element: cardHolderNameElement }
129
146
  )
130
147
 
131
- return collectContainer
148
+ return {
149
+ container: collectContainer,
150
+ elements: {
151
+ cardHolderNameElement,
152
+ cardNumberElement,
153
+ cvvElement,
154
+ expiryMonthElement,
155
+ expiryYearElement
156
+ }
157
+ }
132
158
  }
133
159
 
134
160
  async function mountElements(
@@ -38,7 +38,12 @@ export const cardTemplate = (external: boolean, collectorIds: CollectorIds) => `
38
38
  <div id="${collectorIds.expirationYear}" class="expiration-year"></div>
39
39
  <div id="${collectorIds.cvv}" class="empty-div"></div>
40
40
  </div>
41
- <div class="checkbox"><input id="save-checkout-card" type="checkbox"><label for="save-checkout-card">Guardar tarjeta para futuros pagos</label></div>
41
+ <div class="checkbox">
42
+ <input id="save-checkout-card" type="checkbox">
43
+ <label for="save-checkout-card">
44
+ Guardar tarjeta para futuros pagos
45
+ </label>
46
+ </div>
42
47
  <div id="${collectorIds.msgError}"></div>
43
48
  <div id="${collectorIds.msgNotification}"></div>
44
49
  </div>
@@ -47,6 +52,8 @@ export const cardTemplate = (external: boolean, collectorIds: CollectorIds) => `
47
52
 
48
53
  ${external ? `` : `<style>
49
54
 
55
+ @import url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;700&display=swap");
56
+
50
57
  .container-tonder {
51
58
  background-color: #F9F9F9;
52
59
  margin: 0 auto !important;
@@ -115,6 +122,10 @@ ${external ? `` : `<style>
115
122
  display: none;
116
123
  }
117
124
 
125
+ .pay-button:disabled, pay-button[disabled] {
126
+ background-color: #B9B9B9;
127
+ }
128
+
118
129
  .lds-dual-ring {
119
130
  display: inline-block;
120
131
  width: 14px;
@@ -131,6 +142,7 @@ ${external ? `` : `<style>
131
142
  border-color: #fff transparent #fff transparent;
132
143
  animation: lds-dual-ring 1.2s linear infinite;
133
144
  }
145
+
134
146
  @keyframes lds-dual-ring {
135
147
  0% {
136
148
  transform: rotate(0deg);
@@ -163,12 +175,7 @@ ${external ? `` : `<style>
163
175
  font-size: '12px';
164
176
  font-weight: '500';
165
177
  color: #1D1D1D;
166
- font-family: "Inter", sans-serif;
167
- }
168
-
169
- @font-face {
170
- font-family: Inter;
171
- src: url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;700&display=swap");
178
+ font-family: "Inter", sans-serif !important;
172
179
  }
173
180
 
174
181
  .checkbox {
@@ -192,7 +199,8 @@ ${external ? `` : `<style>
192
199
  }
193
200
 
194
201
  .pay-new-card .card-number {
195
- font-size: 14px;
202
+ font-size: 16px;
203
+ font-family: "Inter", sans-serif !important;
196
204
  }
197
205
 
198
206
  .card-image {
@@ -221,6 +229,8 @@ export const cardItemsTemplate = (external: boolean, cards: Card[]) => {
221
229
  const cardItemStyle = external ? '' : `
222
230
  <style>
223
231
 
232
+ @import url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;700&display=swap");
233
+
224
234
  .card-item-label {
225
235
  display: flex;
226
236
  justify-content: start;
@@ -246,11 +256,13 @@ export const cardItemsTemplate = (external: boolean, cards: Card[]) => {
246
256
  }
247
257
 
248
258
  .card-item .card-number {
249
- font-size: 14px;
259
+ font-size: 16px;
260
+ font-family: "Inter", sans-serif !important;
250
261
  }
251
262
 
252
263
  .card-item .card-expiration {
253
- font-size: 14px;
264
+ font-size: 16px;
265
+ font-family: "Inter", sans-serif !important;
254
266
  }
255
267
 
256
268
  .card-image {