tonder-web-sdk 1.12.3 → 1.14.0
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 +1 -1
- package/src/classes/3dsHandler.js +20 -9
- package/src/classes/BaseInlineCheckout.js +15 -14
- package/src/classes/inlineCheckout.js +23 -12
- package/src/data/cardApi.js +21 -4
- package/src/index-dev.js +8 -3
- package/types/common.d.ts +1 -0
- package/v1/bundle.min.js +1 -1
package/package.json
CHANGED
|
@@ -6,7 +6,8 @@ export class ThreeDSHandler {
|
|
|
6
6
|
}) {
|
|
7
7
|
this.baseUrl = baseUrl,
|
|
8
8
|
this.apiKey = apiKey,
|
|
9
|
-
this.payload = payload
|
|
9
|
+
this.payload = payload,
|
|
10
|
+
this.isTransactionPending = false
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
saveVerifyTransactionUrl() {
|
|
@@ -127,8 +128,6 @@ export class ThreeDSHandler {
|
|
|
127
128
|
return response;
|
|
128
129
|
}
|
|
129
130
|
|
|
130
|
-
// TODO: the method below needs to be tested with a real 3DS challenge
|
|
131
|
-
// since we couldn't get a test card that works with this feature
|
|
132
131
|
async handle3dsChallenge(response_json) {
|
|
133
132
|
// Create the form element:
|
|
134
133
|
const form = document.createElement('form');
|
|
@@ -139,15 +138,17 @@ export class ThreeDSHandler {
|
|
|
139
138
|
// Add hidden fields:
|
|
140
139
|
const creqInput = document.createElement('input');
|
|
141
140
|
creqInput.type = 'hidden';
|
|
142
|
-
creqInput.name =
|
|
141
|
+
creqInput.name = 'creq';
|
|
143
142
|
creqInput.value = response_json.creq;
|
|
144
143
|
form.appendChild(creqInput);
|
|
145
144
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
145
|
+
if (response_json.term_url) {
|
|
146
|
+
const termUrlInput = document.createElement('input');
|
|
147
|
+
termUrlInput.type = 'hidden';
|
|
148
|
+
termUrlInput.name = 'TermUrl';
|
|
149
|
+
termUrlInput.value = response_json.term_url;
|
|
150
|
+
form.appendChild(termUrlInput);
|
|
151
|
+
}
|
|
151
152
|
|
|
152
153
|
// Append the form to the body:
|
|
153
154
|
document.body.appendChild(form);
|
|
@@ -172,6 +173,14 @@ export class ThreeDSHandler {
|
|
|
172
173
|
}
|
|
173
174
|
|
|
174
175
|
async verifyTransactionStatus() {
|
|
176
|
+
console.log('Verificando la transacción...');
|
|
177
|
+
|
|
178
|
+
if (this.isTransactionPending) {
|
|
179
|
+
console.log('La transacción ya está en proceso');
|
|
180
|
+
return
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
this.isTransactionPending = true
|
|
175
184
|
const verifyUrl = this.getUrlWithExpiration();
|
|
176
185
|
|
|
177
186
|
if (verifyUrl) {
|
|
@@ -199,6 +208,8 @@ export class ThreeDSHandler {
|
|
|
199
208
|
} else {
|
|
200
209
|
console.log('No verify_transaction_status_url found');
|
|
201
210
|
}
|
|
211
|
+
|
|
212
|
+
this.isTransactionPending = false
|
|
202
213
|
}
|
|
203
214
|
|
|
204
215
|
setPayload = (payload) => {
|
|
@@ -34,6 +34,7 @@ export class BaseInlineCheckout {
|
|
|
34
34
|
*/
|
|
35
35
|
configureCheckout(data) {
|
|
36
36
|
if ("customer" in data) this.#handleCustomer(data["customer"]);
|
|
37
|
+
if ("secureToken" in data) this.#handleSecureToken(data["secureToken"]);
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
/**
|
|
@@ -265,6 +266,10 @@ export class BaseInlineCheckout {
|
|
|
265
266
|
this.customer = customer;
|
|
266
267
|
}
|
|
267
268
|
|
|
269
|
+
#handleSecureToken(secureToken) {
|
|
270
|
+
this.secureToken = secureToken;
|
|
271
|
+
}
|
|
272
|
+
|
|
268
273
|
#handleMetadata(data) {
|
|
269
274
|
this.metadata = data?.metadata;
|
|
270
275
|
}
|
|
@@ -282,23 +287,19 @@ export class BaseInlineCheckout {
|
|
|
282
287
|
}
|
|
283
288
|
|
|
284
289
|
async #handle3dsRedirect(response) {
|
|
290
|
+
console.log('Handling 3DS redirect...');
|
|
285
291
|
const iframe = response?.next_action?.iframe_resources?.iframe;
|
|
292
|
+
const threeDsChallenge = response?.next_action?.three_ds_challenge;
|
|
286
293
|
|
|
287
294
|
if (iframe) {
|
|
288
|
-
|
|
289
|
-
.loadIframe()
|
|
290
|
-
.
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
// }, 10000);
|
|
297
|
-
this.process3ds.verifyTransactionStatus();
|
|
298
|
-
})
|
|
299
|
-
.catch((error) => {
|
|
300
|
-
console.log("Error loading iframe:", error);
|
|
301
|
-
});
|
|
295
|
+
try {
|
|
296
|
+
await this.process3ds.loadIframe();
|
|
297
|
+
await this.process3ds.verifyTransactionStatus();
|
|
298
|
+
} catch (error) {
|
|
299
|
+
console.log("Error loading iframe:", error);
|
|
300
|
+
}
|
|
301
|
+
} else if (threeDsChallenge) {
|
|
302
|
+
await this.process3ds.handle3dsChallenge(threeDsChallenge);
|
|
302
303
|
} else {
|
|
303
304
|
const redirectUrl = this.process3ds.getRedirectUrl();
|
|
304
305
|
if (redirectUrl) {
|
|
@@ -63,14 +63,14 @@ export class InlineCheckout extends BaseInlineCheckout {
|
|
|
63
63
|
this.customStyles = styles
|
|
64
64
|
this.abortRefreshCardsController = new AbortController();
|
|
65
65
|
// TODO: Wait until SaveCards is ready (server token).
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
66
|
+
this.customization = {
|
|
67
|
+
...this.customization,
|
|
68
|
+
...(customization || {}),
|
|
69
|
+
saveCards: {
|
|
70
|
+
...this.customization.saveCards,
|
|
71
|
+
...(customization?.saveCards || {}),
|
|
72
|
+
},
|
|
73
|
+
}
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
#mountPayButton() {
|
|
@@ -295,9 +295,13 @@ export class InlineCheckout extends BaseInlineCheckout {
|
|
|
295
295
|
const saveCard = document.getElementById("save-checkout-card");
|
|
296
296
|
if ((saveCard && "checked" in saveCard && saveCard.checked) || !!this.customization.saveCards?.autoSave) {
|
|
297
297
|
try {
|
|
298
|
-
await saveCustomerCard(
|
|
299
|
-
|
|
300
|
-
|
|
298
|
+
await saveCustomerCard(
|
|
299
|
+
this.baseUrl,
|
|
300
|
+
auth_token,
|
|
301
|
+
this.secureToken,
|
|
302
|
+
businessId,
|
|
303
|
+
{ skyflow_id: cardTokens.skyflow_id, }
|
|
304
|
+
);
|
|
301
305
|
showMessage(MESSAGES.cardSaved, this.collectorIds.msgNotification);
|
|
302
306
|
} catch (error) {
|
|
303
307
|
if (error?.message) {
|
|
@@ -314,6 +318,7 @@ export class InlineCheckout extends BaseInlineCheckout {
|
|
|
314
318
|
const cardsResponse = await fetchCustomerCards(
|
|
315
319
|
this.baseUrl,
|
|
316
320
|
token,
|
|
321
|
+
this.secureToken,
|
|
317
322
|
this.merchantData.business.pk,
|
|
318
323
|
);
|
|
319
324
|
let cards = []
|
|
@@ -400,7 +405,13 @@ export class InlineCheckout extends BaseInlineCheckout {
|
|
|
400
405
|
this.abortRefreshCardsController = new AbortController();
|
|
401
406
|
}
|
|
402
407
|
const businessId = this.merchantData.business.pk
|
|
403
|
-
await removeCustomerCard(
|
|
408
|
+
await removeCustomerCard(
|
|
409
|
+
this.baseUrl,
|
|
410
|
+
customerToken,
|
|
411
|
+
this.secureToken,
|
|
412
|
+
skyflow_id,
|
|
413
|
+
businessId
|
|
414
|
+
)
|
|
404
415
|
} catch (error) { } finally {
|
|
405
416
|
this.deletingCards = this.deletingCards.filter(id => id !== skyflow_id);
|
|
406
417
|
this.#refreshCardOnDelete(customerToken)
|
package/src/data/cardApi.js
CHANGED
|
@@ -11,6 +11,7 @@ import {MESSAGES} from "../shared/constants/messages";
|
|
|
11
11
|
*
|
|
12
12
|
* @param {string} baseUrl - The base URL of the API.
|
|
13
13
|
* @param {string} customerToken - The customer's authentication token.
|
|
14
|
+
* @param {string} secureToken - Token generated by secure-token endpoint.
|
|
14
15
|
* @param {string | number} businessId - The business ID.
|
|
15
16
|
* @param {import("../../types").ISaveCardSkyflowRequest} data - The card information to be saved.
|
|
16
17
|
* @returns {Promise<import("../../types").ISaveCardResponse>} The saved card data.
|
|
@@ -20,6 +21,7 @@ import {MESSAGES} from "../shared/constants/messages";
|
|
|
20
21
|
export async function saveCustomerCard(
|
|
21
22
|
baseUrl,
|
|
22
23
|
customerToken,
|
|
24
|
+
secureToken,
|
|
23
25
|
businessId,
|
|
24
26
|
data,
|
|
25
27
|
) {
|
|
@@ -28,7 +30,8 @@ export async function saveCustomerCard(
|
|
|
28
30
|
const response = await fetch(url, {
|
|
29
31
|
method: "POST",
|
|
30
32
|
headers: {
|
|
31
|
-
Authorization: `
|
|
33
|
+
Authorization: `Bearer ${secureToken}`,
|
|
34
|
+
"User-Token": customerToken,
|
|
32
35
|
"Content-Type": "application/json",
|
|
33
36
|
},
|
|
34
37
|
body: JSON.stringify(data),
|
|
@@ -57,6 +60,7 @@ export async function saveCustomerCard(
|
|
|
57
60
|
* Removes a customer's card.
|
|
58
61
|
* @param {string} baseUrl - The base URL of the API.
|
|
59
62
|
* @param {string} customerToken - The customer's authentication token.
|
|
63
|
+
* @param {string} secureToken - Token generated by secure-token endpoint.
|
|
60
64
|
* @param {string} skyflowId - The Skyflow ID of the card to be removed.
|
|
61
65
|
* @param {string} businessId - The business ID.
|
|
62
66
|
* @returns {Promise<string>} The result of the card removal operation.
|
|
@@ -66,6 +70,7 @@ export async function saveCustomerCard(
|
|
|
66
70
|
export async function removeCustomerCard(
|
|
67
71
|
baseUrl,
|
|
68
72
|
customerToken,
|
|
73
|
+
secureToken,
|
|
69
74
|
skyflowId = "",
|
|
70
75
|
businessId,
|
|
71
76
|
) {
|
|
@@ -75,8 +80,9 @@ export async function removeCustomerCard(
|
|
|
75
80
|
const response = await fetch(url, {
|
|
76
81
|
method: "DELETE",
|
|
77
82
|
headers: {
|
|
78
|
-
Authorization: `
|
|
83
|
+
Authorization: `Bearer ${secureToken}`,
|
|
79
84
|
"Content-Type": "application/json",
|
|
85
|
+
"User-Token": customerToken,
|
|
80
86
|
},
|
|
81
87
|
});
|
|
82
88
|
|
|
@@ -94,6 +100,7 @@ export async function removeCustomerCard(
|
|
|
94
100
|
* Fetches a customer's saved cards.
|
|
95
101
|
* @param {string} baseUrl - The base URL of the API.
|
|
96
102
|
* @param {string} customerToken - The customer's authentication token.
|
|
103
|
+
* @param {string} secureToken - Token generated by secure-token endpoint.
|
|
97
104
|
* @param {string} businessId - The business ID.
|
|
98
105
|
* @param {AbortSignal} signal - The abort signal to cancel the request.
|
|
99
106
|
* @returns {Promise<import("../../types").ICustomerCardsResponse>} The customer's saved cards.
|
|
@@ -103,6 +110,7 @@ export async function removeCustomerCard(
|
|
|
103
110
|
export async function fetchCustomerCards(
|
|
104
111
|
baseUrl,
|
|
105
112
|
customerToken,
|
|
113
|
+
secureToken,
|
|
106
114
|
businessId,
|
|
107
115
|
signal= null,
|
|
108
116
|
) {
|
|
@@ -111,12 +119,21 @@ export async function fetchCustomerCards(
|
|
|
111
119
|
const response = await fetch(url, {
|
|
112
120
|
method: "GET",
|
|
113
121
|
headers: {
|
|
114
|
-
Authorization: `
|
|
115
|
-
"
|
|
122
|
+
Authorization: `Bearer ${secureToken}`,
|
|
123
|
+
"User-Token": customerToken,
|
|
116
124
|
},
|
|
117
125
|
signal,
|
|
118
126
|
});
|
|
119
127
|
if (response.ok) return await response.json();
|
|
128
|
+
if (response.status === 401) {
|
|
129
|
+
return {
|
|
130
|
+
code: 401,
|
|
131
|
+
body: {},
|
|
132
|
+
name: "",
|
|
133
|
+
message: "Unauthorized",
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
120
137
|
const res_json = await response.json();
|
|
121
138
|
|
|
122
139
|
throw await buildErrorResponse(response, res_json, MESSAGES.getCardsError);
|
package/src/index-dev.js
CHANGED
|
@@ -113,7 +113,6 @@ const commonConfig = {
|
|
|
113
113
|
styles: customStyles,
|
|
114
114
|
};
|
|
115
115
|
|
|
116
|
-
let checkout;
|
|
117
116
|
let inlineCheckout;
|
|
118
117
|
let liteInlineCheckout;
|
|
119
118
|
|
|
@@ -133,7 +132,10 @@ function setupInlineCheckout() {
|
|
|
133
132
|
},
|
|
134
133
|
},
|
|
135
134
|
});
|
|
136
|
-
inlineCheckout.configureCheckout({
|
|
135
|
+
inlineCheckout.configureCheckout({
|
|
136
|
+
customer: checkoutData.customer,
|
|
137
|
+
secureToken: "eyJhbGc..."
|
|
138
|
+
});
|
|
137
139
|
inlineCheckout.injectCheckout();
|
|
138
140
|
// ['Declined', 'Cancelled', 'Failed', 'Success', 'Pending', 'Authorized']
|
|
139
141
|
inlineCheckout.verify3dsTransaction().then((response) => {
|
|
@@ -159,7 +161,10 @@ function setupInlineCheckout() {
|
|
|
159
161
|
function setupLiteInlineCheckout() {
|
|
160
162
|
loadMaskitoMask();
|
|
161
163
|
liteInlineCheckout = new LiteInlineCheckout(commonConfig);
|
|
162
|
-
liteInlineCheckout.configureCheckout({
|
|
164
|
+
liteInlineCheckout.configureCheckout({
|
|
165
|
+
customer: checkoutData.customer,
|
|
166
|
+
secureToken: "eyJhbGc..."
|
|
167
|
+
});
|
|
163
168
|
liteInlineCheckout.injectCheckout().then(() => {});
|
|
164
169
|
liteInlineCheckout.verify3dsTransaction().then((response) => {
|
|
165
170
|
console.log("Verify 3ds response", response);
|