@tonder.io/ionic-full-sdk 0.0.33-beta → 0.0.35-beta
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 +10 -1
- package/dist/classes/3dsHandler.d.ts +5 -1
- package/dist/classes/inlineCheckout.d.ts +7 -1
- package/dist/helpers/skyflow.d.ts +1 -1
- package/dist/helpers/template.d.ts +6 -1
- package/dist/index.js +1 -1
- package/dist/types/commons.d.ts +14 -0
- package/package.json +2 -2
- package/src/classes/3dsHandler.ts +26 -8
- package/src/classes/inlineCheckout.ts +105 -46
- package/src/helpers/template.ts +182 -4
- package/src/index-dev.js +3 -1
- package/src/types/commons.ts +16 -0
package/dist/types/commons.d.ts
CHANGED
|
@@ -39,3 +39,17 @@ export type PaymentData = {
|
|
|
39
39
|
items: OrderItem[];
|
|
40
40
|
};
|
|
41
41
|
};
|
|
42
|
+
export type TonderAPM = {
|
|
43
|
+
pk: string;
|
|
44
|
+
payment_method: string;
|
|
45
|
+
priority: number;
|
|
46
|
+
category: string;
|
|
47
|
+
unavailable_countries: string[];
|
|
48
|
+
status: string;
|
|
49
|
+
};
|
|
50
|
+
export type APM = {
|
|
51
|
+
id: string;
|
|
52
|
+
payment_method: string;
|
|
53
|
+
priority: number;
|
|
54
|
+
category: string;
|
|
55
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tonder.io/ionic-full-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.35-beta",
|
|
4
4
|
"description": "Tonder ionic full SDK",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.js",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"author": "",
|
|
11
11
|
"license": "ISC",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@tonder.io/ionic-lite-sdk": "^0.0.
|
|
13
|
+
"@tonder.io/ionic-lite-sdk": "^0.0.34-beta",
|
|
14
14
|
"crypto-js": "^4.1.1",
|
|
15
15
|
"skyflow-js": "^1.34.1"
|
|
16
16
|
},
|
|
@@ -65,6 +65,19 @@ export class ThreeDSHandler {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
saveCheckoutId(checkoutId: any) {
|
|
69
|
+
localStorage.setItem('checkout_id', JSON.stringify(checkoutId))
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
removeCheckoutId() {
|
|
73
|
+
localStorage.removeItem("checkout_id")
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
getCurrentCheckoutId() {
|
|
77
|
+
const checkout_id = localStorage.getItem("checkout_id")
|
|
78
|
+
return checkout_id ? JSON.parse(checkout_id):null; // TODO: JSON.parse de una string?
|
|
79
|
+
}
|
|
80
|
+
|
|
68
81
|
getUrlWithExpiration() {
|
|
69
82
|
const status = this.getStorageItem();
|
|
70
83
|
if(status) {
|
|
@@ -154,14 +167,13 @@ export class ThreeDSHandler {
|
|
|
154
167
|
|
|
155
168
|
handleSuccessTransaction(response: any) {
|
|
156
169
|
this.removeVerifyTransactionUrl();
|
|
157
|
-
console.log('Transacción autorizada
|
|
170
|
+
console.log('Transacción autorizada.');
|
|
158
171
|
return response;
|
|
159
172
|
}
|
|
160
173
|
|
|
161
174
|
handleDeclinedTransaction(response: any) {
|
|
162
175
|
this.removeVerifyTransactionUrl();
|
|
163
|
-
|
|
164
|
-
throw new Error("Transacción rechazada.");
|
|
176
|
+
return response;
|
|
165
177
|
}
|
|
166
178
|
|
|
167
179
|
// TODO: the method below needs to be tested with a real 3DS challenge
|
|
@@ -193,14 +205,16 @@ export class ThreeDSHandler {
|
|
|
193
205
|
await this.verifyTransactionStatus();
|
|
194
206
|
}
|
|
195
207
|
|
|
208
|
+
// TODO: This method could be removed
|
|
196
209
|
async handleTransactionResponse(response: any) {
|
|
197
210
|
const response_json = await response.json();
|
|
198
|
-
if (response_json.status === "Pending") {
|
|
211
|
+
if (response_json.status === "Pending" && response_json.redirect_post_url) {
|
|
199
212
|
return await this.handle3dsChallenge(response_json);
|
|
200
213
|
} else if (["Success", "Authorized"].includes(response_json.status)) {
|
|
201
|
-
return this.handleSuccessTransaction(
|
|
214
|
+
return this.handleSuccessTransaction(response_json);
|
|
202
215
|
} else {
|
|
203
|
-
|
|
216
|
+
this.handleDeclinedTransaction(response);
|
|
217
|
+
return response_json
|
|
204
218
|
}
|
|
205
219
|
}
|
|
206
220
|
|
|
@@ -221,17 +235,21 @@ export class ThreeDSHandler {
|
|
|
221
235
|
|
|
222
236
|
if (response.status !== 200) {
|
|
223
237
|
console.error('La verificación de la transacción falló.');
|
|
224
|
-
|
|
238
|
+
this.removeVerifyTransactionUrl();
|
|
239
|
+
return response
|
|
225
240
|
}
|
|
226
241
|
|
|
227
242
|
return await this.handleTransactionResponse(response);
|
|
228
243
|
} catch (error) {
|
|
229
244
|
console.error('Error al verificar la transacción:', error);
|
|
230
|
-
|
|
245
|
+
this.removeVerifyTransactionUrl();
|
|
231
246
|
}
|
|
232
247
|
} else {
|
|
233
248
|
console.log('No verify_transaction_status_url found');
|
|
234
249
|
}
|
|
235
250
|
}
|
|
236
251
|
|
|
252
|
+
setPayload = (payload: any) => {
|
|
253
|
+
this.payload = payload
|
|
254
|
+
}
|
|
237
255
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Card, cardItemsTemplate, cardTemplate, CollectorIds } from '../helpers/template'
|
|
1
|
+
import { apmItemsTemplate, Card, cardItemsTemplate, cardTemplate, CollectorIds } from '../helpers/template'
|
|
2
2
|
import { LiteCheckout } from '@tonder.io/ionic-lite-sdk';
|
|
3
3
|
import {
|
|
4
4
|
showError,
|
|
@@ -13,6 +13,7 @@ import { Business, Customer, PaymentData, OrderItem } from '@tonder.io/ionic-lit
|
|
|
13
13
|
import { CustomerRegisterResponse, StartCheckoutResponse } from '@tonder.io/ionic-lite-sdk/dist/types/responses';
|
|
14
14
|
import { StartCheckoutRequest, CreatePaymentRequest, CreateOrderRequest } from '@tonder.io/ionic-lite-sdk/dist/types/requests';
|
|
15
15
|
import { InCollectorContainer } from '../helpers/skyflow';
|
|
16
|
+
import { APM } from 'src/types/commons';
|
|
16
17
|
|
|
17
18
|
export type InlineCheckoutConstructor = {
|
|
18
19
|
returnUrl: string,
|
|
@@ -59,6 +60,8 @@ export class InlineCheckout {
|
|
|
59
60
|
containerId: string
|
|
60
61
|
injected: boolean
|
|
61
62
|
cardsInjected: boolean
|
|
63
|
+
apmsInjected = false
|
|
64
|
+
apmsData: APM[] = []
|
|
62
65
|
collectorIds: CollectorIds
|
|
63
66
|
platforms?: string[]
|
|
64
67
|
liteCheckout: LiteCheckout
|
|
@@ -118,7 +121,8 @@ export class InlineCheckout {
|
|
|
118
121
|
tonderPayButton: "tonderPayButton",
|
|
119
122
|
msgError: "msgError",
|
|
120
123
|
msgNotification: "msgNotification",
|
|
121
|
-
tonderSaveCardButton: "tonderSaveCardButton"
|
|
124
|
+
tonderSaveCardButton: "tonderSaveCardButton",
|
|
125
|
+
apmsListContainer: "apmsListContainer"
|
|
122
126
|
}
|
|
123
127
|
this.clientCards = []
|
|
124
128
|
this.radioChecked = "new"
|
|
@@ -172,7 +176,7 @@ export class InlineCheckout {
|
|
|
172
176
|
if (!this.renderSaveCardButton) return;
|
|
173
177
|
|
|
174
178
|
const saveButton: HTMLElement | null = document.querySelector(`#${this.collectorIds.tonderSaveCardButton}`);
|
|
175
|
-
|
|
179
|
+
|
|
176
180
|
if (!saveButton) {
|
|
177
181
|
console.error("Save button not found");
|
|
178
182
|
return;
|
|
@@ -180,9 +184,9 @@ export class InlineCheckout {
|
|
|
180
184
|
|
|
181
185
|
|
|
182
186
|
saveButton.style.display = "block";
|
|
183
|
-
|
|
187
|
+
|
|
184
188
|
saveButton.textContent = `Guardar`;
|
|
185
|
-
|
|
189
|
+
|
|
186
190
|
saveButton.onclick = async (event) => {
|
|
187
191
|
event.preventDefault();
|
|
188
192
|
await this.#handleSaveCardClick(saveButton);
|
|
@@ -215,6 +219,31 @@ export class InlineCheckout {
|
|
|
215
219
|
this.card = data?.card
|
|
216
220
|
}
|
|
217
221
|
|
|
222
|
+
async handle3dsRedirect(response: ErrorResponse | StartCheckoutResponse | false | undefined) {
|
|
223
|
+
const iframe = response && 'next_action' in response ? response?.next_action?.iframe_resources?.iframe:null
|
|
224
|
+
|
|
225
|
+
if (iframe) {
|
|
226
|
+
this.process3ds.loadIframe()!.then(() => {
|
|
227
|
+
//TODO: Check if this will be necessary on the frontend side
|
|
228
|
+
// after some the tests in production, since the 3DS process
|
|
229
|
+
// doesn't works properly on the sandbox environment
|
|
230
|
+
// setTimeout(() => {
|
|
231
|
+
// process3ds.verifyTransactionStatus();
|
|
232
|
+
// }, 10000);
|
|
233
|
+
this.process3ds.verifyTransactionStatus();
|
|
234
|
+
}).catch((error) => {
|
|
235
|
+
console.log('Error loading iframe:', error)
|
|
236
|
+
})
|
|
237
|
+
} else {
|
|
238
|
+
const redirectUrl = this.process3ds.getRedirectUrl()
|
|
239
|
+
if (redirectUrl) {
|
|
240
|
+
this.process3ds.redirectToChallenge()
|
|
241
|
+
} else {
|
|
242
|
+
return response;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
218
247
|
payment(data: any) {
|
|
219
248
|
return new Promise(async (resolve, reject) => {
|
|
220
249
|
try {
|
|
@@ -225,37 +254,12 @@ export class InlineCheckout {
|
|
|
225
254
|
this.#handleCurrency(data)
|
|
226
255
|
this.#handleCard(data)
|
|
227
256
|
const response: ErrorResponse | StartCheckoutResponse | false | undefined = await this.#checkout()
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
});
|
|
235
|
-
this.callBack(response);
|
|
236
|
-
if("next_action" in response) {
|
|
237
|
-
const iframe = response?.next_action?.iframe_resources?.iframe
|
|
238
|
-
if (iframe) {
|
|
239
|
-
process3ds.loadIframe()?.then(() => {
|
|
240
|
-
//TODO: Check if this will be necessary on the frontend side
|
|
241
|
-
// after some the tests in production, since the 3DS process
|
|
242
|
-
// doesn't works properly on the sandbox environment
|
|
243
|
-
// setTimeout(() => {
|
|
244
|
-
// process3ds.verifyTransactionStatus();
|
|
245
|
-
// }, 10000);
|
|
246
|
-
process3ds.verifyTransactionStatus();
|
|
247
|
-
}).catch((error) => {
|
|
248
|
-
console.log('Error loading iframe:', error)
|
|
249
|
-
})
|
|
250
|
-
} else {
|
|
251
|
-
const redirectUrl = process3ds.getRedirectUrl()
|
|
252
|
-
if (redirectUrl) {
|
|
253
|
-
process3ds.redirectToChallenge()
|
|
254
|
-
} else {
|
|
255
|
-
resolve(response);
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
}
|
|
257
|
+
this.process3ds.setPayload(response)
|
|
258
|
+
this.process3ds.saveCheckoutId(response && 'checkout_id' in response ? response.checkout_id:"")
|
|
259
|
+
this.callBack(response);
|
|
260
|
+
const payload = await this.handle3dsRedirect(response)
|
|
261
|
+
if (payload) {
|
|
262
|
+
resolve(response);
|
|
259
263
|
}
|
|
260
264
|
} catch (error) {
|
|
261
265
|
reject(error);
|
|
@@ -263,7 +267,7 @@ export class InlineCheckout {
|
|
|
263
267
|
});
|
|
264
268
|
}
|
|
265
269
|
|
|
266
|
-
#mountRadioButtons (token: string) {
|
|
270
|
+
#mountRadioButtons (token: string = "") {
|
|
267
271
|
const radioButtons: NodeListOf<HTMLElement> = document.getElementsByName(`card_selected`);
|
|
268
272
|
for (const radio of radioButtons) {
|
|
269
273
|
radio.style.display = "block";
|
|
@@ -358,11 +362,10 @@ export class InlineCheckout {
|
|
|
358
362
|
|
|
359
363
|
injectCheckout() {
|
|
360
364
|
if (this.injected) return
|
|
361
|
-
this.process3ds.verifyTransactionStatus()
|
|
362
365
|
const injectInterval = setInterval(() => {
|
|
363
366
|
const queryElement = document.querySelector(`#${this.containerId}`)
|
|
364
367
|
if (queryElement) {
|
|
365
|
-
queryElement.innerHTML = cardTemplate(this.customStyles ? true : false, this.collectorIds, this.isEnrollmentCard)
|
|
368
|
+
queryElement.innerHTML = cardTemplate(this.customStyles ? true : false, this.collectorIds, this.isEnrollmentCard, { renderPaymentButton: this.renderPaymentButton })
|
|
366
369
|
this.#mountTonder();
|
|
367
370
|
clearInterval(injectInterval);
|
|
368
371
|
this.injected = true
|
|
@@ -370,6 +373,30 @@ export class InlineCheckout {
|
|
|
370
373
|
}, 500);
|
|
371
374
|
}
|
|
372
375
|
|
|
376
|
+
async verify3dsTransaction () {
|
|
377
|
+
const result3ds = await this.process3ds.verifyTransactionStatus()
|
|
378
|
+
const resultCheckout = await this.resumeCheckout(result3ds)
|
|
379
|
+
this.process3ds.setPayload(resultCheckout)
|
|
380
|
+
if (resultCheckout && 'is_route_finished' in resultCheckout && 'provider' in resultCheckout && resultCheckout.provider === 'tonder') {
|
|
381
|
+
return resultCheckout
|
|
382
|
+
}
|
|
383
|
+
return this.handle3dsRedirect(resultCheckout)
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
async resumeCheckout(response: any) {
|
|
387
|
+
if (["Failed", "Declined", "Cancelled"].includes(response?.status)) {
|
|
388
|
+
const routerItems = {
|
|
389
|
+
// TODO: Replace this with reponse.checkout_id
|
|
390
|
+
checkout_id: this.process3ds.getCurrentCheckoutId(),
|
|
391
|
+
};
|
|
392
|
+
const routerResponse = await this.liteCheckout.handleCheckoutRouter(
|
|
393
|
+
routerItems
|
|
394
|
+
);
|
|
395
|
+
return routerResponse
|
|
396
|
+
}
|
|
397
|
+
return response
|
|
398
|
+
}
|
|
399
|
+
|
|
373
400
|
loadCardsList (cards: Card[], token: string) {
|
|
374
401
|
if(this.cardsInjected) return;
|
|
375
402
|
const injectInterval = setInterval(() => {
|
|
@@ -392,6 +419,31 @@ export class InlineCheckout {
|
|
|
392
419
|
return await this.liteCheckout.customerRegister(email);
|
|
393
420
|
}
|
|
394
421
|
|
|
422
|
+
async #mountAPMs(){
|
|
423
|
+
try{
|
|
424
|
+
const apms: APM[] = await this.liteCheckout.getActiveAPMs();
|
|
425
|
+
if(apms.length > 0){
|
|
426
|
+
this.apmsData = apms;
|
|
427
|
+
this.#loadAPMList(apms)
|
|
428
|
+
}
|
|
429
|
+
}catch(e){
|
|
430
|
+
console.warn("Error getting APMS")
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
#loadAPMList(apms: APM[]) {
|
|
435
|
+
if (this.apmsInjected) return;
|
|
436
|
+
const injectInterval = setInterval(() => {
|
|
437
|
+
const queryElement = document.querySelector(`#${this.collectorIds.apmsListContainer}`);
|
|
438
|
+
if (queryElement && this.injected) {
|
|
439
|
+
queryElement.innerHTML = apmItemsTemplate(this.customStyles ? true : false, apms);
|
|
440
|
+
clearInterval(injectInterval);
|
|
441
|
+
this.#mountRadioButtons();
|
|
442
|
+
this.apmsInjected = true;
|
|
443
|
+
}
|
|
444
|
+
}, 500);
|
|
445
|
+
}
|
|
446
|
+
|
|
395
447
|
async #mountTonder() {
|
|
396
448
|
if(this.isEnrollmentCard){
|
|
397
449
|
this.#mountSaveCardButton()
|
|
@@ -426,6 +478,8 @@ export class InlineCheckout {
|
|
|
426
478
|
}
|
|
427
479
|
|
|
428
480
|
}
|
|
481
|
+
|
|
482
|
+
await this.#mountAPMs();
|
|
429
483
|
|
|
430
484
|
this.collectContainer = await initSkyflow(
|
|
431
485
|
vault_id,
|
|
@@ -445,6 +499,7 @@ export class InlineCheckout {
|
|
|
445
499
|
|
|
446
500
|
this.injected = false
|
|
447
501
|
this.cardsInjected = false
|
|
502
|
+
this.apmsInjected = false
|
|
448
503
|
// Cancel all requests
|
|
449
504
|
this.abortController.abort();
|
|
450
505
|
this.abortController = new AbortController();
|
|
@@ -490,7 +545,6 @@ export class InlineCheckout {
|
|
|
490
545
|
}
|
|
491
546
|
|
|
492
547
|
async #getCardTokens(tonderButton: string){
|
|
493
|
-
console.log("this.collectContainer: ", this.collectContainer)
|
|
494
548
|
if(this.collectContainer && "container" in this.collectContainer && "collect" in this.collectContainer.container) {
|
|
495
549
|
try {
|
|
496
550
|
const collectResponseSkyflowTonder: any = await this.collectContainer?.container.collect();
|
|
@@ -507,7 +561,7 @@ export class InlineCheckout {
|
|
|
507
561
|
try {
|
|
508
562
|
|
|
509
563
|
const selector: any = document.querySelector(`#${this.collectorIds.tonderSaveCardButton}`);
|
|
510
|
-
|
|
564
|
+
|
|
511
565
|
if(selector){
|
|
512
566
|
selector.disabled = disabled;
|
|
513
567
|
selector.innerHTML = text
|
|
@@ -522,7 +576,7 @@ export class InlineCheckout {
|
|
|
522
576
|
if(this.merchantData && "openpay_keys" in this.merchantData) {
|
|
523
577
|
const cardTokensSkyflowTonder: any = await this.#getCardTokens(this.collectorIds.tonderSaveCardButton!);
|
|
524
578
|
const customerResponse : CustomerRegisterResponse | ErrorResponse = await this.getCustomer(this.email);
|
|
525
|
-
|
|
579
|
+
|
|
526
580
|
if("auth_token" in customerResponse) {
|
|
527
581
|
const { auth_token, id: cutomerId } = customerResponse;
|
|
528
582
|
console.log("cardTokensSkyflowTonder: ", cardTokensSkyflowTonder)
|
|
@@ -674,10 +728,11 @@ export class InlineCheckout {
|
|
|
674
728
|
const jsonResponsePayment = await this.liteCheckout.createPayment(
|
|
675
729
|
paymentItems
|
|
676
730
|
);
|
|
677
|
-
|
|
731
|
+
|
|
732
|
+
const selected_apm: APM | undefined | null = this.apmsData ? this.apmsData.find((iapm) => iapm.id === this.radioChecked):null;
|
|
733
|
+
|
|
678
734
|
// Checkout router
|
|
679
735
|
const routerItems: StartCheckoutRequest = {
|
|
680
|
-
card: cardTokensSkyflowTonder,
|
|
681
736
|
name: this.firstName,
|
|
682
737
|
last_name: this.lastName ?? "",
|
|
683
738
|
email_client: this.email,
|
|
@@ -698,10 +753,14 @@ export class InlineCheckout {
|
|
|
698
753
|
source: 'sdk',
|
|
699
754
|
metadata: this.metadata,
|
|
700
755
|
browser_info: getBrowserInfo(),
|
|
701
|
-
currency: this.currency
|
|
756
|
+
currency: this.currency,
|
|
757
|
+
...( !!selected_apm
|
|
758
|
+
? {payment_method: selected_apm.payment_method}
|
|
759
|
+
: {card: cardTokensSkyflowTonder}
|
|
760
|
+
)
|
|
702
761
|
};
|
|
703
762
|
|
|
704
|
-
const jsonResponseRouter = await this.liteCheckout.
|
|
763
|
+
const jsonResponseRouter = await this.liteCheckout.handleCheckoutRouter(
|
|
705
764
|
routerItems
|
|
706
765
|
);
|
|
707
766
|
|
package/src/helpers/template.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { APM } from 'src/types/commons';
|
|
1
2
|
import { getCardType } from './utils';
|
|
3
|
+
import { getPaymentMethodDetails } from '@tonder.io/ionic-lite-sdk/dist/helpers/utils';
|
|
2
4
|
|
|
3
5
|
export type CollectorIds = {
|
|
4
6
|
holderName: string,
|
|
@@ -10,7 +12,8 @@ export type CollectorIds = {
|
|
|
10
12
|
tonderSaveCardButton?: string,
|
|
11
13
|
msgError: string,
|
|
12
14
|
msgNotification: string,
|
|
13
|
-
cardsListContainer: string
|
|
15
|
+
cardsListContainer: string,
|
|
16
|
+
apmsListContainer?: string
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
export type Card = {
|
|
@@ -22,7 +25,7 @@ export type Card = {
|
|
|
22
25
|
skyflow_id: string
|
|
23
26
|
}
|
|
24
27
|
|
|
25
|
-
export const cardTemplate = (external: boolean, collectorIds: CollectorIds, isEnrollmentCard: boolean = false) => `
|
|
28
|
+
export const cardTemplate = (external: boolean, collectorIds: CollectorIds, isEnrollmentCard: boolean = false, data: {renderPaymentButton?: boolean} = {}) => `
|
|
26
29
|
<div class="container-tonder">
|
|
27
30
|
<div id="${collectorIds.cardsListContainer}" class="cards-list-container"></div>
|
|
28
31
|
${!isEnrollmentCard ? `
|
|
@@ -53,8 +56,11 @@ export const cardTemplate = (external: boolean, collectorIds: CollectorIds, isEn
|
|
|
53
56
|
<div id="${collectorIds.msgError}"></div>
|
|
54
57
|
<div id="${collectorIds.msgNotification}"></div>
|
|
55
58
|
</div>
|
|
56
|
-
<
|
|
57
|
-
<
|
|
59
|
+
<div id="apmsListContainer" class="apms-list-container"></div>
|
|
60
|
+
<div class="container-pay-button">
|
|
61
|
+
<button id="${collectorIds.tonderPayButton}" class="pay-button">Pagar</button>
|
|
62
|
+
<button id="${collectorIds.tonderSaveCardButton ? collectorIds.tonderSaveCardButton:''}" class="save-card-button">Guardar</button>
|
|
63
|
+
</div>
|
|
58
64
|
</div>
|
|
59
65
|
|
|
60
66
|
${external ? `` : `<style>
|
|
@@ -93,6 +99,10 @@ ${external ? `` : `<style>
|
|
|
93
99
|
border: solid 1px #e3e3e3;
|
|
94
100
|
}
|
|
95
101
|
|
|
102
|
+
.container-pay-button{
|
|
103
|
+
padding: ${!!data['renderPaymentButton'] ? '30px 25px':''};
|
|
104
|
+
}
|
|
105
|
+
|
|
96
106
|
.collect-row {
|
|
97
107
|
display: flex !important;
|
|
98
108
|
justify-content: space-between !important;
|
|
@@ -224,6 +234,14 @@ ${external ? `` : `<style>
|
|
|
224
234
|
gap: 33% 20px;
|
|
225
235
|
}
|
|
226
236
|
|
|
237
|
+
.apms-list-container {
|
|
238
|
+
display: flex;
|
|
239
|
+
flex-direction: column;
|
|
240
|
+
gap: 33% 20px;
|
|
241
|
+
max-height: 300px;
|
|
242
|
+
overflow-y: auto;
|
|
243
|
+
}
|
|
244
|
+
|
|
227
245
|
.checkbox label {
|
|
228
246
|
margin-left: 10px;
|
|
229
247
|
font-size: '12px';
|
|
@@ -518,4 +536,164 @@ export const cardItemsTemplate = (external: boolean, cards: Card[]) => {
|
|
|
518
536
|
${cardItemStyle}
|
|
519
537
|
`
|
|
520
538
|
return cardItem;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
export const apmItemsTemplate = (external: boolean, apms: APM[]) => {
|
|
542
|
+
|
|
543
|
+
const apmItemsHTML = apms.reduce((_, apm) => {
|
|
544
|
+
const apm_data = getPaymentMethodDetails(apm.payment_method);
|
|
545
|
+
return `
|
|
546
|
+
<div class="apm-item" id="card_container-${apm.id}">
|
|
547
|
+
<input id="${apm.id}" class="card_selected" name="card_selected" type="radio"/>
|
|
548
|
+
<label class="apm-item-label" for="${apm.id}">
|
|
549
|
+
<div class="apm-image">
|
|
550
|
+
<div class="apm-image-border"></div>
|
|
551
|
+
<img src="${apm_data.icon}" />
|
|
552
|
+
</div>
|
|
553
|
+
<div class="apm-name">${apm_data.label}</div>
|
|
554
|
+
</label>
|
|
555
|
+
</div>`
|
|
556
|
+
}, ``);
|
|
557
|
+
|
|
558
|
+
const apmItemStyle = external ? '' :`
|
|
559
|
+
<style>
|
|
560
|
+
.apm-item-label {
|
|
561
|
+
display: flex;
|
|
562
|
+
justify-content: flex-start;
|
|
563
|
+
align-items: center;
|
|
564
|
+
color: #1D1D1D;
|
|
565
|
+
gap: 33% 10px;
|
|
566
|
+
margin-top: 15px;
|
|
567
|
+
margin-bottom: 15px;
|
|
568
|
+
width: 100%;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
.apm-item {
|
|
572
|
+
position: relative;
|
|
573
|
+
display: flex;
|
|
574
|
+
justify-content: start;
|
|
575
|
+
align-items: center;
|
|
576
|
+
gap: 33% 15px;
|
|
577
|
+
border-bottom: 1px solid #e2e8f0;
|
|
578
|
+
padding: 0px 30px;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
.apm-item:first-child {
|
|
582
|
+
border-top: 1px solid #e2e8f0;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
.apm-item .apm-name {
|
|
586
|
+
font-size: 16px;
|
|
587
|
+
}
|
|
588
|
+
.apm-image {
|
|
589
|
+
width: 30px;
|
|
590
|
+
height: 30px;
|
|
591
|
+
position: relative;
|
|
592
|
+
display: flex;
|
|
593
|
+
justify-content: center;
|
|
594
|
+
align-items: center;
|
|
595
|
+
}
|
|
596
|
+
.apm-image img {
|
|
597
|
+
width: auto;
|
|
598
|
+
height: 30px;
|
|
599
|
+
}
|
|
600
|
+
.apm-image-border{
|
|
601
|
+
position: absolute;
|
|
602
|
+
border: 1px solid #bababa36;
|
|
603
|
+
border-radius: 4px;
|
|
604
|
+
pointer-events: none;
|
|
605
|
+
box-sizing: border-box;
|
|
606
|
+
width: 100%;
|
|
607
|
+
height: 97%;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
.card_selected {
|
|
611
|
+
position: relative;
|
|
612
|
+
width: 16px;
|
|
613
|
+
min-width: 16px;
|
|
614
|
+
height: 16px;
|
|
615
|
+
appearance: none;
|
|
616
|
+
cursor: pointer;
|
|
617
|
+
border-radius: 100%;
|
|
618
|
+
border: 1px #bababa solid;
|
|
619
|
+
color: #3bc635;
|
|
620
|
+
transition-property: all;
|
|
621
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
622
|
+
transition-duration: 150ms;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
.card_selected:before {
|
|
626
|
+
width: 8px;
|
|
627
|
+
height: 8px;
|
|
628
|
+
content: "";
|
|
629
|
+
position: absolute;
|
|
630
|
+
top: 50%;
|
|
631
|
+
left: 50%;
|
|
632
|
+
display: block;
|
|
633
|
+
transform: translate(-50%, -50%);
|
|
634
|
+
border-radius: 100%;
|
|
635
|
+
background-color: #3bc635;
|
|
636
|
+
opacity: 0;
|
|
637
|
+
transition-property: opacity;
|
|
638
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
639
|
+
transition-duration: 150ms;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
.card_selected:checked {
|
|
643
|
+
border: 1px #3bc635 solid;
|
|
644
|
+
position: relative;
|
|
645
|
+
width: 16px;
|
|
646
|
+
height: 16px;
|
|
647
|
+
min-width: 16px;
|
|
648
|
+
appearance: none;
|
|
649
|
+
cursor: pointer;
|
|
650
|
+
border-radius: 100%;
|
|
651
|
+
color: #3bc635;
|
|
652
|
+
transition-property: all;
|
|
653
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
654
|
+
transition-duration: 150ms;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
.card_selected:checked:before {
|
|
658
|
+
content: "";
|
|
659
|
+
border: 1px #3bc635 solid;
|
|
660
|
+
width: 8px;
|
|
661
|
+
height: 8px;
|
|
662
|
+
position: absolute;
|
|
663
|
+
top: 50%;
|
|
664
|
+
left: 50%;
|
|
665
|
+
display: block;
|
|
666
|
+
transform: translate(-50%, -50%);
|
|
667
|
+
border-radius: 100%;
|
|
668
|
+
background-color: #3bc635;
|
|
669
|
+
opacity: 50;
|
|
670
|
+
transition-property: opacity;
|
|
671
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
672
|
+
transition-duration: 150ms;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
.card_selected:hover:before {
|
|
676
|
+
width: 8px;
|
|
677
|
+
height: 8px;
|
|
678
|
+
content: "";
|
|
679
|
+
position: absolute;
|
|
680
|
+
top: 50%;
|
|
681
|
+
left: 50%;
|
|
682
|
+
display: block;
|
|
683
|
+
transform: translate(-50%, -50%);
|
|
684
|
+
border-radius: 100%;
|
|
685
|
+
background-color: #3bc635;
|
|
686
|
+
transition-property: opacity;
|
|
687
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
688
|
+
transition-duration: 150ms;
|
|
689
|
+
opacity: 10;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
</style>
|
|
693
|
+
`
|
|
694
|
+
const apmItem = `
|
|
695
|
+
${apmItemsHTML}
|
|
696
|
+
${apmItemStyle}
|
|
697
|
+
`
|
|
698
|
+
return apmItem;
|
|
521
699
|
}
|
package/src/index-dev.js
CHANGED
|
@@ -102,7 +102,9 @@ const inlineCheckout = new InlineCheckout({
|
|
|
102
102
|
});
|
|
103
103
|
|
|
104
104
|
inlineCheckout.injectCheckout();
|
|
105
|
-
|
|
105
|
+
inlineCheckout.verify3dsTransaction().then(response => {
|
|
106
|
+
console.log('Verify 3ds response', response)
|
|
107
|
+
})
|
|
106
108
|
document.addEventListener('DOMContentLoaded', function() {
|
|
107
109
|
const payButton = document.getElementById('pay-button');
|
|
108
110
|
payButton.addEventListener('click', async function() {
|
package/src/types/commons.ts
CHANGED
|
@@ -41,4 +41,20 @@ export type PaymentData = {
|
|
|
41
41
|
total: string | number,
|
|
42
42
|
items: OrderItem[]
|
|
43
43
|
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type TonderAPM = {
|
|
47
|
+
pk: string;
|
|
48
|
+
payment_method: string;
|
|
49
|
+
priority: number;
|
|
50
|
+
category: string;
|
|
51
|
+
unavailable_countries: string[];
|
|
52
|
+
status: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export type APM = {
|
|
56
|
+
id: string;
|
|
57
|
+
payment_method: string;
|
|
58
|
+
priority: number;
|
|
59
|
+
category: string;
|
|
44
60
|
}
|