tonder-web-sdk 1.15.2 → 1.16.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/.husky/pre-commit +4 -0
- package/.prettierignore +8 -0
- package/.prettierrc +10 -0
- package/README.md +189 -35
- package/eslint.config.mjs +15 -0
- package/package.json +21 -4
- package/src/classes/3dsHandler.js +58 -62
- package/src/classes/BaseInlineCheckout.js +21 -36
- package/src/classes/LiteInlineCheckout.js +8 -8
- package/src/classes/checkout.js +75 -71
- package/src/classes/globalLoader.js +9 -7
- package/src/classes/inlineCheckout.js +528 -250
- package/src/data/apmApi.js +8 -14
- package/src/data/businessApi.js +5 -8
- package/src/data/cardApi.js +5 -14
- package/src/data/checkoutApi.js +54 -54
- package/src/data/customerApi.js +1 -6
- package/src/data/index.js +15 -15
- package/src/data/openPayApi.js +7 -7
- package/src/data/skyflowApi.js +14 -16
- package/src/helpers/skyflow.js +210 -119
- package/src/helpers/styles.js +56 -27
- package/src/helpers/template-skeleton.js +1 -1
- package/src/helpers/template.js +984 -541
- package/src/helpers/utils.js +152 -58
- package/src/helpers/validations.js +34 -35
- package/src/index-dev.js +38 -11
- package/src/index.html +20 -12
- package/src/index.js +19 -13
- package/src/shared/catalog/commonLogosCatalog.js +7 -0
- package/src/shared/catalog/paymentMethodsCatalog.js +242 -243
- package/src/shared/constants/colors.js +15 -0
- package/src/shared/constants/displayMode.js +4 -0
- package/src/shared/constants/fieldPathNames.js +4 -0
- package/src/shared/constants/htmlTonderIds.js +18 -0
- package/src/shared/constants/messages.js +10 -9
- package/types/card.d.ts +17 -17
- package/types/checkout.d.ts +85 -87
- package/types/common.d.ts +4 -1
- package/types/customer.d.ts +10 -10
- package/types/index.d.ts +9 -11
- package/types/inlineCheckout.d.ts +81 -61
- package/types/liteInlineCheckout.d.ts +78 -83
- package/types/paymentMethod.d.ts +17 -17
- package/types/transaction.d.ts +94 -94
- package/v1/bundle.min.js +3 -3
package/.prettierignore
ADDED
package/.prettierrc
ADDED
package/README.md
CHANGED
|
@@ -8,7 +8,9 @@ Tonder SDK helps to integrate the services Tonder offers in your own website
|
|
|
8
8
|
2. [Usage](#usage)
|
|
9
9
|
- [InlineCheckout](#inlinecheckout)
|
|
10
10
|
- [LiteCheckout](#litecheckout)
|
|
11
|
-
3. [Configuration Options](#configuration
|
|
11
|
+
3. [Configuration Options](#configuration)
|
|
12
|
+
- [Inline Options](#inline-options)
|
|
13
|
+
- [Lite Options](#lite-options)
|
|
12
14
|
4. [Styling InlineCheckout](#styling-inlinecheckout)
|
|
13
15
|
5. [Payment Data Structure](#payment-data-structure)
|
|
14
16
|
6. [Field Validation Functions](#field-validation-functions)
|
|
@@ -96,16 +98,16 @@ inlineCheckout.verify3dsTransaction().then((response) => {
|
|
|
96
98
|
const response = await inlineCheckout.payment(checkoutData);
|
|
97
99
|
```
|
|
98
100
|
|
|
99
|
-
###
|
|
101
|
+
### LiteInlineCheckout
|
|
100
102
|
|
|
101
|
-
|
|
103
|
+
LiteInlineCheckout allows you to build a custom checkout interface using Tonder's core functionality.
|
|
102
104
|
|
|
103
105
|
```javascript
|
|
104
|
-
import {
|
|
106
|
+
import { LiteInlineCheckout } from "tonder-web-sdk";
|
|
105
107
|
```
|
|
106
108
|
|
|
107
109
|
```javascript
|
|
108
|
-
const
|
|
110
|
+
const LiteInlineCheckout = new LiteInlineCheckout({
|
|
109
111
|
apiKey: "your-api-key", // Your api key getted from Tonder Dashboard
|
|
110
112
|
returnUrl: "http://your-website.com/checkout",
|
|
111
113
|
});
|
|
@@ -115,53 +117,148 @@ const liteCheckout = new LiteCheckout({
|
|
|
115
117
|
inlineCheckout.configureCheckout({ customer: { email: "example@email.com" } });
|
|
116
118
|
|
|
117
119
|
// Initialize the checkout
|
|
118
|
-
await
|
|
120
|
+
await LiteInlineCheckout.injectCheckout();
|
|
119
121
|
```
|
|
120
122
|
|
|
121
123
|
```javascript
|
|
122
124
|
// Retrieve customer's saved cards
|
|
123
|
-
const cards = await
|
|
125
|
+
const cards = await LiteInlineCheckout.getCustomerCards();
|
|
124
126
|
```
|
|
125
127
|
|
|
126
128
|
```javascript
|
|
127
129
|
// Save a new card
|
|
128
|
-
const newCard = await
|
|
130
|
+
const newCard = await LiteInlineCheckout.saveCustomerCard(cardData);
|
|
129
131
|
```
|
|
130
132
|
|
|
131
133
|
```javascript
|
|
132
134
|
// Remove a saved card
|
|
133
|
-
await
|
|
135
|
+
await LiteInlineCheckout.removeCustomerCard(cardId);
|
|
134
136
|
```
|
|
135
137
|
|
|
136
138
|
```javascript
|
|
137
139
|
// Get available payment methods
|
|
138
|
-
const paymentMethods = await
|
|
140
|
+
const paymentMethods = await LiteInlineCheckout.getCustomerPaymentMethods();
|
|
139
141
|
```
|
|
140
142
|
|
|
141
143
|
```javascript
|
|
142
144
|
// Process a payment
|
|
143
|
-
const paymentResponse = await
|
|
145
|
+
const paymentResponse = await LiteInlineCheckout.payment(paymentData);
|
|
144
146
|
```
|
|
145
147
|
|
|
146
148
|
```javascript
|
|
147
149
|
// Verify a 3DS transaction
|
|
148
|
-
const verificationResult = await
|
|
150
|
+
const verificationResult = await LiteInlineCheckout.verify3dsTransaction();
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Configuration
|
|
154
|
+
### Inline Options
|
|
155
|
+
|
|
156
|
+
| Property | Type | Required | Description | Default | Description |
|
|
157
|
+
|:-------------:|:--------------------:|----------|------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------:|
|
|
158
|
+
| mode | string | Yes | Environment mode for the SDK | stage | Environment mode. Options: 'stage', 'production', 'sandbox'. Default: 'stage' |
|
|
159
|
+
| apiKey | string | Yes | Your Tonder Public API key | | Your API key from the Tonder Dashboard |
|
|
160
|
+
| returnUrl | string | Yes | URL for 3DS redirect completion | | URL where the checkout form is mounted (used for 3DS) |
|
|
161
|
+
| styles | object | No | | | (InlineCheckout only) Custom styles for the checkout interface |
|
|
162
|
+
| customization | CustomizationOptions | No | UI customization options | `{displayMode: 'light',saveCards: {showSaveCardOption: false,showSaved: false,autoSave: false,},paymentButton: {show: false,text: "Pagar",showAmount: true,},cancelButton: {show: false,text: "Cancelar",},paymentMethods: {show: true,},cardForm: {show: true,},showMessages: true,}` | Object to customize the checkout behavior and UI. |
|
|
163
|
+
| callbacks | IInlineCallbacks | No | Payment process callback functions |
|
|
164
|
+
<details>
|
|
165
|
+
<summary>View Interface Definition</summary>
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
interface IInlineCheckoutBaseOptions {
|
|
169
|
+
mode?: "production" | "sandbox" | "stage" | "development";
|
|
170
|
+
apiKey: string;
|
|
171
|
+
returnUrl: string;
|
|
172
|
+
callBack?: (response: any) => void;
|
|
173
|
+
}
|
|
174
|
+
interface IInlineCheckoutOptions extends IInlineCheckoutBaseOptions {
|
|
175
|
+
styles?: Record<string, string>;
|
|
176
|
+
customization?: CustomizationOptions;
|
|
177
|
+
callbacks?: IInlineCallbacks;
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
</details>
|
|
181
|
+
|
|
182
|
+
> **Important Note about SaveCard functionality**:
|
|
183
|
+
> To properly implement the SaveCard feature, you must use a SecureToken. For detailed implementation instructions and best practices, please refer to our official documentation on [How to use SecureToken for secure card saving](https://docs.tonder.io/integration/sdks/secure-token#how-to-use-securetoken-for-secure-card-saving).
|
|
184
|
+
|
|
185
|
+
### Inline Callbacks Structure
|
|
186
|
+
|
|
187
|
+
| Callback | Required | Parameters | Description | Return |
|
|
188
|
+
|------------|----------|------------|--------------------------------------------|---------------|
|
|
189
|
+
| `onCancel` | No | none | Called when user clicked the cancel button | Promise<void> |
|
|
190
|
+
<details>
|
|
191
|
+
<summary>View Interface Definition</summary>
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
interface IInlineCallbacks extends IBaseCallback {
|
|
195
|
+
onCancel?: () => Promise<void>;
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
</details>
|
|
199
|
+
|
|
200
|
+
### Inline Customization Options
|
|
201
|
+
|
|
202
|
+
| Option | Type | Default | Description |
|
|
203
|
+
|------------------------------|---------|------------|-------------------------------------------------------------------------------------------|
|
|
204
|
+
| **saveCards** |
|
|
205
|
+
| saveCards.showSaveCardOption | boolean | true | Shows a checkbox allowing users to choose whether to save their card for future purchases |
|
|
206
|
+
| saveCards.showSaved | boolean | true | Displays a list of previously saved cards for the customer |
|
|
207
|
+
| saveCards.autoSave | boolean | false | Automatically saves the card without showing the save option to the user |
|
|
208
|
+
| **paymentButton** |
|
|
209
|
+
| paymentButton.show | boolean | true | Controls the visibility of the payment button |
|
|
210
|
+
| paymentButton.text | string | 'Pagar' | Custom text to display on the payment button |
|
|
211
|
+
| paymentButton.showAmount | boolean | true | Shows the payment amount on the button (e.g., "Pay $100") |
|
|
212
|
+
| **cancelButton** |
|
|
213
|
+
| cancelButton.show | boolean | true | Controls the visibility of the cancel button |
|
|
214
|
+
| cancelButton.text | string | 'Cancelar' | Custom text to display on the cancel button |
|
|
215
|
+
| **paymentMethods** |
|
|
216
|
+
| paymentMethods.show | boolean | true | Controls the visibility of alternative payment methods section |
|
|
217
|
+
| **cardForm** |
|
|
218
|
+
| cardForm.show | boolean | true | Controls the visibility of the card input form |
|
|
219
|
+
| **General** |
|
|
220
|
+
| showMessages | boolean | true | Controls the visibility of error and success messages |
|
|
221
|
+
| displayMode | string | light | Controls the display mode light or dark |
|
|
222
|
+
|
|
223
|
+
<details>
|
|
224
|
+
<summary>View Interface Definition</summary>
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
export type CustomizationOptions = {
|
|
228
|
+
displayMode?: "light" | "dark";
|
|
229
|
+
saveCards?: {
|
|
230
|
+
showSaveCardOption?: boolean;
|
|
231
|
+
showSaved?: boolean;
|
|
232
|
+
autoSave?: boolean;
|
|
233
|
+
};
|
|
234
|
+
paymentButton?: {
|
|
235
|
+
show?: boolean;
|
|
236
|
+
text?: string;
|
|
237
|
+
showAmount?: boolean;
|
|
238
|
+
};
|
|
239
|
+
cancelButton?: {
|
|
240
|
+
show?: boolean;
|
|
241
|
+
text?: string;
|
|
242
|
+
};
|
|
243
|
+
paymentMethods?: {
|
|
244
|
+
show?: boolean;
|
|
245
|
+
};
|
|
246
|
+
cardForm?: {
|
|
247
|
+
show?: boolean;
|
|
248
|
+
};
|
|
249
|
+
showMessages?: boolean;
|
|
250
|
+
};
|
|
149
251
|
```
|
|
252
|
+
</details>
|
|
150
253
|
|
|
151
|
-
##
|
|
254
|
+
## Lite Options
|
|
152
255
|
|
|
153
|
-
|
|
256
|
+
| Property | Type | Required | Description | Default | Description |
|
|
257
|
+
|:---------:|:------:|----------|---------------------------------|---------|:-----------------------------------------------------------------------------:|
|
|
258
|
+
| mode | string | Yes | Environment mode for the SDK | stage | Environment mode. Options: 'stage', 'production', 'sandbox'. Default: 'stage' |
|
|
259
|
+
| apiKey | string | Yes | Your Tonder Public API key | | Your API key from the Tonder Dashboard |
|
|
260
|
+
| returnUrl | string | Yes | URL for 3DS redirect completion | | URL where the checkout form is mounted (used for 3DS) |
|
|
154
261
|
|
|
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
262
|
|
|
166
263
|
## Styling InlineCheckout
|
|
167
264
|
|
|
@@ -252,15 +349,15 @@ When calling the `payment` method, use the following data structure:
|
|
|
252
349
|
|
|
253
350
|
- **metadata**: Object for including any additional information about the transaction. This can be used for internal references or tracking.
|
|
254
351
|
|
|
255
|
-
- **card**: (for
|
|
352
|
+
- **card**: (for LiteInlineCheckout) Object containing card information. This is used differently depending on whether it's a new card or a saved card:
|
|
256
353
|
|
|
257
354
|
- For a new card: Include `card_number`, `cvv`, `expiration_month`, `expiration_year`, and `cardholder_name`.
|
|
258
355
|
- For a saved card: Include only the `skyflow_id` of the saved card.
|
|
259
356
|
- This is only used when not paying with a payment_method.
|
|
260
357
|
|
|
261
|
-
- **payment_method**: (for
|
|
358
|
+
- **payment_method**: (for LiteInlineCheckout) String indicating the alternative payment method to be used (e.g., "Spei"). This is only used when not paying with a card.
|
|
262
359
|
|
|
263
|
-
Note: The exact fields required may vary depending on whether you're using InlineCheckout or
|
|
360
|
+
Note: The exact fields required may vary depending on whether you're using InlineCheckout or LiteInlineCheckout, and the specific payment method being used.
|
|
264
361
|
|
|
265
362
|
```javascript
|
|
266
363
|
const paymentData = {
|
|
@@ -312,7 +409,7 @@ const paymentData = {
|
|
|
312
409
|
|
|
313
410
|
## Field Validation Functions
|
|
314
411
|
|
|
315
|
-
For
|
|
412
|
+
For LiteInlineCheckout implementations, the SDK provides validation functions to ensure the integrity of card data before submitting:
|
|
316
413
|
|
|
317
414
|
- `validateCardNumber(cardNumber)`: Validates the card number using the Luhn algorithm.
|
|
318
415
|
- `validateCardholderName(name)`: Checks if the cardholder name is valid.
|
|
@@ -357,7 +454,7 @@ if (
|
|
|
357
454
|
- `payment(data)`: Process a payment
|
|
358
455
|
- `verify3dsTransaction()`: Verify a 3DS transaction
|
|
359
456
|
|
|
360
|
-
###
|
|
457
|
+
### LiteInlineCheckout Methods
|
|
361
458
|
|
|
362
459
|
- `configureCheckout(data)`: Set initial checkout data
|
|
363
460
|
- `injectCheckout()`: Initialize the checkout
|
|
@@ -434,6 +531,63 @@ document
|
|
|
434
531
|
});
|
|
435
532
|
```
|
|
436
533
|
|
|
534
|
+
|
|
535
|
+
#### InlineCheckout with default Tonder Payment button Example (your-script.js)
|
|
536
|
+
> 💡 **Note:** It is important to send all payment data (customer, cart, metadata, etc) when configuring the checkout; this is necessary when using Tonder's default payment button.
|
|
537
|
+
|
|
538
|
+
```javascript
|
|
539
|
+
import { InlineCheckout } from "tonder-web-sdk";
|
|
540
|
+
|
|
541
|
+
const apiKey = "your-api-key";
|
|
542
|
+
const returnUrl = "http://your-website.com/checkout";
|
|
543
|
+
|
|
544
|
+
const inlineCheckout = new InlineCheckout({
|
|
545
|
+
mode: "development",
|
|
546
|
+
apiKey,
|
|
547
|
+
returnUrl,
|
|
548
|
+
styles: customStyles,
|
|
549
|
+
customization: {
|
|
550
|
+
paymentButton: {
|
|
551
|
+
show: true
|
|
552
|
+
}
|
|
553
|
+
}, // activate default Tonder Payment button
|
|
554
|
+
callBack: (response) => {
|
|
555
|
+
console.log('Payment response', response)
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
// It is important to send all payment data (customer, cart, metadata, etc) when configuring the checkout; this is necessary when using Tonder's default payment button.
|
|
560
|
+
inlineCheckout.configureCheckout(
|
|
561
|
+
{
|
|
562
|
+
customer: { email: "example@email.com" },
|
|
563
|
+
currency: "mxn",
|
|
564
|
+
cart: {
|
|
565
|
+
total: 399,
|
|
566
|
+
items: [
|
|
567
|
+
{
|
|
568
|
+
description: "Black T-Shirt",
|
|
569
|
+
quantity: 1,
|
|
570
|
+
price_unit: 1,
|
|
571
|
+
discount: 0,
|
|
572
|
+
taxes: 0,
|
|
573
|
+
product_reference: 1,
|
|
574
|
+
name: "T-Shirt",
|
|
575
|
+
amount_total: 399,
|
|
576
|
+
},
|
|
577
|
+
],
|
|
578
|
+
},
|
|
579
|
+
metadata: {}, // Optional
|
|
580
|
+
order_reference: "" // Optional
|
|
581
|
+
}
|
|
582
|
+
);
|
|
583
|
+
inlineCheckout.injectCheckout();
|
|
584
|
+
|
|
585
|
+
inlineCheckout.verify3dsTransaction().then((response) => {
|
|
586
|
+
console.log("Verify 3ds response", response);
|
|
587
|
+
});
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
|
|
437
591
|
#### LiteCheckout Example (your-script.js)
|
|
438
592
|
|
|
439
593
|
```javascript
|
|
@@ -442,16 +596,16 @@ import { LiteInlineCheckout } from "tonder-web-sdk";
|
|
|
442
596
|
const apiKey = "your-api-key";
|
|
443
597
|
const returnUrl = "http://your-website.com/checkout";
|
|
444
598
|
|
|
445
|
-
const
|
|
599
|
+
const LiteInlineCheckout = new LiteInlineCheckout({
|
|
446
600
|
mode: "development",
|
|
447
601
|
apiKey,
|
|
448
602
|
returnUrl,
|
|
449
603
|
});
|
|
450
604
|
|
|
451
|
-
|
|
452
|
-
|
|
605
|
+
LiteInlineCheckout.configureCheckout({ customer: { email: "example@email.com" } });
|
|
606
|
+
LiteInlineCheckout.injectCheckout();
|
|
453
607
|
|
|
454
|
-
|
|
608
|
+
LiteInlineCheckout.verify3dsTransaction().then((response) => {
|
|
455
609
|
console.log("Verify 3ds response", response);
|
|
456
610
|
});
|
|
457
611
|
|
|
@@ -469,7 +623,7 @@ document
|
|
|
469
623
|
|
|
470
624
|
try {
|
|
471
625
|
const paymentData = { ...checkoutData, card: cardData };
|
|
472
|
-
const response = await
|
|
626
|
+
const response = await LiteInlineCheckout.payment(paymentData);
|
|
473
627
|
console.log("Payment response:", response);
|
|
474
628
|
alert("Payment successful");
|
|
475
629
|
} catch (error) {
|
|
@@ -681,7 +835,7 @@ export class TonderService {
|
|
|
681
835
|
// Add more functions, for example for lite sdk: get payment methods
|
|
682
836
|
|
|
683
837
|
// getCustomerPaymentMethods(): Promise<IPaymentMethod[]> {
|
|
684
|
-
// return this.
|
|
838
|
+
// return this.LiteInlineCheckout.getCustomerPaymentMethods();
|
|
685
839
|
// }
|
|
686
840
|
}
|
|
687
841
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import eslintConfigPrettier from "eslint-config-prettier";
|
|
2
|
+
import eslintPluginPrettier from "eslint-plugin-prettier";
|
|
3
|
+
|
|
4
|
+
export default [
|
|
5
|
+
eslintConfigPrettier,
|
|
6
|
+
{
|
|
7
|
+
files: ["src/**/*.js"],
|
|
8
|
+
plugins: {
|
|
9
|
+
prettier: eslintPluginPrettier,
|
|
10
|
+
},
|
|
11
|
+
rules: {
|
|
12
|
+
"prettier/prettier": "error",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
];
|
package/package.json
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tonder-web-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.16.3",
|
|
4
4
|
"description": "tonder sdk for integrations",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"start": "webpack-dev-server",
|
|
8
|
-
"build": "webpack --config webpack.config.js --mode production"
|
|
8
|
+
"build": "webpack --config webpack.config.js --mode production",
|
|
9
|
+
"prepare": "husky install",
|
|
10
|
+
"format": "prettier --write .",
|
|
11
|
+
"lint": "eslint 'src/**/*.js'",
|
|
12
|
+
"lint:fix": "eslint 'src/**/*.js' --fix"
|
|
9
13
|
},
|
|
10
14
|
"author": "",
|
|
11
15
|
"types": "types/index.d.ts",
|
|
12
16
|
"license": "ISC",
|
|
13
17
|
"dependencies": {
|
|
18
|
+
"accordion-js": "^3.4.0",
|
|
14
19
|
"crypto-js": "^4.1.1",
|
|
15
|
-
"dotenv": "^16.3.1"
|
|
20
|
+
"dotenv": "^16.3.1",
|
|
21
|
+
"lodash.get": "^4.4.2"
|
|
16
22
|
},
|
|
17
23
|
"devDependencies": {
|
|
18
24
|
"@babel/core": "^7.20.12",
|
|
@@ -21,12 +27,23 @@
|
|
|
21
27
|
"babel-loader": "^9.1.2",
|
|
22
28
|
"css-loader": "^6.7.3",
|
|
23
29
|
"cypress": "^13.6.2",
|
|
30
|
+
"eslint": "^9.18.0",
|
|
31
|
+
"eslint-config-prettier": "^10.0.1",
|
|
32
|
+
"eslint-plugin-prettier": "^5.2.3",
|
|
24
33
|
"html-webpack-plugin": "^5.5.3",
|
|
25
|
-
"
|
|
34
|
+
"husky": "^8.0.3",
|
|
35
|
+
"lint-staged": "^15.4.1",
|
|
36
|
+
"prettier": "3.4.2",
|
|
26
37
|
"style-loader": "^3.3.1",
|
|
27
38
|
"terser-webpack-plugin": "^5.3.10",
|
|
28
39
|
"webpack": "^5.75.0",
|
|
29
40
|
"webpack-cli": "^5.0.1",
|
|
30
41
|
"webpack-dev-server": "^4.11.1"
|
|
42
|
+
},
|
|
43
|
+
"lint-staged": {
|
|
44
|
+
"**/*.{js,jsx,ts,tsx}": [
|
|
45
|
+
"npm run format",
|
|
46
|
+
"npm run lint:fix"
|
|
47
|
+
]
|
|
31
48
|
}
|
|
32
49
|
}
|
|
@@ -1,103 +1,99 @@
|
|
|
1
1
|
export class ThreeDSHandler {
|
|
2
|
-
constructor({
|
|
3
|
-
|
|
4
|
-
apiKey
|
|
5
|
-
|
|
6
|
-
}) {
|
|
7
|
-
this.baseUrl = baseUrl
|
|
8
|
-
this.apiKey = apiKey
|
|
9
|
-
this.payload = payload
|
|
2
|
+
constructor({ payload = null, apiKey, baseUrl }) {
|
|
3
|
+
this.baseUrl = baseUrl;
|
|
4
|
+
this.apiKey = apiKey;
|
|
5
|
+
this.payload = payload;
|
|
10
6
|
}
|
|
11
7
|
|
|
12
8
|
saveVerifyTransactionUrl() {
|
|
13
|
-
const url = this.payload?.next_action?.redirect_to_url?.verify_transaction_status_url
|
|
9
|
+
const url = this.payload?.next_action?.redirect_to_url?.verify_transaction_status_url;
|
|
14
10
|
if (url) {
|
|
15
|
-
this.saveUrlWithExpiration(url)
|
|
11
|
+
this.saveUrlWithExpiration(url);
|
|
16
12
|
} else {
|
|
17
|
-
const url = this.payload?.next_action?.iframe_resources?.verify_transaction_status_url
|
|
13
|
+
const url = this.payload?.next_action?.iframe_resources?.verify_transaction_status_url;
|
|
18
14
|
if (url) {
|
|
19
|
-
this.saveUrlWithExpiration(url)
|
|
15
|
+
this.saveUrlWithExpiration(url);
|
|
20
16
|
} else {
|
|
21
|
-
console.log(
|
|
17
|
+
console.log("No verify_transaction_status_url found");
|
|
22
18
|
}
|
|
23
19
|
}
|
|
24
20
|
}
|
|
25
21
|
|
|
26
22
|
saveUrlWithExpiration(url) {
|
|
27
23
|
try {
|
|
28
|
-
const now = new Date()
|
|
24
|
+
const now = new Date();
|
|
29
25
|
const item = {
|
|
30
26
|
url: url,
|
|
31
27
|
// Expires after 20 minutes
|
|
32
|
-
expires: now.getTime() + 20 * 60 * 1000
|
|
33
|
-
}
|
|
34
|
-
localStorage.setItem(
|
|
28
|
+
expires: now.getTime() + 20 * 60 * 1000,
|
|
29
|
+
};
|
|
30
|
+
localStorage.setItem("verify_transaction_status", JSON.stringify(item));
|
|
35
31
|
} catch (error) {
|
|
36
|
-
|
|
32
|
+
console.log("error: ", error);
|
|
37
33
|
}
|
|
38
34
|
}
|
|
39
35
|
|
|
40
36
|
getUrlWithExpiration() {
|
|
41
|
-
const item = JSON.parse(localStorage.getItem("verify_transaction_status"))
|
|
42
|
-
if (!item) return
|
|
37
|
+
const item = JSON.parse(localStorage.getItem("verify_transaction_status"));
|
|
38
|
+
if (!item) return;
|
|
43
39
|
|
|
44
|
-
const now = new Date()
|
|
40
|
+
const now = new Date();
|
|
45
41
|
if (now.getTime() > item.expires) {
|
|
46
|
-
this.removeVerifyTransactionUrl()
|
|
47
|
-
return null
|
|
42
|
+
this.removeVerifyTransactionUrl();
|
|
43
|
+
return null;
|
|
48
44
|
} else {
|
|
49
|
-
return item.url
|
|
45
|
+
return item.url;
|
|
50
46
|
}
|
|
51
47
|
}
|
|
52
48
|
|
|
53
49
|
removeVerifyTransactionUrl() {
|
|
54
|
-
localStorage.removeItem("verify_transaction_status")
|
|
50
|
+
localStorage.removeItem("verify_transaction_status");
|
|
55
51
|
}
|
|
56
52
|
|
|
57
53
|
getVerifyTransactionUrl() {
|
|
58
|
-
return localStorage.getItem("verify_transaction_status")
|
|
54
|
+
return localStorage.getItem("verify_transaction_status");
|
|
59
55
|
}
|
|
60
56
|
|
|
61
57
|
loadIframe() {
|
|
62
|
-
const iframe = this.payload?.next_action?.iframe_resources?.iframe
|
|
58
|
+
const iframe = this.payload?.next_action?.iframe_resources?.iframe;
|
|
63
59
|
if (iframe) {
|
|
64
60
|
return new Promise((resolve, reject) => {
|
|
65
|
-
const iframe = this.payload?.next_action?.iframe_resources?.iframe
|
|
61
|
+
const iframe = this.payload?.next_action?.iframe_resources?.iframe;
|
|
66
62
|
|
|
67
63
|
if (iframe) {
|
|
68
64
|
// TODO: This is not working for Azul
|
|
69
|
-
this.saveVerifyTransactionUrl()
|
|
70
|
-
const container = document.createElement(
|
|
71
|
-
container.innerHTML = iframe
|
|
72
|
-
document.body.appendChild(container)
|
|
65
|
+
this.saveVerifyTransactionUrl();
|
|
66
|
+
const container = document.createElement("div");
|
|
67
|
+
container.innerHTML = iframe;
|
|
68
|
+
document.body.appendChild(container);
|
|
73
69
|
|
|
74
70
|
// Create and append the script tag manually
|
|
75
|
-
const script = document.createElement(
|
|
76
|
-
script.textContent = 'document.getElementById("tdsMmethodForm").submit();'
|
|
77
|
-
container.appendChild(script)
|
|
71
|
+
const script = document.createElement("script");
|
|
72
|
+
script.textContent = 'document.getElementById("tdsMmethodForm").submit();';
|
|
73
|
+
container.appendChild(script);
|
|
78
74
|
|
|
79
75
|
// Resolve the promise when the iframe is loaded
|
|
80
|
-
const iframeElement = document.getElementById(
|
|
81
|
-
iframeElement.onload = () => resolve(true)
|
|
76
|
+
const iframeElement = document.getElementById("tdsMmethodTgtFrame");
|
|
77
|
+
iframeElement.onload = () => resolve(true);
|
|
82
78
|
} else {
|
|
83
|
-
console.log(
|
|
84
|
-
reject(false)
|
|
79
|
+
console.log("No redirection found");
|
|
80
|
+
reject(false);
|
|
85
81
|
}
|
|
86
|
-
})
|
|
82
|
+
});
|
|
87
83
|
}
|
|
88
84
|
}
|
|
89
85
|
|
|
90
86
|
getRedirectUrl() {
|
|
91
|
-
return this.payload?.next_action?.redirect_to_url?.url
|
|
87
|
+
return this.payload?.next_action?.redirect_to_url?.url;
|
|
92
88
|
}
|
|
93
89
|
|
|
94
90
|
redirectToChallenge() {
|
|
95
|
-
const url = this.getRedirectUrl()
|
|
91
|
+
const url = this.getRedirectUrl();
|
|
96
92
|
if (url) {
|
|
97
|
-
this.saveVerifyTransactionUrl()
|
|
93
|
+
this.saveVerifyTransactionUrl();
|
|
98
94
|
window.location = url;
|
|
99
95
|
} else {
|
|
100
|
-
console.log(
|
|
96
|
+
console.log("No redirection found");
|
|
101
97
|
}
|
|
102
98
|
}
|
|
103
99
|
|
|
@@ -118,7 +114,7 @@ export class ThreeDSHandler {
|
|
|
118
114
|
// TODO: Remove this duplication
|
|
119
115
|
handleSuccessTransaction(response) {
|
|
120
116
|
this.removeVerifyTransactionUrl();
|
|
121
|
-
console.log(
|
|
117
|
+
console.log("Transacción autorizada");
|
|
122
118
|
return response;
|
|
123
119
|
}
|
|
124
120
|
|
|
@@ -129,22 +125,22 @@ export class ThreeDSHandler {
|
|
|
129
125
|
|
|
130
126
|
async handle3dsChallenge(response_json) {
|
|
131
127
|
// Create the form element:
|
|
132
|
-
const form = document.createElement(
|
|
133
|
-
form.name =
|
|
134
|
-
form.method =
|
|
128
|
+
const form = document.createElement("form");
|
|
129
|
+
form.name = "frm";
|
|
130
|
+
form.method = "POST";
|
|
135
131
|
form.action = response_json.redirect_post_url;
|
|
136
132
|
|
|
137
133
|
// Add hidden fields:
|
|
138
|
-
const creqInput = document.createElement(
|
|
139
|
-
creqInput.type =
|
|
140
|
-
creqInput.name =
|
|
134
|
+
const creqInput = document.createElement("input");
|
|
135
|
+
creqInput.type = "hidden";
|
|
136
|
+
creqInput.name = "creq";
|
|
141
137
|
creqInput.value = response_json.creq;
|
|
142
138
|
form.appendChild(creqInput);
|
|
143
139
|
|
|
144
140
|
if (response_json.term_url) {
|
|
145
|
-
const termUrlInput = document.createElement(
|
|
146
|
-
termUrlInput.type =
|
|
147
|
-
termUrlInput.name =
|
|
141
|
+
const termUrlInput = document.createElement("input");
|
|
142
|
+
termUrlInput.type = "hidden";
|
|
143
|
+
termUrlInput.name = "TermUrl";
|
|
148
144
|
termUrlInput.value = response_json.term_url;
|
|
149
145
|
form.appendChild(termUrlInput);
|
|
150
146
|
}
|
|
@@ -164,7 +160,7 @@ export class ThreeDSHandler {
|
|
|
164
160
|
return this.handleSuccessTransaction(response_json);
|
|
165
161
|
} else {
|
|
166
162
|
this.handleDeclinedTransaction();
|
|
167
|
-
return response_json
|
|
163
|
+
return response_json;
|
|
168
164
|
}
|
|
169
165
|
}
|
|
170
166
|
|
|
@@ -182,22 +178,22 @@ export class ThreeDSHandler {
|
|
|
182
178
|
// body: JSON.stringify(data),
|
|
183
179
|
});
|
|
184
180
|
if (response.status !== 200) {
|
|
185
|
-
console.error(
|
|
181
|
+
console.error("La verificación de la transacción falló.");
|
|
186
182
|
this.removeVerifyTransactionUrl();
|
|
187
|
-
return response
|
|
183
|
+
return response;
|
|
188
184
|
}
|
|
189
185
|
|
|
190
186
|
return await this.handleTransactionResponse(response);
|
|
191
187
|
} catch (error) {
|
|
192
|
-
console.error(
|
|
188
|
+
console.error("Error al verificar la transacción:", error);
|
|
193
189
|
this.removeVerifyTransactionUrl();
|
|
194
190
|
}
|
|
195
191
|
} else {
|
|
196
|
-
console.log(
|
|
192
|
+
console.log("No verify_transaction_status_url found");
|
|
197
193
|
}
|
|
198
194
|
}
|
|
199
195
|
|
|
200
|
-
setPayload =
|
|
201
|
-
this.payload = payload
|
|
202
|
-
}
|
|
196
|
+
setPayload = payload => {
|
|
197
|
+
this.payload = payload;
|
|
198
|
+
};
|
|
203
199
|
}
|