tonder-web-sdk 1.12.0-beta.9 → 1.12.3

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
@@ -2,19 +2,40 @@
2
2
 
3
3
  Tonder SDK helps to integrate the services Tonder offers in your own website
4
4
 
5
+ ## Table of Contents
6
+
7
+ 1. [Installation](#installation)
8
+ 2. [Usage](#usage)
9
+ - [InlineCheckout](#inlinecheckout)
10
+ - [LiteCheckout](#litecheckout)
11
+ 3. [Configuration Options](#configuration-options)
12
+ 4. [Styling InlineCheckout](#styling-inlinecheckout)
13
+ 5. [Payment Data Structure](#payment-data-structure)
14
+ 6. [Field Validation Functions](#field-validation-functions)
15
+ 7. [API Reference](#api-reference)
16
+ 8. [Examples](#examples)
17
+ 9. [License](#license)
18
+
5
19
  ## Installation
6
20
 
7
- You can install using NPM
21
+ You can install the Tonder SDK using NPM or by including it via a script tag.
22
+
23
+ ### NPM Installation
24
+
8
25
  ```bash
9
26
  npm i tonder-web-sdk
10
27
  ```
11
28
 
12
- or using an script tag
29
+ ### Script Tag Installation
30
+
13
31
  ```html
14
32
  <script src="https://zplit-prod.s3.amazonaws.com/v1/bundle.min.js"></script>
15
33
  ```
16
34
 
35
+ ### Dependencies
36
+
17
37
  Add dependencies to the root of the app (index.html)
38
+
18
39
  ```html
19
40
  <script src="https://js.skyflow.com/v1/index.js"></script>
20
41
  <script src="https://openpay.s3.amazonaws.com/openpay.v1.min.js"></script>
@@ -22,20 +43,129 @@ Add dependencies to the root of the app (index.html)
22
43
  ```
23
44
 
24
45
  ## Usage
25
- HTML
46
+
47
+ ### InlineCheckout
48
+
49
+ InlineCheckout provides a pre-built, customizable checkout interface.
50
+
51
+ #### HTML Setup
52
+
53
+ You need to have an element where the inline checkout will be mounted. This should be a DIV element with the ID "tonder-checkout":
54
+
26
55
  ```html
27
56
  <div>
28
- <h1>Checkout</h1>
29
- <!-- You have to add an entry point with the ID 'tonder-checkout' -->
30
- <div id="tonder-checkout">
31
- </div>
57
+ <h1>Checkout</h1>
58
+ <div id="tonder-checkout"></div>
32
59
  </div>
33
60
  ```
34
- ## Javascript Example
61
+
62
+ #### JavaScript Implementation
63
+
64
+ ```javascript
65
+ import { InlineCheckout } from "tonder-web-sdk"; // Not required if using script tag
66
+ ```
67
+
68
+ ```javascript
69
+ // if using script tag, it should be initialized like this
70
+ // new TonderSdk.InlineCheckout
71
+ const inlineCheckout = new InlineCheckout({
72
+ apiKey: "your-api-key",
73
+ returnUrl: "https://your-website.com/checkout",
74
+ styles: customStyles, // Optional, see Styling section
75
+ });
76
+
77
+ // The configureCheckout function allows you to set initial information,
78
+ // such as the customer's email, which is used to retrieve a list of saved cards.
79
+ inlineCheckout.configureCheckout({ customer: { email: "example@email.com" } });
80
+
81
+ // Inject the checkout into the DOM
82
+ inlineCheckout.injectCheckout();
83
+
84
+ // To verify a 3ds transaction you can use the following method
85
+ // It should be called after the injectCheckout method
86
+ // The response status will be one of the following
87
+ // ['Declined', 'Cancelled', 'Failed', 'Success', 'Pending', 'Authorized']
88
+
89
+ inlineCheckout.verify3dsTransaction().then((response) => {
90
+ console.log("Verify 3ds response", response);
91
+ });
92
+ ```
93
+
94
+ ```javascript
95
+ // Process a payment
96
+ const response = await inlineCheckout.payment(checkoutData);
97
+ ```
98
+
99
+ ### LiteCheckout
100
+
101
+ LiteCheckout allows you to build a custom checkout interface using Tonder's core functionality.
102
+
103
+ ```javascript
104
+ import { LiteCheckout } from "tonder-web-sdk";
105
+ ```
106
+
107
+ ```javascript
108
+ const liteCheckout = new LiteCheckout({
109
+ apiKey: "your-api-key", // Your api key getted from Tonder Dashboard
110
+ returnUrl: "http://your-website.com/checkout",
111
+ });
112
+
113
+ // The configureCheckout function allows you to set initial information,
114
+ // such as the customer's email, which is used to retrieve a list of saved cards.
115
+ inlineCheckout.configureCheckout({ customer: { email: "example@email.com" } });
116
+
117
+ // Initialize the checkout
118
+ await liteCheckout.injectCheckout();
119
+ ```
120
+
35
121
  ```javascript
36
- import { InlineCheckout } from "tonder-web-sdk" // Not required if using script tag
122
+ // Retrieve customer's saved cards
123
+ const cards = await liteCheckout.getCustomerCards();
37
124
  ```
38
125
 
126
+ ```javascript
127
+ // Save a new card
128
+ const newCard = await liteCheckout.saveCustomerCard(cardData);
129
+ ```
130
+
131
+ ```javascript
132
+ // Remove a saved card
133
+ await liteCheckout.removeCustomerCard(cardId);
134
+ ```
135
+
136
+ ```javascript
137
+ // Get available payment methods
138
+ const paymentMethods = await liteCheckout.getCustomerPaymentMethods();
139
+ ```
140
+
141
+ ```javascript
142
+ // Process a payment
143
+ const paymentResponse = await liteCheckout.payment(paymentData);
144
+ ```
145
+
146
+ ```javascript
147
+ // Verify a 3DS transaction
148
+ const verificationResult = await liteCheckout.verify3dsTransaction();
149
+ ```
150
+
151
+ ## Configuration Options
152
+
153
+ Both InlineCheckout and LiteCheckout accept the following configuration options:
154
+
155
+ | Property | Type | Description |
156
+ | :----------------------------------------: | :-----: | :-----------------------------------------------------------------------------------------------------------------------------------------: |
157
+ | mode | string | Environment mode. Options: 'stage', 'production', 'sandbox'. Default: 'stage' |
158
+ | apiKey | string | Your API key from the Tonder Dashboard |
159
+ | returnUrl | string | URL where the checkout form is mounted (used for 3DS) |
160
+ | styles | object | (InlineCheckout only) Custom styles for the checkout interface |
161
+ | customization | object | Object to customize the checkout behavior and UI. Default value `{saveCards: {showSaved: true, showSaveCardOption: true, autoSave: false}}` |
162
+ | customization.saveCards.showSaved | boolean | Show saved cards in the checkout UI. Default value: `true` |
163
+ | customization.saveCards.showSaveCardOption | object | Show the option to save the card for future payments. Default value: `true` |
164
+ | customization.saveCards.autoSave | object | Automatically save the card without showing the option to the user. Default value: `false` |
165
+
166
+ ## Styling InlineCheckout
167
+
168
+ You can customize the appearance of InlineCheckout by passing a `styles` object:
39
169
 
40
170
  ```javascript
41
171
  const customStyles = {
@@ -48,15 +178,15 @@ const customStyles = {
48
178
  marginTop: "2px",
49
179
  backgroundColor: "white",
50
180
  fontFamily: '"Inter", sans-serif',
51
- fontSize: '16px',
52
- '&::placeholder': {
181
+ fontSize: "16px",
182
+ "&::placeholder": {
53
183
  color: "#ccc",
54
184
  },
55
185
  },
56
186
  cardIcon: {
57
- position: 'absolute',
58
- left: '6px',
59
- bottom: 'calc(50% - 12px)',
187
+ position: "absolute",
188
+ left: "6px",
189
+ bottom: "calc(50% - 12px)",
60
190
  },
61
191
  complete: {
62
192
  color: "#4caf50",
@@ -67,151 +197,579 @@ const customStyles = {
67
197
  border: "1px solid #f44336",
68
198
  },
69
199
  global: {
70
- '@import': 'url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;700&display=swap")',
71
- }
200
+ "@import":
201
+ 'url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;700&display=swap")',
202
+ },
72
203
  },
73
204
  labelStyles: {
74
205
  base: {
75
- fontSize: '12px',
76
- fontWeight: '500',
77
- fontFamily: '"Inter", sans-serif'
206
+ fontSize: "12px",
207
+ fontWeight: "500",
208
+ fontFamily: '"Inter", sans-serif',
78
209
  },
79
210
  },
80
211
  errorTextStyles: {
81
212
  base: {
82
- fontSize: '12px',
83
- fontWeight: '500',
213
+ fontSize: "12px",
214
+ fontWeight: "500",
84
215
  color: "#f44336",
85
- fontFamily: '"Inter", sans-serif'
216
+ fontFamily: '"Inter", sans-serif',
86
217
  },
87
218
  },
88
219
  labels: {
89
- nameLabel: 'Titular de la tarjeta',
90
- cardLabel: 'Número de tarjeta',
91
- cvvLabel: 'CVC/CVV',
92
- expiryDateLabel: 'Fecha de expiración',
220
+ nameLabel: "Card Holder Name",
221
+ cardLabel: "Card Number",
222
+ cvvLabel: "CVC/CVV",
223
+ expiryDateLabel: "Expiration Date",
93
224
  },
94
225
  placeholders: {
95
- namePlaceholder: 'Nombre como aparece en la tarjeta',
96
- cardPlaceholder: '1234 1234 1234 1234',
97
- cvvPlaceholder: '3-4 dígitos',
98
- expiryMonthPlaceholder: 'MM',
99
- expiryYearPlaceholder: 'AA'
100
- }
101
- }
226
+ namePlaceholder: "Name as it appears on the card",
227
+ cardPlaceholder: "1234 1234 1234 1234",
228
+ cvvPlaceholder: "3-4 digits",
229
+ expiryMonthPlaceholder: "MM",
230
+ expiryYearPlaceholder: "YY",
231
+ },
232
+ };
233
+ ```
234
+
235
+ ## Payment Data Structure
236
+
237
+ When calling the `payment` method, use the following data structure:
238
+
239
+ ### Field Descriptions
240
+
241
+ - **customer**: Object containing the customer's personal information to be registered in the transaction.
102
242
 
103
- const checkoutData = {
243
+ - **cart**: Object containing the total amount and an array of items to be registered in the Tonder order.
244
+
245
+ - **total**: The total amount of the transaction.
246
+ - **items**: An array of objects, each representing a product or service in the order.
247
+ - name: name of the product
248
+ - price_unit: valid float string with the price of the product
249
+ - quantity: valid integer string with the quantity of this product
250
+
251
+ - **currency**: String representing the currency code for the transaction (e.g., "MXN" for Mexican Peso).
252
+
253
+ - **metadata**: Object for including any additional information about the transaction. This can be used for internal references or tracking.
254
+
255
+ - **card**: (for LiteCheckout) Object containing card information. This is used differently depending on whether it's a new card or a saved card:
256
+
257
+ - For a new card: Include `card_number`, `cvv`, `expiration_month`, `expiration_year`, and `cardholder_name`.
258
+ - For a saved card: Include only the `skyflow_id` of the saved card.
259
+ - This is only used when not paying with a payment_method.
260
+
261
+ - **payment_method**: (for LiteCheckout) String indicating the alternative payment method to be used (e.g., "Spei"). This is only used when not paying with a card.
262
+
263
+ Note: The exact fields required may vary depending on whether you're using InlineCheckout or LiteCheckout, and the specific payment method being used.
264
+
265
+ ```javascript
266
+ const paymentData = {
104
267
  customer: {
105
- firstName: "Juan",
106
- lastName: "Hernández",
107
- country: "Mexico",
108
- address: "Av. Revolución 356, Col. Roma",
109
- city: "Monterrey",
110
- state: "Nuevo León",
111
- postCode: "64700",
112
- email: "juan.hernandez@mail.com",
113
- phone: "8187654321",
268
+ firstName: "John",
269
+ lastName: "Doe",
270
+ country: "USA",
271
+ address: "123 Main St",
272
+ city: "Anytown",
273
+ state: "CA",
274
+ postCode: "12345",
275
+ email: "john.doe@example.com",
276
+ phone: "1234567890",
114
277
  },
115
- currency: 'mxn',
116
278
  cart: {
117
- total: 399,
279
+ total: "100.00",
118
280
  items: [
119
281
  {
120
- description: "Black T-Shirt",
282
+ description: "Product description",
121
283
  quantity: 1,
122
- price_unit: 1,
123
- discount: 0,
124
- taxes: 0,
125
- product_reference: 1,
126
- name: "T-Shirt",
127
- amount_total: 399,
284
+ price_unit: "100.00",
285
+ discount: "0.00",
286
+ taxes: "0.00",
287
+ product_reference: "PROD123",
288
+ name: "Product Name",
289
+ amount_total: "100.00",
128
290
  },
129
- ]
291
+ ],
130
292
  },
293
+ currency: "MXN",
131
294
  metadata: {
132
- order_id: 123456
295
+ order_id: "ORDER123",
133
296
  },
297
+ // For Lite checkout
134
298
  card: {
135
- skyflow_id: "12340120349123049",
136
- }
299
+ // For a new card:
300
+ card_number: "4111111111111111",
301
+ cvv: "123",
302
+ expiration_month: "12",
303
+ expiration_year: "25",
304
+ cardholder_name: "John Doe",
305
+ // Or for a saved card:
306
+ skyflow_id: "saved-card-id",
307
+ },
308
+ // For Lite checkout
309
+ payment_method: "Spei",
137
310
  };
311
+ ```
138
312
 
139
- const apiKey = "4c87c36e697e65ddfe288be0afbe7967ea0ab865";
140
- const returnUrl = "http://my-website:8080/checkout"
313
+ ## Field Validation Functions
314
+
315
+ For LiteCheckout implementations, the SDK provides validation functions to ensure the integrity of card data before submitting:
316
+
317
+ - `validateCardNumber(cardNumber)`: Validates the card number using the Luhn algorithm.
318
+ - `validateCardholderName(name)`: Checks if the cardholder name is valid.
319
+ - `validateCVV(cvv)`: Ensures the CVV is in the correct format.
320
+ - `validateExpirationDate(expirationDate)`: Validates the expiration date in MM/YY format.
321
+ - `validateExpirationMonth(month)`: Checks if the expiration month is valid.
322
+ - `validateExpirationYear(year)`: Validates the expiration year.
323
+
324
+ Example usage:
325
+
326
+ ```javascript
327
+ import {
328
+ validateCardNumber,
329
+ validateCardholderName,
330
+ validateCVV,
331
+ validateExpirationDate,
332
+ } from "tonder-web-sdk";
333
+
334
+ const cardNumber = "4111111111111111";
335
+ const cardholderName = "John Doe";
336
+ const cvv = "123";
337
+ const expirationDate = "12/25";
338
+
339
+ if (
340
+ validateCardNumber(cardNumber) &&
341
+ validateCardholderName(cardholderName) &&
342
+ validateCVV(cvv) &&
343
+ validateExpirationDate(expirationDate)
344
+ ) {
345
+ // Proceed with payment
346
+ } else {
347
+ // Show error message
348
+ }
349
+ ```
350
+
351
+ ## API Reference
352
+
353
+ ### InlineCheckout Methods
354
+
355
+ - `configureCheckout(data)`: Set initial checkout data
356
+ - `injectCheckout()`: Inject the checkout interface into the DOM
357
+ - `payment(data)`: Process a payment
358
+ - `verify3dsTransaction()`: Verify a 3DS transaction
359
+
360
+ ### LiteCheckout Methods
361
+
362
+ - `configureCheckout(data)`: Set initial checkout data
363
+ - `injectCheckout()`: Initialize the checkout
364
+ - `getCustomerCards()`: Retrieve saved cards
365
+ - `saveCustomerCard(cardData)`: Save a new card
366
+ - `removeCustomerCard(cardId)`: Remove a saved card
367
+ - `getCustomerPaymentMethods()`: Get available payment methods
368
+ - `payment(data)`: Process a payment
369
+ - `verify3dsTransaction()`: Verify a 3DS transaction
370
+
371
+ ## Examples
372
+
373
+ Here are examples of how to implement Tonder SDK in various JavaScript frameworks:
374
+
375
+ ### Vanilla JavaScript
376
+
377
+ #### HTML Setup
378
+
379
+ ```html
380
+ <!doctype html>
381
+ <html lang="en">
382
+ <head>
383
+ <meta charset="UTF-8" />
384
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
385
+ <title>Tonder Checkout Example</title>
386
+ <script src="https://js.skyflow.com/v1/index.js"></script>
387
+ <script src="https://openpay.s3.amazonaws.com/openpay.v1.min.js"></script>
388
+ <script src="https://openpay.s3.amazonaws.com/openpay-data.v1.min.js"></script>
389
+ <!-- Only if not use npm package -->
390
+ <script src="https://zplit-prod.s3.amazonaws.com/v1/bundle.min.js"></script>
391
+ </head>
392
+ <body>
393
+ <div id="tonder-checkout"></div>
394
+ <button id="pay-button">Pay Now</button>
395
+
396
+ <script src="your-script.js"></script>
397
+ </body>
398
+ </html>
399
+ ```
400
+
401
+ #### InlineCheckout Example (your-script.js)
402
+
403
+ ```javascript
404
+ import { InlineCheckout } from "tonder-web-sdk";
405
+
406
+ const apiKey = "your-api-key";
407
+ const returnUrl = "http://your-website.com/checkout";
141
408
 
142
- // if using script tag, it should be initialized like this
143
- // new TonderSdk.InlineCheckout
144
409
  const inlineCheckout = new InlineCheckout({
410
+ mode: "development",
145
411
  apiKey,
146
412
  returnUrl,
147
- styles: customStyles
413
+ styles: customStyles, // Define your custom styles here
148
414
  });
149
415
 
150
- // The configureCheckout function allows you to set initial information,
151
- // such as the customer's email, which is used to retrieve a list of saved cards.
152
- inlineCheckout.configureCheckout({customer: {email: "example@email.com"}});
416
+ inlineCheckout.configureCheckout({ customer: { email: "example@email.com" } });
417
+ inlineCheckout.injectCheckout();
153
418
 
419
+ inlineCheckout.verify3dsTransaction().then((response) => {
420
+ console.log("Verify 3ds response", response);
421
+ });
154
422
 
155
- inlineCheckout.injectCheckout();
423
+ document
424
+ .getElementById("pay-button")
425
+ .addEventListener("click", async function () {
426
+ try {
427
+ const response = await inlineCheckout.payment(checkoutData);
428
+ console.log("Payment response:", response);
429
+ alert("Payment successful");
430
+ } catch (error) {
431
+ console.error("Payment error:", error.details);
432
+ alert("Payment failed");
433
+ }
434
+ });
435
+ ```
156
436
 
157
- // To verify a 3ds transaction you can use the following method
158
- // It should be called after the injectCheckout method
159
- // The response status will be one of the following
160
- // ['Declined', 'Cancelled', 'Failed', 'Success', 'Pending', 'Authorized']
437
+ #### LiteCheckout Example (your-script.js)
161
438
 
162
- inlineCheckout.verify3dsTransaction().then(response => {
163
- console.log('Verify 3ds response', response)
164
- })
439
+ ```javascript
440
+ import { LiteInlineCheckout } from "tonder-web-sdk";
165
441
 
166
- const response = await inlineCheckout.payment(checkoutData);
442
+ const apiKey = "your-api-key";
443
+ const returnUrl = "http://your-website.com/checkout";
444
+
445
+ const liteCheckout = new LiteInlineCheckout({
446
+ mode: "development",
447
+ apiKey,
448
+ returnUrl,
449
+ });
450
+
451
+ liteCheckout.configureCheckout({ customer: { email: "example@email.com" } });
452
+ liteCheckout.injectCheckout();
453
+
454
+ liteCheckout.verify3dsTransaction().then((response) => {
455
+ console.log("Verify 3ds response", response);
456
+ });
457
+
458
+ document
459
+ .getElementById("lite-payment-form")
460
+ .addEventListener("submit", async function (event) {
461
+ event.preventDefault();
462
+ const cardData = {
463
+ card_number: document.getElementById("card-number").value,
464
+ cardholder_name: document.getElementById("card-name").value,
465
+ expiration_month: document.getElementById("month").value,
466
+ expiration_year: document.getElementById("year").value,
467
+ cvv: document.getElementById("cvv").value,
468
+ };
469
+
470
+ try {
471
+ const paymentData = { ...checkoutData, card: cardData };
472
+ const response = await liteCheckout.payment(paymentData);
473
+ console.log("Payment response:", response);
474
+ alert("Payment successful");
475
+ } catch (error) {
476
+ console.error("Payment error:", error);
477
+ alert("Payment failed");
478
+ }
479
+ });
167
480
  ```
168
481
 
169
- ## React Example
170
- ```javascript
482
+ ### React or Nextjs
483
+
484
+ For React or Nextjs applications, we recommend using a context provider to manage the Tonder instance across your application.
485
+
486
+ First, create a TonderProvider:
487
+
488
+ ```jsx
489
+ // TonderProvider.jsx
490
+ "use client"; // only for Nextjs
491
+ import React, { createContext, useContext, useState, useEffect } from "react";
492
+ import { InlineCheckout } from "tonder-web-sdk";
493
+
494
+ const TonderContext = createContext();
495
+
496
+ export const useTonder = () => useContext(TonderContext);
497
+
498
+ export const TonderProvider = ({ children }) => {
499
+ const [tonderInstance, setTonderInstance] = useState(null);
500
+
501
+ useEffect(() => {
502
+ const init = async () => {
503
+ try {
504
+ const inlineCheckout = new InlineCheckout({
505
+ mode: "development",
506
+ apiKey: "your-api-key",
507
+ returnUrl: "http://your-website.com/checkout",
508
+ });
509
+ setTonderInstance(inlineCheckout);
510
+ } catch (error) {
511
+ console.error("Error initializing Tonder:", error);
512
+ }
513
+ };
514
+
515
+ init();
516
+ }, []);
517
+
518
+ return (
519
+ <TonderContext.Provider value={tonderInstance}>
520
+ {children}
521
+ </TonderContext.Provider>
522
+ );
523
+ };
171
524
  ```
172
525
 
173
- ## Configuration
174
- | Property | Type | Description |
175
- |:---------------:|:-------------:|:---------------------------------------------------:|
176
- | mode | string | 'stage' 'production' 'sandbox', default 'stage' |
177
- | apiKey | string | You can take this from you Tonder Dashboard |
178
- | backgroundColor | string | Hex color #000000 |
179
- | returnUrl | string | url where the checkout form is mounted (3ds) |
180
- | backgroundColor | string | |
526
+ Then, create a TonderCheckout component:
181
527
 
182
- ## setPayment params
183
- ### products
184
- It will receive an array of objects that represent the products.
185
- ```javascript
186
- [
528
+ ```jsx
529
+ // TonderCheckout.jsx
530
+ "use client"; // only for Nextjs
531
+ import React, { useEffect, useState } from "react";
532
+ import { useTonder } from "./TonderProvider";
533
+
534
+ const TonderCheckout = () => {
535
+ const tonder = useTonder();
536
+ const [loading, setLoading] = useState(false);
537
+
538
+ useEffect(() => {
539
+ if (!tonder) return;
540
+
541
+ tonder.configureCheckout({ customer: { email: "example@email.com" } });
542
+ tonder.injectCheckout();
543
+
544
+ tonder.verify3dsTransaction().then((response) => {
545
+ console.log("Verify 3ds response", response);
546
+ });
547
+
548
+ return () => {
549
+ if (tonder.removeCheckout) {
550
+ tonder.removeCheckout();
551
+ }
552
+ };
553
+ }, [tonder]);
554
+
555
+ const handlePayment = async () => {
556
+ if (!tonder) return;
557
+ setLoading(true);
558
+ try {
559
+ const response = await tonder.payment(paymentData);
560
+ console.log("Payment successful:", response);
561
+ alert("Payment successful");
562
+ } catch (error) {
563
+ console.error("Payment failed:", error);
564
+ alert("Payment failed");
565
+ } finally {
566
+ setLoading(false);
567
+ }
568
+ };
569
+
570
+ return (
571
+ <div>
572
+ <div id="tonder-checkout"></div>
573
+ <button onClick={handlePayment} disabled={loading}>
574
+ {loading ? "Processing..." : "Pay Now"}
575
+ </button>
576
+ </div>
577
+ );
578
+ };
579
+
580
+ export default TonderCheckout;
581
+ ```
582
+
583
+ Finally, use it in your checkout component:
584
+
585
+ ```jsx
586
+ "use client";
587
+ import { useEffect, useState } from "react";
588
+ import { useTonder, TonderProvider } from "./TonderProvider";
589
+ import Script from "next/script";
590
+
591
+ export default function TonderCheckout() {
592
+ return (
593
+ <div id="checkout">
594
+ {/*Provider*/}
595
+ <TonderProvider>
596
+ <CheckoutContent />
597
+ </TonderProvider>
598
+ </div>
599
+ );
600
+ }
601
+
602
+ function CheckoutContent() {
603
+ const tonder = useTonder();
604
+ const [loading, setLoading] = useState(false);
605
+
606
+ useEffect(() => {
607
+ if (!tonder) return;
608
+ tonder.configureCheckout({ customer: { email: "example@email.com" } });
609
+ tonder.injectCheckout();
610
+ tonder.verify3dsTransaction().then((response) => {
611
+ console.log("Verify 3ds response", response);
612
+ });
613
+ return () => {
614
+ if (tonder.removeCheckout) {
615
+ tonder.removeCheckout();
616
+ }
617
+ };
618
+ }, [tonder]);
619
+
620
+ const handlePayment = async () => {
621
+ if (!tonder) return;
622
+ setLoading(true);
623
+ try {
624
+ const response = await tonder.payment(paymentData);
625
+ console.log(response);
626
+ alert("Payment successful");
627
+ } catch (error) {
628
+ console.error(error);
629
+ alert("Payment failed");
630
+ } finally {
631
+ setLoading(false);
632
+ }
633
+ };
634
+
635
+ return (
636
+ <div>
637
+ <div id="tonder-checkout"></div>
638
+ <button onClick={handlePayment} disabled={loading}>
639
+ {loading ? "Processing..." : "Pay"}
640
+ </button>
641
+ </div>
642
+ );
643
+ }
644
+ ```
645
+
646
+ ### Angular
647
+
648
+ For Angular, we recommend using a service to manage the Tonder instance:
649
+
650
+ ```typescript
651
+ // tonder.service.ts
652
+ import { Injectable } from "@angular/core";
653
+ import { InlineCheckout } from "tonder-web-sdk";
654
+
655
+ @Injectable({
656
+ providedIn: "root",
657
+ })
658
+ export class TonderService {
659
+ private inlineCheckout: InlineCheckout;
660
+
661
+ constructor(private sdkParameters: IInlineCheckoutOptions) {
662
+ this.initializeInlineCheckout();
663
+ }
664
+
665
+ private initializeInlineCheckout(): void {
666
+ this.inlineCheckout = new InlineCheckout({ ...this.sdkParameters });
667
+ }
668
+
669
+ configureCheckout(customerData: IConfigureCheckout): void {
670
+ this.inlineCheckout.configureCheckout({ ...customerData });
671
+ }
672
+
673
+ async injectCheckout(): Promise<void> {
674
+ await this.inlineCheckout.injectCheckout();
675
+ }
676
+
677
+ verify3dsTransaction(): Promise<ITransaction | void> {
678
+ return this.inlineCheckout.verify3dsTransaction();
679
+ }
680
+
681
+ // Add more functions, for example for lite sdk: get payment methods
682
+
683
+ // getCustomerPaymentMethods(): Promise<IPaymentMethod[]> {
684
+ // return this.liteCheckout.getCustomerPaymentMethods();
685
+ // }
686
+ }
687
+
688
+ // checkout.component.ts
689
+ import { Component, OnInit, OnDestroy } from "@angular/core";
690
+ import { TonderService } from "./tonder.service";
691
+
692
+ @Component({
693
+ selector: "app-tonder-checkout",
694
+ template: `
695
+ <div id="tonder-checkout"></div>
696
+ <button (click)="pay()" [disabled]="loading">
697
+ {{ loading ? "Processing..." : "Pay" }}
698
+ </button>
699
+ `,
700
+ providers: [
187
701
  {
188
- name: 'name of the product',
189
- price_unit: 'valid float string with the price of the product',
190
- quantity: 'valid integer strig with the quantity of this product',
702
+ provide: TonderInlineService,
703
+ // Inicialización del SDK de Tonder Inline
704
+ // Nota: Reemplace estas credenciales con las suyas propias en desarrollo/producción
705
+ useFactory: () =>
706
+ new TonderInlineService({
707
+ apiKey: "11e3d3c3e95e0eaabbcae61ebad34ee5f93c3d27",
708
+ returnUrl: "http://localhost:4200/checkout/payment?tabPayment=0",
709
+ mode: "development",
710
+ }),
711
+ },
712
+ ],
713
+ })
714
+ export class TonderCheckoutComponent implements OnInit, OnDestroy {
715
+ loading = false;
716
+
717
+ constructor(private tonderService: TonderService) {}
718
+
719
+ ngOnInit() {
720
+ this.initCheckout();
721
+ }
722
+
723
+ ngOnDestroy() {
724
+ // Limpieza del checkout al destruir el componente
725
+ this.tonderService.removeCheckout();
726
+ }
727
+
728
+ async initCheckout() {
729
+ this.tonderService.configureCheckout({
730
+ customer: { email: "example@email.com" },
731
+ });
732
+ await this.tonderService.injectCheckout();
733
+ this.tonderService.verify3dsTransaction().then((response) => {
734
+ console.log("Verify 3ds response", response);
735
+ });
736
+ }
737
+
738
+ async pay() {
739
+ this.loading = true;
740
+ try {
741
+ const response = await this.tonderService.payment(paymentData);
742
+ console.log("Payment successful:", response);
743
+ alert("Payment successful");
744
+ } catch (error) {
745
+ console.error("Payment failed:", error);
746
+ alert("Payment failed");
747
+ } finally {
748
+ this.loading = false;
191
749
  }
192
- ]
750
+ }
751
+ }
193
752
  ```
194
- ### shippingCost
195
- It is a valid float string, that will be the shipping cost.
196
753
 
197
- ### email
198
- The email of the customer that is making the purchase.
754
+ ## Notes
199
755
 
200
- ### apiKey
201
- Your api key getted from Tonder Dashboard
756
+ ### General
202
757
 
203
- ### customer
204
- The data of the customer to be registered in the transaction
758
+ - Replace `'your-api-key'`, `'http://your-website.com/checkout'`, `customStyles`, and `paymentData` with your actual values.
759
+ - The `paymentData` should be defined according to your specific requirements.
205
760
 
206
- ### items
207
- An array of items to be registered in the Tonder order.
761
+ ### Script Dependencies
208
762
 
209
- ### Mount element
210
- You need to have an element where the inline checkout will be mounted, this should be a DIV element with the ID "tonder-checkout"
763
+ For all implementations, ensure you include the necessary scripts:
211
764
 
212
765
  ```html
213
- <div id="tonder-checkout"></div>
766
+ <script src="https://js.skyflow.com/v1/index.js"></script>
767
+ <script src="https://openpay.s3.amazonaws.com/openpay.v1.min.js"></script>
768
+ <script src="https://openpay.s3.amazonaws.com/openpay-data.v1.min.js"></script>
769
+ <!-- Only if not use npm package -->
770
+ <script src="https://zplit-prod.s3.amazonaws.com/v1/bundle.min.js"></script>
214
771
  ```
772
+
215
773
  ## License
216
774
 
217
- [MIT](https://choosealicense.com/licenses/mit/)
775
+ [MIT](https://choosealicense.com/licenses/mit/)