tonder-web-sdk 1.12.0-beta.15 → 1.12.0-beta.16

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.
@@ -13,6 +13,8 @@
13
13
  <change beforePath="$PROJECT_DIR$/src/classes/BaseInlineCheckout.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/classes/BaseInlineCheckout.js" afterDir="false" />
14
14
  <change beforePath="$PROJECT_DIR$/src/classes/LiteInlineCheckout.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/classes/LiteInlineCheckout.js" afterDir="false" />
15
15
  <change beforePath="$PROJECT_DIR$/src/helpers/utils.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/helpers/utils.js" afterDir="false" />
16
+ <change beforePath="$PROJECT_DIR$/src/index-dev.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/index-dev.js" afterDir="false" />
17
+ <change beforePath="$PROJECT_DIR$/src/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/src/index.html" afterDir="false" />
16
18
  <change beforePath="$PROJECT_DIR$/src/index.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/index.js" afterDir="false" />
17
19
  <change beforePath="$PROJECT_DIR$/types/card.d.ts" beforeDir="false" afterPath="$PROJECT_DIR$/types/card.d.ts" afterDir="false" />
18
20
  <change beforePath="$PROJECT_DIR$/types/index.d.ts" beforeDir="false" afterPath="$PROJECT_DIR$/types/index.d.ts" afterDir="false" />
@@ -103,7 +105,7 @@
103
105
  <workItem from="1723855727317" duration="20341000" />
104
106
  <workItem from="1723952592527" duration="17418000" />
105
107
  <workItem from="1724247675743" duration="41003000" />
106
- <workItem from="1724435697518" duration="2056000" />
108
+ <workItem from="1724435697518" duration="6417000" />
107
109
  </task>
108
110
  <servers />
109
111
  </component>
package/README.md CHANGED
@@ -637,17 +637,31 @@ import { InlineCheckout } from 'tonder-web-sdk';
637
637
  export class TonderService {
638
638
  private inlineCheckout: InlineCheckout;
639
639
 
640
- constructor() {
641
- this.inlineCheckout = new InlineCheckout({
642
- apiKey: 'your-api-key',
643
- returnUrl: 'http://your-website.com/checkout',
644
- mode: 'development'
645
- });
646
- }
640
+ constructor(private sdkParameters: IInlineCheckoutOptions) {
641
+ this.initializeInlineCheckout();
642
+ }
647
643
 
648
- getInlineCheckout(): InlineCheckout {
649
- return this.inlineCheckout;
650
- }
644
+ private initializeInlineCheckout(): void {
645
+ this.inlineCheckout = new InlineCheckout({ ...this.sdkParameters });
646
+ }
647
+
648
+ configureCheckout(customerData: IConfigureCheckout): void {
649
+ this.inlineCheckout.configureCheckout({ ...customerData });
650
+ }
651
+
652
+ async injectCheckout(): Promise<void> {
653
+ await this.inlineCheckout.injectCheckout();
654
+ }
655
+
656
+ verify3dsTransaction(): Promise<ITransaction | void> {
657
+ return this.inlineCheckout.verify3dsTransaction();
658
+ }
659
+
660
+ // Add more functions, for example for lite sdk: get payment methods
661
+
662
+ // getCustomerPaymentMethods(): Promise<IPaymentMethod[]> {
663
+ // return this.liteCheckout.getCustomerPaymentMethods();
664
+ // }
651
665
  }
652
666
 
653
667
  // checkout.component.ts
@@ -661,7 +675,21 @@ import { TonderService } from './tonder.service';
661
675
  <button (click)="pay()" [disabled]="loading">
662
676
  {{ loading ? 'Processing...' : 'Pay' }}
663
677
  </button>
664
- `
678
+ `,
679
+ providers: [
680
+ {
681
+ provide: TonderInlineService,
682
+ // Inicialización del SDK de Tonder Inline
683
+ // Nota: Reemplace estas credenciales con las suyas propias en desarrollo/producción
684
+ useFactory: () =>
685
+ new TonderInlineService({
686
+ apiKey: "11e3d3c3e95e0eaabbcae61ebad34ee5f93c3d27",
687
+ returnUrl:
688
+ "http://localhost:4200/checkout/payment?tabPayment=0",
689
+ mode: "development",
690
+ }),
691
+ },
692
+ ],
665
693
  })
666
694
  export class TonderCheckoutComponent implements OnInit, OnDestroy {
667
695
  loading = false;
@@ -669,26 +697,26 @@ export class TonderCheckoutComponent implements OnInit, OnDestroy {
669
697
  constructor(private tonderService: TonderService) {}
670
698
 
671
699
  ngOnInit() {
672
- const tonder = this.tonderService.getInlineCheckout();
673
- tonder.configureCheckout({ customer: { email: 'example@email.com' } });
674
- tonder.injectCheckout();
675
- tonder.verify3dsTransaction().then(response => {
676
- console.log('Verify 3ds response', response);
677
- });
700
+ this.initCheckout()
678
701
  }
679
702
 
680
703
  ngOnDestroy() {
681
- const tonder = this.tonderService.getInlineCheckout();
682
- if (tonder.removeCheckout) {
683
- tonder.removeCheckout();
684
- }
704
+ // Limpieza del checkout al destruir el componente
705
+ this.tonderService.removeCheckout();
706
+ }
707
+
708
+ async initCheckout() {
709
+ this.tonderService.configureCheckout({ customer: { email: 'example@email.com' } });
710
+ await this.tonderService.injectCheckout();
711
+ this.tonderService.verify3dsTransaction().then(response => {
712
+ console.log('Verify 3ds response', response);
713
+ });
685
714
  }
686
715
 
687
716
  async pay() {
688
717
  this.loading = true;
689
718
  try {
690
- const tonder = this.tonderService.getInlineCheckout();
691
- const response = await tonder.payment(paymentData);
719
+ const response = await this.tonderService.payment(paymentData);
692
720
  console.log('Payment successful:', response);
693
721
  alert('Payment successful');
694
722
  } catch (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tonder-web-sdk",
3
- "version": "1.12.0-beta.15",
3
+ "version": "1.12.0-beta.16",
4
4
  "description": "tonder sdk for integrations",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -17,6 +17,7 @@
17
17
  "devDependencies": {
18
18
  "@babel/core": "^7.20.12",
19
19
  "@babel/preset-env": "^7.20.2",
20
+ "@maskito/core": "^3.0.1",
20
21
  "babel-loader": "^9.1.2",
21
22
  "css-loader": "^6.7.3",
22
23
  "cypress": "^13.6.2",
package/src/index-dev.js CHANGED
@@ -1,5 +1,7 @@
1
- import { InlineCheckout } from './classes/inlineCheckout'
2
- import {LiteInlineCheckout} from "./classes/LiteInlineCheckout";
1
+ import { InlineCheckout } from "./classes/inlineCheckout";
2
+ import { LiteInlineCheckout } from "./classes/LiteInlineCheckout";
3
+ import { Maskito } from '@maskito/core';
4
+ import {validateCardNumber} from "./helpers/validations";
3
5
 
4
6
  const customStyles = {
5
7
  inputStyles: {
@@ -10,15 +12,15 @@ const customStyles = {
10
12
  color: "#333333",
11
13
  backgroundColor: "#f0f0f0",
12
14
  fontFamily: '"Arial", sans-serif',
13
- fontSize: '14px',
14
- '&::placeholder': {
15
+ fontSize: "14px",
16
+ "&::placeholder": {
15
17
  color: "#888888",
16
18
  },
17
19
  },
18
20
  cardIcon: {
19
- position: 'absolute',
20
- left: '6px',
21
- bottom: 'calc(50% - 12px)',
21
+ position: "absolute",
22
+ left: "6px",
23
+ bottom: "calc(50% - 12px)",
22
24
  },
23
25
  complete: {
24
26
  color: "#4caf50",
@@ -29,39 +31,40 @@ const customStyles = {
29
31
  border: "1px solid #f44336",
30
32
  },
31
33
  global: {
32
- '@import': 'url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;700&display=swap")',
33
- }
34
+ "@import":
35
+ 'url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;700&display=swap")',
36
+ },
34
37
  },
35
38
  labelStyles: {
36
39
  base: {
37
- fontSize: '14px',
38
- fontWeight: 'bold',
40
+ fontSize: "14px",
41
+ fontWeight: "bold",
39
42
  fontFamily: '"Inter", sans-serif',
40
43
  color: "#4a90e2",
41
44
  },
42
45
  },
43
46
  errorTextStyles: {
44
47
  base: {
45
- fontSize: '12px',
46
- fontWeight: '500',
48
+ fontSize: "12px",
49
+ fontWeight: "500",
47
50
  color: "#e74c3c",
48
51
  fontFamily: '"Inter", sans-serif',
49
52
  },
50
53
  },
51
54
  labels: {
52
- nameLabel: 'Nombre de la de Tarjeta',
53
- cardLabel: 'Número de Tarjeta',
54
- cvvLabel: 'Código de Seguridad',
55
- expiryDateLabel: 'Fecha de Expiración',
55
+ nameLabel: "Nombre de la de Tarjeta",
56
+ cardLabel: "Número de Tarjeta",
57
+ cvvLabel: "Código de Seguridad",
58
+ expiryDateLabel: "Fecha de Expiración",
56
59
  },
57
60
  placeholders: {
58
- namePlaceholder: 'Nombre como aparece en la tarjeta',
59
- cardPlaceholder: '0000 0000 0000 0000',
60
- cvvPlaceholder: '123',
61
- expiryMonthPlaceholder: 'Mes',
62
- expiryYearPlaceholder: 'Año'
63
- }
64
- }
61
+ namePlaceholder: "Nombre como aparece en la tarjeta",
62
+ cardPlaceholder: "0000 0000 0000 0000",
63
+ cvvPlaceholder: "123",
64
+ expiryMonthPlaceholder: "Mes",
65
+ expiryYearPlaceholder: "Año",
66
+ },
67
+ };
65
68
 
66
69
  const checkoutData = {
67
70
  customer: {
@@ -75,7 +78,7 @@ const checkoutData = {
75
78
  email: "adrian@email.com",
76
79
  phone: "8161234567",
77
80
  },
78
- currency: 'mxn',
81
+ currency: "mxn",
79
82
  cart: {
80
83
  total: 399,
81
84
  items: [
@@ -89,7 +92,7 @@ const checkoutData = {
89
92
  name: "T-Shirt",
90
93
  amount_total: 399,
91
94
  },
92
- ]
95
+ ],
93
96
  },
94
97
  // card: { "skyflow_id": "53ca875c-16fd-4395-8ac9-c756613dbaf9" },
95
98
  // metadata: {
@@ -97,122 +100,194 @@ const checkoutData = {
97
100
  // }
98
101
  };
99
102
 
100
-
101
-
102
103
  // localhost
103
104
  const apiKey = "11e3d3c3e95e0eaabbcae61ebad34ee5f93c3d27";
104
- const returnUrl = "http://127.0.0.1:8080/"
105
+ const returnUrl = "http://127.0.0.1:8080/";
105
106
  // stage
106
107
  // const apiKey = "8365683bdc33dd6d50fe2397188d79f1a6765852";
107
108
 
108
-
109
109
  const commonConfig = {
110
- mode: 'development',
110
+ mode: "development",
111
111
  apiKey,
112
- returnUrl: returnUrl+"?mode="+getCheckoutMode(),
113
- styles: customStyles
112
+ returnUrl: returnUrl + "?mode=" + getCheckoutMode(),
113
+ styles: customStyles,
114
114
  };
115
115
 
116
116
  let checkout;
117
117
  let inlineCheckout;
118
118
  let liteInlineCheckout;
119
119
 
120
-
121
120
  function getCheckoutMode() {
122
121
  const urlParams = new URLSearchParams(window.location.search);
123
- return urlParams.get('mode') || 'inline';
122
+ return urlParams.get("mode") || "inline";
124
123
  }
125
124
 
126
125
  function setupInlineCheckout() {
127
- inlineCheckout = new InlineCheckout({...commonConfig});
128
- inlineCheckout.configureCheckout({customer: checkoutData.customer})
126
+ inlineCheckout = new InlineCheckout({ ...commonConfig });
127
+ inlineCheckout.configureCheckout({ customer: checkoutData.customer });
129
128
  inlineCheckout.injectCheckout();
130
129
  // ['Declined', 'Cancelled', 'Failed', 'Success', 'Pending', 'Authorized']
131
- inlineCheckout.verify3dsTransaction().then(response => {
132
- console.log('Verify 3ds response', response)
133
- })
130
+ inlineCheckout.verify3dsTransaction().then((response) => {
131
+ console.log("Verify 3ds response", response);
132
+ });
134
133
 
135
- const payButton = document.getElementById('pay-button');
136
- payButton.addEventListener('click', async function () {
134
+ const payButton = document.getElementById("pay-button");
135
+ payButton.addEventListener("click", async function () {
137
136
  try {
138
- payButton.textContent = 'Procesando...';
137
+ payButton.textContent = "Procesando...";
139
138
  const response = await inlineCheckout.payment(checkoutData);
140
- console.log("Respuesta del pago:", response)
141
- alert('Pago realizado con éxito');
139
+ console.log("Respuesta del pago:", response);
140
+ alert("Pago realizado con éxito");
142
141
  } catch (error) {
143
142
  console.log("Error en el pago:", error.details);
144
- alert('Error al realizar el pago')
143
+ alert("Error al realizar el pago");
145
144
  } finally {
146
- payButton.textContent = 'Pagar';
145
+ payButton.textContent = "Pagar";
147
146
  }
148
147
  });
149
148
  }
150
149
 
151
150
  function setupLiteInlineCheckout() {
152
- liteInlineCheckout = new LiteInlineCheckout(commonConfig);
153
- liteInlineCheckout.configureCheckout({customer: checkoutData.customer})
154
- liteInlineCheckout.injectCheckout().then(() => {});
155
- liteInlineCheckout.verify3dsTransaction().then(response => {
156
- console.log('Verify 3ds response', response)
157
- })
158
-
159
- const liteForm = document.getElementById('lite-payment-form');
160
- liteForm.addEventListener('submit', async function(event) {
151
+ loadMaskitoMask();
152
+ liteInlineCheckout = new LiteInlineCheckout(commonConfig);
153
+ liteInlineCheckout.configureCheckout({ customer: checkoutData.customer });
154
+ liteInlineCheckout.injectCheckout().then(() => {});
155
+ liteInlineCheckout.verify3dsTransaction().then((response) => {
156
+ console.log("Verify 3ds response", response);
157
+ });
158
+
159
+ const liteForm = document.getElementById("lite-payment-form");
160
+ liteForm.addEventListener("submit", async function (event) {
161
161
  event.preventDefault();
162
162
 
163
163
  const cardData = {
164
- card_number: document.getElementById('card-number').value,
165
- cardholder_name: document.getElementById('card-name').value,
166
- expiration_month: document.getElementById('month').value,
167
- expiration_year: document.getElementById('year').value,
168
- cvv: document.getElementById('cvv').value
164
+ card_number: document.getElementById("card-number").value,
165
+ cardholder_name: document.getElementById("card-name").value,
166
+ expiration_month: document.getElementById("month").value,
167
+ expiration_year: document.getElementById("year").value,
168
+ cvv: document.getElementById("cvv").value,
169
169
  };
170
170
 
171
171
  try {
172
172
  const paymentData = {
173
173
  ...checkoutData,
174
- card: cardData
174
+ card: cardData,
175
175
  };
176
176
  const response = await liteInlineCheckout.payment(paymentData);
177
177
  console.log("Respuesta del pago:", response);
178
- alert('Pago realizado con éxito');
178
+ alert("Pago realizado con éxito");
179
179
  } catch (error) {
180
180
  console.error("Error en el pago:", error);
181
- alert('Error al realizar el pago');
181
+ alert("Error al realizar el pago");
182
182
  }
183
183
  });
184
184
  }
185
185
 
186
186
  function setupCheckout() {
187
187
  const mode = getCheckoutMode();
188
- document.querySelectorAll('.tab-content').forEach(content => {
189
- content.style.display = 'none';
188
+ document.querySelectorAll(".tab-content").forEach((content) => {
189
+ content.style.display = "none";
190
190
  });
191
191
 
192
- if (mode === 'inline') {
193
- document.getElementById('inline-content').style.display = 'block';
194
- setupInlineCheckout()
195
- }else{
196
- document.getElementById('lite-content').style.display = 'block';
197
- setupLiteInlineCheckout()
192
+ if (mode === "inline") {
193
+ document.getElementById("inline-content").style.display = "block";
194
+ setupInlineCheckout();
195
+ } else {
196
+ document.getElementById("lite-content").style.display = "block";
197
+ setupLiteInlineCheckout();
198
198
  }
199
199
  }
200
200
 
201
+
202
+ function loadMaskitoMask(){
203
+ const cardNumberInput = document.getElementById('card-number');
204
+ const monthInput = document.getElementById('month');
205
+ const yearInput = document.getElementById('year');
206
+ const cvvInput = document.getElementById('cvv');
207
+ const nameInput = document.getElementById('card-name');
208
+
209
+ // Definir las opciones para las máscaras
210
+ const cardNumberOptions = {
211
+ mask: [
212
+ ...Array(4).fill(/\d/),
213
+ " ",
214
+ ...Array(4).fill(/\d/),
215
+ " ",
216
+ ...Array(4).fill(/\d/),
217
+ " ",
218
+ ...Array(4).fill(/\d/),
219
+ " ",
220
+ ...Array(3).fill(/\d/),
221
+ ]
222
+ };
223
+
224
+ const monthOptions = {
225
+ mask: [/[0-1]/, /\d/],
226
+ };
227
+
228
+ const yearOptions = {
229
+ mask: [/\d/, /\d/]
230
+ };
231
+
232
+ const nameOptions = {
233
+ mask: /^[a-zA-Z\s]*$/,
234
+ };
235
+
236
+ const cvvOptions = {
237
+ mask: [
238
+ ...Array(4).fill(/\d/),
239
+ " ",
240
+ ...Array(4).fill(/\d/),
241
+ " ",
242
+ ...Array(4).fill(/\d/),
243
+ " ",
244
+ ...Array(4).fill(/\d/),
245
+ " ",
246
+ ...Array(3).fill(/\d/),
247
+ ],
248
+ };
249
+
250
+ // Aplicar Maskito a cada campo
251
+ const cardNumberMask = new Maskito(cardNumberInput, cardNumberOptions);
252
+ const monthMask = new Maskito(monthInput, monthOptions);
253
+ const yearMask = new Maskito(yearInput, yearOptions);
254
+ const cvvMask = new Maskito(cvvInput, cvvOptions);
255
+ const nameMask = new Maskito(nameInput, nameOptions);
256
+
257
+ cardNumberInput.addEventListener('input', () => {
258
+ const cardNumber = cardNumberInput.value.replace(/\s+/g, '');
259
+ if (!validateCardNumber(cardNumber)) {
260
+ cardNumberInput.setCustomValidity("Número de tarjeta inválido");
261
+ cardNumberInput.classList.add("invalid");
262
+ } else {
263
+ cardNumberInput.setCustomValidity("");
264
+ cardNumberInput.classList.remove("invalid");
265
+ }
266
+ });
267
+
268
+ window.addEventListener('beforeunload', () => {
269
+ cardNumberMask.destroy();
270
+ monthMask.destroy();
271
+ yearMask.destroy();
272
+ cvvMask.destroy();
273
+ nameMask.destroy();
274
+ });
275
+ }
201
276
  function updateActiveTab() {
202
277
  const mode = getCheckoutMode();
203
- document.querySelectorAll('.tab').forEach(tab => {
204
- tab.classList.remove('active');
278
+ document.querySelectorAll(".tab").forEach((tab) => {
279
+ tab.classList.remove("active");
205
280
  });
206
- document.querySelector(`[data-mode="${mode}"]`).classList.add('active');
281
+ document.querySelector(`[data-mode="${mode}"]`).classList.add("active");
207
282
  }
208
283
 
209
284
  function switchTab(mode) {
210
285
  window.location.href = `${window.location.pathname}?mode=${mode}`;
211
286
  }
212
287
 
213
- document.addEventListener('DOMContentLoaded', function() {
288
+ document.addEventListener("DOMContentLoaded", function () {
214
289
  setupCheckout();
215
290
  updateActiveTab();
216
291
  });
217
292
 
218
- window.switchTab = switchTab;
293
+ window.switchTab = switchTab;
package/src/index.html CHANGED
@@ -109,6 +109,9 @@
109
109
  .input-md {
110
110
  max-width: 100%;
111
111
  }
112
+ .invalid{
113
+ border: 2px solid red !important;
114
+ }
112
115
  </style>
113
116
  </head>
114
117
 
package/webpack.config.js CHANGED
@@ -14,6 +14,14 @@ module.exports = (env, argv) => {
14
14
  resourceRegExp: /samples\//
15
15
  }),
16
16
  ];
17
+
18
+ if (isProduction) {
19
+ plugins.push(
20
+ new webpack.IgnorePlugin({
21
+ resourceRegExp: /^@maskito\/core$/,
22
+ })
23
+ );
24
+ }
17
25
  if (!isProduction) {
18
26
  plugins.push(new HtmlWebpackPlugin({
19
27
  template: 'src/index.html'