@tonder.io/ionic-full-sdk 0.0.48-beta.DEV-1610.2 → 0.0.49-beta.DEV-1630.1
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 +169 -7
- package/dist/classes/inlineCheckout.d.ts +1 -1
- package/dist/helpers/skyflow.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/types/commons.d.ts +21 -0
- package/package.json +2 -2
- package/src/classes/inlineCheckout.ts +13 -12
- package/src/helpers/skyflow.ts +58 -3
- package/src/helpers/utils.ts +0 -1
- package/src/types/commons.ts +20 -0
- package/src/classes/3dsHandler.ts +0 -326
package/src/helpers/skyflow.ts
CHANGED
|
@@ -4,8 +4,8 @@ import Skyflow from "skyflow-js";
|
|
|
4
4
|
import { CollectorIds } from "./template";
|
|
5
5
|
import RevealElement from "skyflow-js/types/core/external/reveal/reveal-element";
|
|
6
6
|
import ComposableElement from "skyflow-js/types/core/external/collect/compose-collect-element";
|
|
7
|
-
import { InCollectorContainer
|
|
8
|
-
import
|
|
7
|
+
import {IEvents, IInputEvents, InCollectorContainer} from "../types/commons";
|
|
8
|
+
import get from "lodash.get";
|
|
9
9
|
|
|
10
10
|
export async function initSkyflow(
|
|
11
11
|
vaultId: string,
|
|
@@ -15,6 +15,7 @@ export async function initSkyflow(
|
|
|
15
15
|
customStyles: any = {},
|
|
16
16
|
collectorIds: CollectorIds,
|
|
17
17
|
apiKey: string,
|
|
18
|
+
events?: IEvents
|
|
18
19
|
): Promise<InCollectorContainer> {
|
|
19
20
|
const skyflow = await initializeSkyflow(
|
|
20
21
|
vaultId,
|
|
@@ -74,6 +75,8 @@ export async function initSkyflow(
|
|
|
74
75
|
|
|
75
76
|
if ("on" in cardHolderNameElement) {
|
|
76
77
|
cardHolderNameElement.on(Skyflow.EventName.CHANGE, (state: any) => {
|
|
78
|
+
executeEvent( "onChange", state, events?.cardHolderEvents)
|
|
79
|
+
|
|
77
80
|
let element = document.getElementById("errorCardHolderIdTonder");
|
|
78
81
|
|
|
79
82
|
if (element && state.isValid && !state.isEmpty) {
|
|
@@ -82,6 +85,8 @@ export async function initSkyflow(
|
|
|
82
85
|
});
|
|
83
86
|
|
|
84
87
|
cardHolderNameElement.on(Skyflow.EventName.BLUR, (state: any) => {
|
|
88
|
+
executeEvent( "onBlur", state, events?.cardHolderEvents)
|
|
89
|
+
|
|
85
90
|
let tonderContainer = document.getElementById(collectorIds.holderName);
|
|
86
91
|
|
|
87
92
|
let element = document.getElementById("errorCardHolderIdTonder");
|
|
@@ -100,6 +105,11 @@ export async function initSkyflow(
|
|
|
100
105
|
tonderContainer?.appendChild(errorLabel);
|
|
101
106
|
}
|
|
102
107
|
});
|
|
108
|
+
|
|
109
|
+
cardHolderNameElement.on(Skyflow.EventName.FOCUS, (state: any) => {
|
|
110
|
+
executeEvent( "onFocus", state, events?.cardHolderEvents)
|
|
111
|
+
});
|
|
112
|
+
|
|
103
113
|
}
|
|
104
114
|
|
|
105
115
|
// Create collect elements.
|
|
@@ -120,6 +130,7 @@ export async function initSkyflow(
|
|
|
120
130
|
|
|
121
131
|
if ("on" in cardNumberElement) {
|
|
122
132
|
cardNumberElement.on(Skyflow.EventName.CHANGE, (state: any) => {
|
|
133
|
+
executeEvent( "onChange", state, events?.cardNumberEvents)
|
|
123
134
|
let element = document.getElementById("errorCardNumberIdTonder");
|
|
124
135
|
|
|
125
136
|
if (element && state.isValid && !state.isEmpty) {
|
|
@@ -128,6 +139,8 @@ export async function initSkyflow(
|
|
|
128
139
|
});
|
|
129
140
|
|
|
130
141
|
cardNumberElement.on(Skyflow.EventName.BLUR, (state: any) => {
|
|
142
|
+
executeEvent( "onBlur", state, events?.cardNumberEvents)
|
|
143
|
+
|
|
131
144
|
let tonderContainer = document.getElementById(collectorIds.cardNumber);
|
|
132
145
|
|
|
133
146
|
let element = document.getElementById("errorCardNumberIdTonder");
|
|
@@ -146,6 +159,11 @@ export async function initSkyflow(
|
|
|
146
159
|
tonderContainer?.appendChild(errorLabel);
|
|
147
160
|
}
|
|
148
161
|
});
|
|
162
|
+
|
|
163
|
+
cardNumberElement.on(Skyflow.EventName.FOCUS, (state: any) => {
|
|
164
|
+
executeEvent( "onFocus", state, events?.cardNumberEvents)
|
|
165
|
+
});
|
|
166
|
+
|
|
149
167
|
}
|
|
150
168
|
|
|
151
169
|
const cvvElement: CollectElement | RevealElement | ComposableElement =
|
|
@@ -161,6 +179,7 @@ export async function initSkyflow(
|
|
|
161
179
|
|
|
162
180
|
if ("on" in cvvElement) {
|
|
163
181
|
cvvElement.on(Skyflow.EventName.CHANGE, (state: any) => {
|
|
182
|
+
executeEvent( "onChange", state, events?.cvvEvents)
|
|
164
183
|
let element = document.getElementById("errorCvvIdTonder");
|
|
165
184
|
|
|
166
185
|
if (element && state.isValid && !state.isEmpty) {
|
|
@@ -169,6 +188,7 @@ export async function initSkyflow(
|
|
|
169
188
|
});
|
|
170
189
|
|
|
171
190
|
cvvElement.on(Skyflow.EventName.BLUR, (state: any) => {
|
|
191
|
+
executeEvent( "onBlur", state, events?.cvvEvents)
|
|
172
192
|
let tonderContainer = document.getElementById(collectorIds.cvv);
|
|
173
193
|
|
|
174
194
|
let element = document.getElementById("errorCvvIdTonder");
|
|
@@ -187,6 +207,10 @@ export async function initSkyflow(
|
|
|
187
207
|
tonderContainer?.appendChild(errorLabel);
|
|
188
208
|
}
|
|
189
209
|
});
|
|
210
|
+
|
|
211
|
+
cvvElement.on(Skyflow.EventName.FOCUS, (state: any) => {
|
|
212
|
+
executeEvent( "onFocus", state, events?.cvvEvents)
|
|
213
|
+
});
|
|
190
214
|
}
|
|
191
215
|
|
|
192
216
|
const expiryMonthElement: CollectElement | RevealElement | ComposableElement = collectContainer.create({
|
|
@@ -201,6 +225,7 @@ export async function initSkyflow(
|
|
|
201
225
|
|
|
202
226
|
if ("on" in expiryMonthElement) {
|
|
203
227
|
expiryMonthElement.on(Skyflow.EventName.CHANGE, (state: any) => {
|
|
228
|
+
executeEvent( "onChange", state, events?.monthEvents)
|
|
204
229
|
let element = document.getElementById("errorExpiryMonthIdTonder");
|
|
205
230
|
|
|
206
231
|
if (element && state.isValid && !state.isEmpty) {
|
|
@@ -209,6 +234,7 @@ export async function initSkyflow(
|
|
|
209
234
|
});
|
|
210
235
|
|
|
211
236
|
expiryMonthElement.on(Skyflow.EventName.BLUR, (state: any) => {
|
|
237
|
+
executeEvent( "onBlur", state, events?.monthEvents)
|
|
212
238
|
let tonderContainer = document.getElementById(
|
|
213
239
|
collectorIds.expirationMonth,
|
|
214
240
|
);
|
|
@@ -229,8 +255,11 @@ export async function initSkyflow(
|
|
|
229
255
|
tonderContainer?.appendChild(errorLabel);
|
|
230
256
|
}
|
|
231
257
|
});
|
|
258
|
+
|
|
259
|
+
expiryMonthElement.on(Skyflow.EventName.FOCUS, (state: any) => {
|
|
260
|
+
executeEvent( "onFocus", state, events?.monthEvents)
|
|
261
|
+
});
|
|
232
262
|
}
|
|
233
|
-
console.log("collectStylesOptions ====", collectStylesOptions)
|
|
234
263
|
|
|
235
264
|
const expiryYearElement: CollectElement | RevealElement | ComposableElement = collectContainer.create({
|
|
236
265
|
table: "cards",
|
|
@@ -244,6 +273,7 @@ export async function initSkyflow(
|
|
|
244
273
|
|
|
245
274
|
if ("on" in expiryYearElement) {
|
|
246
275
|
expiryYearElement.on(Skyflow.EventName.CHANGE, (state: any) => {
|
|
276
|
+
executeEvent( "onChange", state, events?.yearEvents)
|
|
247
277
|
let element = document.getElementById("errorExpiryYearIdTonder");
|
|
248
278
|
|
|
249
279
|
if (element && state.isValid && !state.isEmpty) {
|
|
@@ -252,6 +282,7 @@ export async function initSkyflow(
|
|
|
252
282
|
});
|
|
253
283
|
|
|
254
284
|
expiryYearElement.on(Skyflow.EventName.BLUR, (state: any) => {
|
|
285
|
+
executeEvent( "onBlur", state, events?.yearEvents)
|
|
255
286
|
let tonderContainer = document.getElementById(
|
|
256
287
|
collectorIds.expirationYear,
|
|
257
288
|
);
|
|
@@ -272,6 +303,10 @@ export async function initSkyflow(
|
|
|
272
303
|
tonderContainer?.appendChild(errorLabel);
|
|
273
304
|
}
|
|
274
305
|
});
|
|
306
|
+
|
|
307
|
+
expiryYearElement.on(Skyflow.EventName.FOCUS, (state: any) => {
|
|
308
|
+
executeEvent( "onFocus", state, events?.yearEvents)
|
|
309
|
+
});
|
|
275
310
|
}
|
|
276
311
|
|
|
277
312
|
const elementsConfig = {
|
|
@@ -320,6 +355,7 @@ export async function initUpdateSkyflow(
|
|
|
320
355
|
customStyles: any = {},
|
|
321
356
|
collectorIds: CollectorIds,
|
|
322
357
|
apiKey: string,
|
|
358
|
+
events?: IEvents
|
|
323
359
|
) {
|
|
324
360
|
const skyflow = await initializeSkyflow(
|
|
325
361
|
vaultId,
|
|
@@ -365,6 +401,7 @@ export async function initUpdateSkyflow(
|
|
|
365
401
|
|
|
366
402
|
if ("on" in cvvElement) {
|
|
367
403
|
cvvElement.on(Skyflow.EventName.CHANGE, (state: any) => {
|
|
404
|
+
executeEvent( "onChange", state, events?.cvvEvents)
|
|
368
405
|
let element = document.getElementById(`errorCvvIdTonder${skyflowId}`);
|
|
369
406
|
|
|
370
407
|
if (element && state.isValid && !state.isEmpty) {
|
|
@@ -373,6 +410,7 @@ export async function initUpdateSkyflow(
|
|
|
373
410
|
});
|
|
374
411
|
|
|
375
412
|
cvvElement.on(Skyflow.EventName.BLUR, (state: any) => {
|
|
413
|
+
executeEvent( "onBlur", state, events?.cvvEvents)
|
|
376
414
|
let tonderContainer = document.getElementById(
|
|
377
415
|
collectorIds.cvv + skyflowId,
|
|
378
416
|
);
|
|
@@ -393,6 +431,10 @@ export async function initUpdateSkyflow(
|
|
|
393
431
|
tonderContainer?.appendChild(errorLabel);
|
|
394
432
|
}
|
|
395
433
|
});
|
|
434
|
+
|
|
435
|
+
cvvElement.on(Skyflow.EventName.FOCUS, (state: any) => {
|
|
436
|
+
executeEvent( "onFocus", state, events?.cvvEvents)
|
|
437
|
+
});
|
|
396
438
|
}
|
|
397
439
|
|
|
398
440
|
const elementsConfig = {
|
|
@@ -473,3 +515,16 @@ const regexMatchRule = {
|
|
|
473
515
|
error: "El campo es requerido",
|
|
474
516
|
},
|
|
475
517
|
};
|
|
518
|
+
const executeEvent = (eventName: "onChange" | "onBlur" | "onFocus", data: any, events?: IInputEvents, ) => {
|
|
519
|
+
if (events && eventName in events){
|
|
520
|
+
const eventHandler = events[eventName];
|
|
521
|
+
if (typeof eventHandler === "function") {
|
|
522
|
+
eventHandler({
|
|
523
|
+
elementType: get(data, "elementType",""),
|
|
524
|
+
isEmpty: get(data, "isEmpty",""),
|
|
525
|
+
isFocused: get(data, "isFocused",""),
|
|
526
|
+
isValid: get(data, "isValid",""),
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
package/src/helpers/utils.ts
CHANGED
|
@@ -61,7 +61,6 @@ export function showError(
|
|
|
61
61
|
msgErrorText!.innerHTML = "";
|
|
62
62
|
msgErrorText!.innerHTML = message;
|
|
63
63
|
msgErrorDiv!.style.display = "flex";
|
|
64
|
-
console.log("msgErrorDiv", msgErrorDiv)
|
|
65
64
|
setTimeout(function () {
|
|
66
65
|
msgErrorDiv!.style.display = "none";
|
|
67
66
|
msgErrorText!.innerHTML = "";
|
package/src/types/commons.ts
CHANGED
|
@@ -94,11 +94,31 @@ export interface IInlineCustomizationOptions extends CustomizationOptions {
|
|
|
94
94
|
autoSave?: boolean;
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
|
+
export interface IEventSecureInput {
|
|
98
|
+
elementType: string;
|
|
99
|
+
isEmpty: boolean;
|
|
100
|
+
isFocused: boolean;
|
|
101
|
+
isValid: boolean;
|
|
102
|
+
}
|
|
103
|
+
export interface IInputEvents {
|
|
104
|
+
onChange?: (event: IEventSecureInput) => void;
|
|
105
|
+
onFocus?: (event: IEventSecureInput) => void;
|
|
106
|
+
onBlur?: (event: IEventSecureInput) => void;
|
|
107
|
+
}
|
|
97
108
|
|
|
109
|
+
export interface ICardFormEvents {
|
|
110
|
+
cardHolderEvents?: IInputEvents;
|
|
111
|
+
cardNumberEvents?: IInputEvents;
|
|
112
|
+
cvvEvents?: IInputEvents;
|
|
113
|
+
monthEvents?: IInputEvents;
|
|
114
|
+
yearEvents?: IInputEvents;
|
|
115
|
+
}
|
|
116
|
+
export interface IEvents extends ICardFormEvents {}
|
|
98
117
|
export interface IInlineCheckoutOptions extends IInlineCheckoutBaseOptions{
|
|
99
118
|
styles?: Record<string, string>;
|
|
100
119
|
renderPaymentButton?: boolean;
|
|
101
120
|
customization?: IInlineCustomizationOptions;
|
|
121
|
+
events?: IEvents;
|
|
102
122
|
renderSaveCardButton?: boolean,
|
|
103
123
|
containerId?: string,
|
|
104
124
|
collectorIds?: CollectorIds,
|
|
@@ -1,326 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import {CustomizationOptions} from "@tonder.io/ionic-lite-sdk/dist/types/commons";
|
|
3
|
-
|
|
4
|
-
type ThreeDSHandlerContructor = {
|
|
5
|
-
payload?: any,
|
|
6
|
-
apiKey?: string,
|
|
7
|
-
baseUrl?: string,
|
|
8
|
-
customization?: CustomizationOptions,
|
|
9
|
-
tdsIframeId?: string,
|
|
10
|
-
callBack?: (params: any) => any
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export class ThreeDSHandler {
|
|
14
|
-
|
|
15
|
-
baseUrl?: string
|
|
16
|
-
apiKey?: string
|
|
17
|
-
payload?: any
|
|
18
|
-
localStorageKey: string = "verify_transaction_status_url"
|
|
19
|
-
customization?: CustomizationOptions
|
|
20
|
-
callBack?: (params: any) => any
|
|
21
|
-
tdsIframeId?: string
|
|
22
|
-
|
|
23
|
-
constructor({
|
|
24
|
-
payload = null,
|
|
25
|
-
apiKey,
|
|
26
|
-
baseUrl,
|
|
27
|
-
customization,
|
|
28
|
-
tdsIframeId,
|
|
29
|
-
callBack
|
|
30
|
-
}: ThreeDSHandlerContructor) {
|
|
31
|
-
this.baseUrl = baseUrl,
|
|
32
|
-
this.apiKey = apiKey,
|
|
33
|
-
this.payload = payload
|
|
34
|
-
this.customization = customization
|
|
35
|
-
this.tdsIframeId = tdsIframeId
|
|
36
|
-
this.callBack = callBack;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
setStorageItem (data: any) {
|
|
40
|
-
return localStorage.setItem(this.localStorageKey, JSON.stringify(data))
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
getStorageItem () {
|
|
44
|
-
return localStorage.getItem(this.localStorageKey)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
removeStorageItem () {
|
|
48
|
-
return localStorage.removeItem(this.localStorageKey)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
saveVerifyTransactionUrl() {
|
|
52
|
-
const url = this.payload?.next_action?.redirect_to_url?.verify_transaction_status_url
|
|
53
|
-
if (url) {
|
|
54
|
-
this.saveUrlWithExpiration(url)
|
|
55
|
-
} else {
|
|
56
|
-
const url = this.payload?.next_action?.iframe_resources?.verify_transaction_status_url
|
|
57
|
-
if (url) {
|
|
58
|
-
this.saveUrlWithExpiration(url)
|
|
59
|
-
} else {
|
|
60
|
-
console.log('No verify_transaction_status_url found');
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
saveUrlWithExpiration(url: string) {
|
|
66
|
-
try {
|
|
67
|
-
const now = new Date()
|
|
68
|
-
const item = {
|
|
69
|
-
url: url,
|
|
70
|
-
// Expires after 20 minutes
|
|
71
|
-
expires: now.getTime() + 20 * 60 * 1000
|
|
72
|
-
}
|
|
73
|
-
this.setStorageItem(item)
|
|
74
|
-
} catch (error) {
|
|
75
|
-
console.log('error: ', error)
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
getUrlWithExpiration() {
|
|
80
|
-
const status = this.getStorageItem();
|
|
81
|
-
if(status) {
|
|
82
|
-
const item = JSON.parse(status)
|
|
83
|
-
if (!item) return
|
|
84
|
-
const now = new Date()
|
|
85
|
-
if (now.getTime() > item.expires) {
|
|
86
|
-
this.removeVerifyTransactionUrl()
|
|
87
|
-
return null
|
|
88
|
-
} else {
|
|
89
|
-
return item.url
|
|
90
|
-
}
|
|
91
|
-
} else {
|
|
92
|
-
return null
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
removeVerifyTransactionUrl() {
|
|
97
|
-
return this.removeStorageItem()
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
getVerifyTransactionUrl() {
|
|
101
|
-
return this.getStorageItem()
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
loadIframe() {
|
|
105
|
-
const iframe = this.payload?.next_action?.iframe_resources?.iframe
|
|
106
|
-
|
|
107
|
-
if (iframe) {
|
|
108
|
-
return new Promise((resolve, reject) => {
|
|
109
|
-
const iframe = this.payload?.next_action?.iframe_resources?.iframe
|
|
110
|
-
|
|
111
|
-
if (iframe) {
|
|
112
|
-
this.saveVerifyTransactionUrl()
|
|
113
|
-
const container = document.createElement('div')
|
|
114
|
-
container.innerHTML = iframe
|
|
115
|
-
document.body.appendChild(container)
|
|
116
|
-
|
|
117
|
-
// Create and append the script tag manually
|
|
118
|
-
const script = document.createElement('script')
|
|
119
|
-
script.textContent = 'document.getElementById("tdsMmethodForm").submit();'
|
|
120
|
-
container.appendChild(script)
|
|
121
|
-
|
|
122
|
-
// Resolve the promise when the iframe is loaded
|
|
123
|
-
const iframeElement = document.getElementById('tdsMmethodTgtFrame')
|
|
124
|
-
if(iframeElement) {
|
|
125
|
-
iframeElement.onload = () => resolve(true)
|
|
126
|
-
} else {
|
|
127
|
-
console.log('No redirection found');
|
|
128
|
-
reject(false)
|
|
129
|
-
}
|
|
130
|
-
} else {
|
|
131
|
-
console.log('No redirection found');
|
|
132
|
-
reject(false)
|
|
133
|
-
}
|
|
134
|
-
})
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
getRedirectUrl() {
|
|
139
|
-
return this.payload?.next_action?.redirect_to_url?.url
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
redirectToChallenge() {
|
|
143
|
-
const url = this.getRedirectUrl()
|
|
144
|
-
if (url) {
|
|
145
|
-
this.saveVerifyTransactionUrl()
|
|
146
|
-
if(this.customization) {
|
|
147
|
-
if(this.customization?.redirectOnComplete) {
|
|
148
|
-
window.location = url;
|
|
149
|
-
} else {
|
|
150
|
-
const iframe = document.querySelector(`#${this.tdsIframeId}`)
|
|
151
|
-
if(iframe) {
|
|
152
|
-
|
|
153
|
-
iframe.setAttribute("src", url);
|
|
154
|
-
iframe.setAttribute("style", "display: block");
|
|
155
|
-
|
|
156
|
-
const self = this;
|
|
157
|
-
|
|
158
|
-
const listenerHandler = async (event: any) => {
|
|
159
|
-
|
|
160
|
-
const checkStatus = (result: any) => result?.transaction_status !== "Pending";
|
|
161
|
-
|
|
162
|
-
const executeAction = () => {
|
|
163
|
-
if(iframe) {
|
|
164
|
-
iframe.setAttribute("style", "display: none");
|
|
165
|
-
}
|
|
166
|
-
if(self.callBack) self.callBack(self.payload);
|
|
167
|
-
iframe.removeEventListener("load", listenerHandler);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const chainPromises = async (promise: Promise<any>) => {
|
|
171
|
-
const result = await new Promise((resolve, reject) => resolve(promise))
|
|
172
|
-
if(result) {
|
|
173
|
-
if(checkStatus(result)) {
|
|
174
|
-
return executeAction()
|
|
175
|
-
} else {
|
|
176
|
-
const timer = setTimeout(async () => {
|
|
177
|
-
clearTimeout(timer);
|
|
178
|
-
await chainPromises(self.requestTransactionStatus());
|
|
179
|
-
}, 5000)
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
await chainPromises(self.requestTransactionStatus())
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
iframe.addEventListener("load", listenerHandler)
|
|
188
|
-
|
|
189
|
-
} else {
|
|
190
|
-
console.log('No iframe found');
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
} else {
|
|
194
|
-
window.location = url;
|
|
195
|
-
}
|
|
196
|
-
} else {
|
|
197
|
-
console.log('No redirection found');
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Returns an object
|
|
202
|
-
// https://example.com/?name=John&age=30&city=NewYork
|
|
203
|
-
// { name: "John", age: "30", city: "NewYork" }
|
|
204
|
-
getURLParameters() {
|
|
205
|
-
const parameters: any = {};
|
|
206
|
-
const urlParams: any = new URLSearchParams(window.location.search);
|
|
207
|
-
|
|
208
|
-
for (const [key, value] of urlParams) {
|
|
209
|
-
parameters[key] = value;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
return parameters;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
handleSuccessTransaction(response: any) {
|
|
216
|
-
this.removeVerifyTransactionUrl();
|
|
217
|
-
console.log('Transacción autorizada.');
|
|
218
|
-
return response;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
handleDeclinedTransaction(response: any) {
|
|
222
|
-
this.removeVerifyTransactionUrl();
|
|
223
|
-
return response;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// TODO: the method below needs to be tested with a real 3DS challenge
|
|
227
|
-
// since we couldn't get a test card that works with this feature
|
|
228
|
-
async handle3dsChallenge(response_json: any) {
|
|
229
|
-
// Create the form element:
|
|
230
|
-
const form = document.createElement('form');
|
|
231
|
-
form.name = 'frm';
|
|
232
|
-
form.method = 'POST';
|
|
233
|
-
form.action = response_json.redirect_post_url;
|
|
234
|
-
|
|
235
|
-
// Add hidden fields:
|
|
236
|
-
const creqInput = document.createElement('input');
|
|
237
|
-
creqInput.type = 'hidden';
|
|
238
|
-
creqInput.name = response_json.creq;
|
|
239
|
-
creqInput.value = response_json.creq;
|
|
240
|
-
form.appendChild(creqInput);
|
|
241
|
-
|
|
242
|
-
const termUrlInput = document.createElement('input');
|
|
243
|
-
termUrlInput.type = 'hidden';
|
|
244
|
-
termUrlInput.name = response_json.term_url;
|
|
245
|
-
termUrlInput.value = response_json.TermUrl;
|
|
246
|
-
form.appendChild(termUrlInput);
|
|
247
|
-
|
|
248
|
-
// Append the form to the body:
|
|
249
|
-
document.body.appendChild(form);
|
|
250
|
-
form.submit();
|
|
251
|
-
|
|
252
|
-
await this.verifyTransactionStatus();
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// TODO: This method could be removed
|
|
256
|
-
async handleTransactionResponse(response: any) {
|
|
257
|
-
const response_json = await response.json();
|
|
258
|
-
if (response_json.status === "Pending" && response_json.redirect_post_url) {
|
|
259
|
-
return await this.handle3dsChallenge(response_json);
|
|
260
|
-
} else if (["Success", "Authorized"].includes(response_json.status)) {
|
|
261
|
-
return this.handleSuccessTransaction(response_json);
|
|
262
|
-
} else {
|
|
263
|
-
this.handleDeclinedTransaction(response);
|
|
264
|
-
return response_json
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
async requestTransactionStatus() {
|
|
269
|
-
|
|
270
|
-
const verifyUrl = this.getUrlWithExpiration();
|
|
271
|
-
console.log('verifyUrls: ', verifyUrl);
|
|
272
|
-
const url = verifyUrl.startsWith("https://") ? verifyUrl : `${this.baseUrl}${verifyUrl}`;
|
|
273
|
-
const response = await fetch(url, {
|
|
274
|
-
method: "GET",
|
|
275
|
-
headers: {
|
|
276
|
-
"Content-Type": "application/json",
|
|
277
|
-
Authorization: `Token ${this.apiKey}`,
|
|
278
|
-
},
|
|
279
|
-
// body: JSON.stringify(data),
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
if (response.status !== 200) {
|
|
283
|
-
console.error('La verificación de la transacción falló.');
|
|
284
|
-
return null;
|
|
285
|
-
} else {
|
|
286
|
-
const response_json = await response.json();
|
|
287
|
-
return response_json;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
async verifyTransactionStatus() {
|
|
293
|
-
const verifyUrl = this.getUrlWithExpiration();
|
|
294
|
-
|
|
295
|
-
if (verifyUrl) {
|
|
296
|
-
const url = verifyUrl.startsWith("https://") ? verifyUrl : `${this.baseUrl}${verifyUrl}`;
|
|
297
|
-
try {
|
|
298
|
-
const response = await fetch(url, {
|
|
299
|
-
method: "GET",
|
|
300
|
-
headers: {
|
|
301
|
-
"Content-Type": "application/json",
|
|
302
|
-
Authorization: `Token ${this.apiKey}`,
|
|
303
|
-
},
|
|
304
|
-
// body: JSON.stringify(data),
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
if (response.status !== 200) {
|
|
308
|
-
console.error('La verificación de la transacción falló.');
|
|
309
|
-
this.removeVerifyTransactionUrl();
|
|
310
|
-
return response
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
return await this.handleTransactionResponse(response);
|
|
314
|
-
} catch (error) {
|
|
315
|
-
console.error('Error al verificar la transacción:', error);
|
|
316
|
-
this.removeVerifyTransactionUrl();
|
|
317
|
-
}
|
|
318
|
-
} else {
|
|
319
|
-
console.log('No verify_transaction_status_url found');
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
setPayload = (payload: any) => {
|
|
324
|
-
this.payload = payload
|
|
325
|
-
}
|
|
326
|
-
}
|