@tonder.io/ionic-lite-sdk 0.0.35-beta.8 → 0.0.37-beta.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.
Files changed (83) hide show
  1. package/.gitlab-ci.yml +28 -28
  2. package/README.md +532 -202
  3. package/dist/classes/BaseInlineCheckout.d.ts +21 -19
  4. package/dist/classes/errorResponse.d.ts +1 -1
  5. package/dist/classes/liteCheckout.d.ts +15 -43
  6. package/dist/data/api.d.ts +1 -1
  7. package/dist/data/businessApi.d.ts +1 -1
  8. package/dist/data/cardApi.d.ts +1 -1
  9. package/dist/data/checkoutApi.d.ts +2 -1
  10. package/dist/data/customerApi.d.ts +1 -1
  11. package/dist/data/paymentMethodApi.d.ts +2 -2
  12. package/dist/helpers/skyflow.d.ts +1 -1
  13. package/dist/index.d.ts +2 -1
  14. package/dist/index.js +1 -1
  15. package/dist/types/card.d.ts +1 -0
  16. package/dist/types/checkout.d.ts +7 -1
  17. package/dist/types/commons.d.ts +8 -3
  18. package/dist/types/customer.d.ts +10 -0
  19. package/{src → dist}/types/liteInlineCheckout.d.ts +33 -73
  20. package/dist/types/responses.d.ts +3 -0
  21. package/jest.config.ts +14 -14
  22. package/package.json +41 -38
  23. package/rollup.config.js +16 -16
  24. package/src/classes/3dsHandler.ts +237 -237
  25. package/src/classes/BaseInlineCheckout.ts +385 -356
  26. package/src/classes/errorResponse.ts +16 -16
  27. package/src/classes/liteCheckout.ts +588 -598
  28. package/src/data/api.ts +20 -20
  29. package/src/data/businessApi.ts +18 -18
  30. package/src/data/cardApi.ts +85 -89
  31. package/src/data/checkoutApi.ts +84 -87
  32. package/src/data/customerApi.ts +31 -31
  33. package/src/data/openPayApi.ts +12 -12
  34. package/src/data/paymentMethodApi.ts +37 -37
  35. package/src/data/skyflowApi.ts +20 -20
  36. package/src/helpers/constants.ts +63 -63
  37. package/src/helpers/mercadopago.ts +15 -15
  38. package/src/helpers/skyflow.ts +91 -91
  39. package/src/helpers/utils.ts +120 -120
  40. package/src/helpers/validations.ts +55 -55
  41. package/src/index.ts +12 -10
  42. package/src/shared/catalog/paymentMethodsCatalog.ts +247 -247
  43. package/src/shared/constants/messages.ts +10 -10
  44. package/src/shared/constants/paymentMethodAPM.ts +63 -63
  45. package/src/shared/constants/tonderUrl.ts +8 -8
  46. package/src/types/card.ts +35 -34
  47. package/src/types/checkout.ts +123 -117
  48. package/src/types/commons.ts +130 -125
  49. package/src/types/customer.ts +22 -12
  50. package/src/types/liteInlineCheckout.ts +216 -0
  51. package/src/types/paymentMethod.ts +23 -23
  52. package/src/types/requests.ts +114 -114
  53. package/src/types/responses.ts +193 -189
  54. package/src/types/skyflow.ts +17 -17
  55. package/src/types/transaction.ts +101 -101
  56. package/src/types/validations.d.ts +11 -11
  57. package/tests/classes/liteCheckout.test.ts +57 -57
  58. package/tests/methods/createOrder.test.ts +141 -142
  59. package/tests/methods/createPayment.test.ts +121 -122
  60. package/tests/methods/customerRegister.test.ts +118 -119
  61. package/tests/methods/getBusiness.test.ts +114 -115
  62. package/tests/methods/getCustomerCards.test.ts +112 -113
  63. package/tests/methods/registerCustomerCard.test.ts +117 -117
  64. package/tests/methods/startCheckoutRouter.test.ts +119 -119
  65. package/tests/methods/startCheckoutRouterFull.test.ts +138 -138
  66. package/tests/utils/defaultMock.ts +21 -21
  67. package/tests/utils/mockClasses.ts +659 -659
  68. package/tsconfig.json +18 -18
  69. package/types/classes/liteCheckout.d.ts +29 -0
  70. package/types/classes/liteCheckout.js +225 -0
  71. package/types/classes/liteCheckout.js.map +1 -0
  72. package/types/helpers/utils.d.ts +3 -0
  73. package/types/helpers/utils.js +27 -0
  74. package/types/helpers/utils.js.map +1 -0
  75. package/types/index.d.ts +2 -0
  76. package/types/index.js +6 -0
  77. package/types/index.js.map +1 -0
  78. package/.idea/aws.xml +0 -17
  79. package/.idea/inspectionProfiles/Project_Default.xml +0 -6
  80. package/.idea/prettier.xml +0 -6
  81. package/.idea/vcs.xml +0 -6
  82. package/.idea/workspace.xml +0 -133
  83. package/src/types/index.d.ts +0 -10
@@ -1,598 +1,588 @@
1
- import { fetchBusiness } from "../data/businessApi";
2
-
3
- declare const MP_DEVICE_SESSION_ID: string | undefined;
4
- import { ErrorResponse } from "./errorResponse";
5
- import {
6
- buildErrorResponse,
7
- buildErrorResponseFromCatch,
8
- getBrowserInfo,
9
- getBusinessId,
10
- formatPublicErrorResponse,
11
- getCardType,
12
- } from "../helpers/utils";
13
- import { getCustomerAPMs } from "../data/api";
14
- import { BaseInlineCheckout } from "./BaseInlineCheckout";
15
- import {
16
- fetchCustomerCards,
17
- removeCustomerCard,
18
- saveCustomerCard,
19
- } from "../data/cardApi";
20
- import { MESSAGES } from "../shared/constants/messages";
21
- import { getSkyflowTokens } from "../helpers/skyflow";
22
- import { fetchCustomerAPMs } from "../data/paymentMethodApi";
23
- import { startCheckoutRouter } from "../data/checkoutApi";
24
- import { getOpenpayDeviceSessionID } from "../data/openPayApi";
25
- import { getPaymentMethodDetails } from "../shared/catalog/paymentMethodsCatalog";
26
- import {
27
- APM,
28
- IInlineCheckoutBaseOptions,
29
- TonderAPM,
30
- RegisterCustomerCardResponse,
31
- ISaveCardRequest,
32
- ICustomerCardsResponse,
33
- ISaveCardResponse,
34
- IPaymentMethod,
35
- GetBusinessResponse,
36
- TokensRequest,
37
- ICardFields,
38
- CustomerRegisterResponse,
39
- StartCheckoutFullRequest,
40
- CreateOrderRequest,
41
- CreatePaymentRequest,
42
- StartCheckoutRequest,
43
- IErrorResponse,
44
- StartCheckoutResponse,
45
- StartCheckoutIdRequest,
46
- CreatePaymentResponse,
47
- CreateOrderResponse,
48
- RegisterCustomerCardRequest,
49
- } from "../types";
50
-
51
- declare global {
52
- interface Window {
53
- OpenPay: any;
54
- }
55
- }
56
-
57
- export interface LiteCheckoutConstructor extends IInlineCheckoutBaseOptions {}
58
-
59
- export class LiteCheckout extends BaseInlineCheckout {
60
- activeAPMs: APM[] = [];
61
-
62
- constructor({ apiKey, mode, returnUrl, callBack }: LiteCheckoutConstructor) {
63
- super({ mode, apiKey, returnUrl, callBack });
64
- }
65
-
66
- async injectCheckout() {
67
- await this._initializeCheckout();
68
- }
69
-
70
- async getCustomerCards(): Promise<ICustomerCardsResponse> {
71
- try {
72
- await this._fetchMerchantData();
73
- const { auth_token } = await this._getCustomer();
74
- const response = await fetchCustomerCards(
75
- this.baseUrl,
76
- auth_token,
77
- this.merchantData!.business.pk,
78
- );
79
-
80
- return {
81
- ...response,
82
- cards: response.cards.map((ic) => ({
83
- ...ic,
84
- icon: getCardType(ic.fields.card_scheme),
85
- })),
86
- };
87
- } catch (error) {
88
- throw formatPublicErrorResponse(
89
- {
90
- message: MESSAGES.getCardsError,
91
- },
92
- error,
93
- );
94
- }
95
- }
96
-
97
- async saveCustomerCard(card: ISaveCardRequest): Promise<ISaveCardResponse> {
98
- try {
99
- await this._fetchMerchantData();
100
- const { auth_token } = await this._getCustomer();
101
- const { vault_id, vault_url, business } = this.merchantData!;
102
-
103
- const skyflowTokens = await getSkyflowTokens({
104
- vault_id: vault_id,
105
- vault_url: vault_url,
106
- data: card,
107
- baseUrl: this.baseUrl,
108
- apiKey: this.apiKeyTonder,
109
- });
110
-
111
- return await saveCustomerCard(
112
- this.baseUrl,
113
- auth_token,
114
- business?.pk,
115
- skyflowTokens,
116
- );
117
- } catch (error) {
118
- throw formatPublicErrorResponse(
119
- {
120
- message: MESSAGES.saveCardError,
121
- },
122
- error,
123
- );
124
- }
125
- }
126
-
127
- async removeCustomerCard(skyflowId: string): Promise<string> {
128
- try {
129
- await this._fetchMerchantData();
130
- const { auth_token } = await this._getCustomer();
131
- const { business } = this.merchantData!;
132
-
133
- return await removeCustomerCard(
134
- this.baseUrl,
135
- auth_token,
136
- skyflowId,
137
- business?.pk,
138
- );
139
- } catch (error) {
140
- throw formatPublicErrorResponse(
141
- {
142
- message: MESSAGES.removeCardError,
143
- },
144
- error,
145
- );
146
- }
147
- }
148
-
149
- async getCustomerPaymentMethods(): Promise<IPaymentMethod[]> {
150
- try {
151
- const response = await fetchCustomerAPMs(this.baseUrl, this.apiKeyTonder);
152
-
153
- const apms_results =
154
- response && "results" in response && response["results"].length > 0
155
- ? response["results"]
156
- : [];
157
-
158
- return apms_results
159
- .filter((apmItem) => apmItem.category.toLowerCase() !== "cards")
160
- .map((apmItem) => {
161
- const apm = {
162
- id: apmItem.pk,
163
- payment_method: apmItem.payment_method,
164
- priority: apmItem.priority,
165
- category: apmItem.category,
166
- ...getPaymentMethodDetails(apmItem.payment_method),
167
- };
168
- return apm;
169
- })
170
- .sort((a, b) => a.priority - b.priority);
171
- } catch (error) {
172
- throw formatPublicErrorResponse(
173
- {
174
- message: MESSAGES.getPaymentMethodsError,
175
- },
176
- error,
177
- );
178
- }
179
- }
180
-
181
- async getBusiness(): Promise<GetBusinessResponse> {
182
- try {
183
- return await fetchBusiness(
184
- this.baseUrl,
185
- this.apiKeyTonder,
186
- this.abortController.signal,
187
- );
188
- } catch (e) {
189
- throw formatPublicErrorResponse(
190
- {
191
- message: MESSAGES.getBusinessError,
192
- },
193
- e,
194
- );
195
- }
196
- }
197
-
198
- // TODO: DEPRECATED
199
- async getSkyflowTokens({
200
- vault_id,
201
- vault_url,
202
- data,
203
- }: TokensRequest): Promise<any | ErrorResponse> {
204
- return await getSkyflowTokens({
205
- vault_id: vault_id,
206
- vault_url: vault_url,
207
- data,
208
- baseUrl: this.baseUrl,
209
- apiKey: this.apiKeyTonder,
210
- });
211
- }
212
-
213
- _setCartTotal(total: string) {
214
- this.cartTotal = total;
215
- }
216
-
217
- async _checkout({
218
- card,
219
- payment_method,
220
- isSandbox,
221
- }: {
222
- card?: ICardFields | string;
223
- payment_method?: string;
224
- isSandbox?: boolean;
225
- }) {
226
- await this._fetchMerchantData();
227
- const customer = await this._getCustomer(this.abortController.signal);
228
- const { vault_id, vault_url } = this.merchantData!;
229
- let skyflowTokens;
230
- if (!payment_method || payment_method !== "" || payment_method === null) {
231
- if (typeof card === "string") {
232
- skyflowTokens = {
233
- skyflow_id: card,
234
- };
235
- } else {
236
- skyflowTokens = await getSkyflowTokens({
237
- vault_id: vault_id,
238
- vault_url: vault_url,
239
- data: { ...card, card_number: card!.card_number.replace(/\s+/g, "") },
240
- baseUrl: this.baseUrl,
241
- apiKey: this.apiKeyTonder,
242
- });
243
- }
244
- }
245
-
246
- return await this._handleCheckout({
247
- card: skyflowTokens,
248
- payment_method,
249
- customer,
250
- isSandbox,
251
- });
252
- }
253
-
254
- // TODO: DEPRECATED
255
- /**
256
- * @deprecated This method is deprecated and will be removed in a future release.
257
- * It is no longer necessary to use this method as customer registration is now automatically handled
258
- * during the payment process or when using card management methods.
259
- */
260
- async customerRegister(
261
- email: string,
262
- ): Promise<CustomerRegisterResponse | ErrorResponse> {
263
- try {
264
- const url = `${this.baseUrl}/api/v1/customer/`;
265
- const data = { email: email };
266
- const response = await fetch(url, {
267
- method: "POST",
268
- headers: {
269
- "Content-Type": "application/json",
270
- Authorization: `Token ${this.apiKeyTonder}`,
271
- },
272
- signal: this.abortController.signal,
273
- body: JSON.stringify(data),
274
- });
275
-
276
- if (response.ok)
277
- return (await response.json()) as CustomerRegisterResponse;
278
- throw await buildErrorResponse(response);
279
- } catch (e) {
280
- throw buildErrorResponseFromCatch(e);
281
- }
282
- }
283
-
284
- // TODO: DEPRECATED
285
- /**
286
- * @deprecated This method is deprecated and will be removed in a future release.
287
- * It is no longer necessary to use this method as order creation is now automatically
288
- * handled when making a payment through the `payment` function.
289
- */
290
- async createOrder(
291
- orderItems: CreateOrderRequest,
292
- ): Promise<CreateOrderResponse | ErrorResponse> {
293
- try {
294
- const url = `${this.baseUrl}/api/v1/orders/`;
295
- const data = orderItems;
296
- const response = await fetch(url, {
297
- method: "POST",
298
- headers: {
299
- "Content-Type": "application/json",
300
- Authorization: `Token ${this.apiKeyTonder}`,
301
- },
302
- body: JSON.stringify(data),
303
- });
304
- if (response.ok) return (await response.json()) as CreateOrderResponse;
305
- throw await buildErrorResponse(response);
306
- } catch (e) {
307
- throw buildErrorResponseFromCatch(e);
308
- }
309
- }
310
-
311
- // TODO: DEPRECATED
312
- /**
313
- * @deprecated This method is deprecated and will be removed in a future release.
314
- * It is no longer necessary to use this method as payment creation is now automatically
315
- * handled when making a payment through the `payment` function.
316
- */
317
- async createPayment(
318
- paymentItems: CreatePaymentRequest,
319
- ): Promise<CreatePaymentResponse | ErrorResponse> {
320
- try {
321
- const url = `${this.baseUrl}/api/v1/business/${paymentItems.business_pk}/payments/`;
322
- const data = paymentItems;
323
- const response = await fetch(url, {
324
- method: "POST",
325
- headers: {
326
- "Content-Type": "application/json",
327
- Authorization: `Token ${this.apiKeyTonder}`,
328
- },
329
- body: JSON.stringify(data),
330
- });
331
- if (response.ok) return (await response.json()) as CreatePaymentResponse;
332
- throw await buildErrorResponse(response);
333
- } catch (e) {
334
- throw buildErrorResponseFromCatch(e);
335
- }
336
- }
337
-
338
- // TODO: DEPRECATED
339
- /**
340
- * @deprecated This method is deprecated and will be removed in a future release.
341
- * Use the {@link payment} method
342
- */
343
- async startCheckoutRouter(
344
- routerData: StartCheckoutRequest | StartCheckoutIdRequest,
345
- ): Promise<StartCheckoutResponse | ErrorResponse | undefined> {
346
- const checkoutResult = await startCheckoutRouter(
347
- this.baseUrl,
348
- this.apiKeyTonder,
349
- routerData,
350
- );
351
- const payload = await this.init3DSRedirect(checkoutResult);
352
- if (payload) return checkoutResult;
353
- }
354
-
355
- // TODO: DEPRECATED
356
- async init3DSRedirect(checkoutResult: ErrorResponse | StartCheckoutResponse) {
357
- this.process3ds.setPayload(checkoutResult);
358
- return await this._handle3dsRedirect(checkoutResult);
359
- }
360
-
361
- // TODO: DEPRECATED
362
- /**
363
- * @deprecated This method is deprecated and will be removed in a future release.
364
- * Use the {@link payment} method
365
- */
366
- async startCheckoutRouterFull(
367
- routerFullData: StartCheckoutFullRequest,
368
- ): Promise<StartCheckoutResponse | ErrorResponse | undefined> {
369
- try {
370
- const {
371
- order,
372
- total,
373
- customer,
374
- skyflowTokens,
375
- return_url,
376
- isSandbox,
377
- metadata,
378
- currency,
379
- payment_method,
380
- } = routerFullData;
381
-
382
- const merchantResult = await this._fetchMerchantData();
383
-
384
- const customerResult: CustomerRegisterResponse | ErrorResponse =
385
- await this.customerRegister(customer.email);
386
-
387
- if (
388
- customerResult &&
389
- "auth_token" in customerResult &&
390
- merchantResult &&
391
- "reference" in merchantResult
392
- ) {
393
- const orderData: CreateOrderRequest = {
394
- business: this.apiKeyTonder,
395
- client: customerResult.auth_token,
396
- billing_address_id: null,
397
- shipping_address_id: null,
398
- amount: total,
399
- reference: merchantResult.reference,
400
- is_oneclick: true,
401
- items: order.items,
402
- };
403
-
404
- const orderResult = await this.createOrder(orderData);
405
-
406
- const now = new Date();
407
-
408
- const dateString = now.toISOString();
409
-
410
- if (
411
- "id" in orderResult &&
412
- "id" in customerResult &&
413
- "business" in merchantResult
414
- ) {
415
- const paymentItems: CreatePaymentRequest = {
416
- business_pk: merchantResult.business.pk,
417
- amount: total,
418
- date: dateString,
419
- order_id: orderResult.id,
420
- client_id: customerResult.id,
421
- };
422
-
423
- const paymentResult = await this.createPayment(paymentItems);
424
-
425
- let deviceSessionIdTonder: any;
426
-
427
- const { openpay_keys, business } = merchantResult;
428
-
429
- if (openpay_keys.merchant_id && openpay_keys.public_key) {
430
- deviceSessionIdTonder = await getOpenpayDeviceSessionID(
431
- openpay_keys.merchant_id,
432
- openpay_keys.public_key,
433
- isSandbox,
434
- );
435
- }
436
-
437
- const routerItems: StartCheckoutRequest = {
438
- name: customer.name,
439
- last_name: customer.lastname,
440
- email_client: customer.email,
441
- phone_number: customer.phone,
442
- return_url: return_url,
443
- id_product: "no_id",
444
- quantity_product: 1,
445
- id_ship: "0",
446
- instance_id_ship: "0",
447
- amount: total,
448
- title_ship: "shipping",
449
- description: "transaction",
450
- device_session_id: deviceSessionIdTonder
451
- ? deviceSessionIdTonder
452
- : null,
453
- token_id: "",
454
- order_id: "id" in orderResult && orderResult.id,
455
- business_id: business.pk,
456
- payment_id: "pk" in paymentResult && paymentResult.pk,
457
- source: "sdk",
458
- metadata: metadata,
459
- browser_info: getBrowserInfo(),
460
- currency: currency,
461
- ...(!!payment_method
462
- ? { payment_method }
463
- : { card: skyflowTokens }),
464
- ...(typeof MP_DEVICE_SESSION_ID !== "undefined"
465
- ? { mp_device_session_id: MP_DEVICE_SESSION_ID }
466
- : {}),
467
- };
468
-
469
- const checkoutResult = await startCheckoutRouter(
470
- this.baseUrl,
471
- this.apiKeyTonder,
472
- routerItems,
473
- );
474
- const payload = await this.init3DSRedirect(checkoutResult);
475
- if (payload) return checkoutResult;
476
- } else {
477
- throw new ErrorResponse({
478
- code: "500",
479
- body: orderResult as any,
480
- name: "Keys error",
481
- message: "Order response errors",
482
- } as IErrorResponse);
483
- }
484
- } else {
485
- throw new ErrorResponse({
486
- code: "500",
487
- body: merchantResult as any,
488
- name: "Keys error",
489
- message: "Merchant or customer reposne errors",
490
- } as IErrorResponse);
491
- }
492
- } catch (e) {
493
- throw buildErrorResponseFromCatch(e);
494
- }
495
- }
496
-
497
- // TODO: DEPRECATED
498
- /**
499
- * @deprecated This method is deprecated and will be removed in a future release.
500
- * Use the {@link saveCustomerCard} method
501
- */
502
- async registerCustomerCard(
503
- customerToken: string,
504
- data: RegisterCustomerCardRequest,
505
- ): Promise<RegisterCustomerCardResponse | ErrorResponse> {
506
- try {
507
- await this._fetchMerchantData();
508
-
509
- const response = await fetch(
510
- `${this.baseUrl}/api/v1/business/${getBusinessId(this.merchantData)}/cards/`,
511
- {
512
- method: "POST",
513
- headers: {
514
- Authorization: `Token ${customerToken}`,
515
- "Content-Type": "application/json",
516
- },
517
- body: JSON.stringify({ ...data }),
518
- },
519
- );
520
-
521
- if (response.ok)
522
- return (await response.json()) as RegisterCustomerCardResponse;
523
- throw await buildErrorResponse(response);
524
- } catch (error) {
525
- throw buildErrorResponseFromCatch(error);
526
- }
527
- }
528
-
529
- // TODO: DEPRECATED
530
- /**
531
- * @deprecated This method is deprecated and will be removed in a future release.
532
- * Use the {@link removeCustomerCard} method
533
- */
534
- async deleteCustomerCard(
535
- customerToken: string,
536
- skyflowId: string = "",
537
- ): Promise<Boolean | ErrorResponse> {
538
- try {
539
- await this._fetchMerchantData();
540
- const response = await fetch(
541
- `${this.baseUrl}/api/v1/business/${getBusinessId(this.merchantData)}/cards/${skyflowId}`,
542
- {
543
- method: "DELETE",
544
- headers: {
545
- Authorization: `Token ${customerToken}`,
546
- "Content-Type": "application/json",
547
- },
548
- signal: this.abortController.signal,
549
- },
550
- );
551
-
552
- if (response.ok) return true;
553
- throw await buildErrorResponse(response);
554
- } catch (error) {
555
- throw buildErrorResponseFromCatch(error);
556
- }
557
- }
558
-
559
- // TODO: DEPRECATED
560
- /**
561
- * @deprecated This method is deprecated and will be removed in a future release.
562
- * Use the {@link getCustomerPaymentMethods} method
563
- */
564
- async getActiveAPMs(): Promise<APM[]> {
565
- try {
566
- const apms_response = await getCustomerAPMs(
567
- this.baseUrl,
568
- this.apiKeyTonder,
569
- );
570
- const apms_results =
571
- apms_response &&
572
- apms_response["results"] &&
573
- apms_response["results"].length > 0
574
- ? apms_response["results"]
575
- : [];
576
- this.activeAPMs = apms_results
577
- .filter(
578
- (apmItem: TonderAPM) => apmItem.category.toLowerCase() !== "cards",
579
- )
580
- .map((apmItem: TonderAPM) => {
581
- const apm: APM = {
582
- id: apmItem.pk,
583
- payment_method: apmItem.payment_method,
584
- priority: apmItem.priority,
585
- category: apmItem.category,
586
- ...getPaymentMethodDetails(apmItem.payment_method),
587
- };
588
- return apm;
589
- })
590
- .sort((a: APM, b: APM) => a.priority - b.priority);
591
-
592
- return this.activeAPMs;
593
- } catch (e) {
594
- console.error("Error getting APMS", e);
595
- return [];
596
- }
597
- }
598
- }
1
+ import { fetchBusiness } from "../data/businessApi";
2
+
3
+ declare const MP_DEVICE_SESSION_ID: string | undefined;
4
+ import { ErrorResponse } from "./errorResponse";
5
+ import {
6
+ buildErrorResponse,
7
+ buildErrorResponseFromCatch,
8
+ getBrowserInfo,
9
+ getBusinessId,
10
+ formatPublicErrorResponse,
11
+ getCardType,
12
+ } from "../helpers/utils";
13
+ import { getCustomerAPMs } from "../data/api";
14
+ import { BaseInlineCheckout } from "./BaseInlineCheckout";
15
+ import { MESSAGES } from "../shared/constants/messages";
16
+ import { getSkyflowTokens } from "../helpers/skyflow";
17
+ import { startCheckoutRouter } from "../data/checkoutApi";
18
+ import { getOpenpayDeviceSessionID } from "../data/openPayApi";
19
+ import { getPaymentMethodDetails } from "../shared/catalog/paymentMethodsCatalog";
20
+ import {APM, IInlineLiteCheckoutOptions, TonderAPM} from "../types/commons";
21
+ import {ICustomerCardsResponse, ISaveCardRequest, ISaveCardResponse, ISaveCardSkyflowRequest} from "../types/card";
22
+ import {IPaymentMethod} from "../types/paymentMethod";
23
+ import {
24
+ CreateOrderResponse,
25
+ CreatePaymentResponse,
26
+ CustomerRegisterResponse,
27
+ GetBusinessResponse, IErrorResponse, RegisterCustomerCardResponse, StartCheckoutResponse, GetSecureTokenResponse
28
+ } from "../types/responses";
29
+ import {
30
+ CreateOrderRequest,
31
+ CreatePaymentRequest, RegisterCustomerCardRequest, StartCheckoutFullRequest,
32
+ StartCheckoutIdRequest,
33
+ StartCheckoutRequest,
34
+ TokensRequest
35
+ } from "../types/requests";
36
+ import {ICardFields, IStartCheckoutResponse} from "../types/checkout";
37
+ import {ILiteCheckout} from "../types/liteInlineCheckout";
38
+
39
+ declare global {
40
+ interface Window {
41
+ OpenPay: any;
42
+ }
43
+ }
44
+
45
+ export class LiteCheckout extends BaseInlineCheckout implements ILiteCheckout{
46
+ activeAPMs: APM[] = [];
47
+
48
+ constructor({ apiKey, mode, returnUrl, callBack, apiKeyTonder, baseUrlTonder }: IInlineLiteCheckoutOptions) {
49
+ super({ mode, apiKey, returnUrl, callBack, apiKeyTonder, baseUrlTonder });
50
+ }
51
+
52
+ public async injectCheckout() {
53
+ await this._initializeCheckout();
54
+ }
55
+
56
+ public async getCustomerCards(): Promise<ICustomerCardsResponse> {
57
+ try {
58
+ await this._fetchMerchantData();
59
+ const { auth_token } = await this._getCustomer();
60
+ const response = await this._getCustomerCards(
61
+ auth_token,
62
+ this.merchantData!.business.pk,
63
+ );
64
+
65
+ return {
66
+ ...response,
67
+ cards: response.cards.map((ic) => ({
68
+ ...ic,
69
+ icon: getCardType(ic.fields.card_scheme),
70
+ })),
71
+ };
72
+ } catch (error) {
73
+ throw formatPublicErrorResponse(
74
+ {
75
+ message: MESSAGES.getCardsError,
76
+ },
77
+ error,
78
+ );
79
+ }
80
+ }
81
+
82
+ public async saveCustomerCard(
83
+ card: ISaveCardRequest,
84
+ ): Promise<ISaveCardResponse> {
85
+ try {
86
+ await this._fetchMerchantData();
87
+ const { auth_token } = await this._getCustomer();
88
+ const { vault_id, vault_url, business } = this.merchantData!;
89
+
90
+ const skyflowTokens: ISaveCardSkyflowRequest = await getSkyflowTokens({
91
+ vault_id: vault_id,
92
+ vault_url: vault_url,
93
+ data: card,
94
+ baseUrl: this.baseUrl,
95
+ apiKey: this.apiKeyTonder,
96
+ });
97
+
98
+ return await this._saveCustomerCard(
99
+ auth_token,
100
+ business?.pk,
101
+ skyflowTokens,
102
+ );
103
+ } catch (error) {
104
+ throw formatPublicErrorResponse(
105
+ {
106
+ message: MESSAGES.saveCardError,
107
+ },
108
+ error,
109
+ );
110
+ }
111
+ }
112
+
113
+ public async removeCustomerCard(skyflowId: string): Promise<string> {
114
+ try {
115
+ await this._fetchMerchantData();
116
+ const { auth_token } = await this._getCustomer();
117
+ const { business } = this.merchantData!;
118
+
119
+ return await this._removeCustomerCard(
120
+ auth_token,
121
+ business?.pk,
122
+ skyflowId,
123
+ );
124
+ } catch (error) {
125
+ throw formatPublicErrorResponse(
126
+ {
127
+ message: MESSAGES.removeCardError,
128
+ },
129
+ error,
130
+ );
131
+ }
132
+ }
133
+
134
+ public async getCustomerPaymentMethods(): Promise<IPaymentMethod[]> {
135
+ try {
136
+ const response = await this._fetchCustomerPaymentMethods();
137
+
138
+ const apms_results =
139
+ response && "results" in response && response["results"].length > 0
140
+ ? response["results"]
141
+ : [];
142
+
143
+ return apms_results
144
+ .filter((apmItem) => apmItem.category.toLowerCase() !== "cards")
145
+ .map((apmItem) => {
146
+ const apm = {
147
+ id: apmItem.pk,
148
+ payment_method: apmItem.payment_method,
149
+ priority: apmItem.priority,
150
+ category: apmItem.category,
151
+ ...getPaymentMethodDetails(apmItem.payment_method),
152
+ };
153
+ return apm;
154
+ })
155
+ .sort((a, b) => a.priority - b.priority);
156
+ } catch (error) {
157
+ throw formatPublicErrorResponse(
158
+ {
159
+ message: MESSAGES.getPaymentMethodsError,
160
+ },
161
+ error,
162
+ );
163
+ }
164
+ }
165
+
166
+ public async getBusiness(): Promise<GetBusinessResponse> {
167
+ try {
168
+ return await fetchBusiness(
169
+ this.baseUrl,
170
+ this.apiKeyTonder,
171
+ this.abortController.signal,
172
+ );
173
+ } catch (e) {
174
+ throw formatPublicErrorResponse(
175
+ {
176
+ message: MESSAGES.getBusinessError,
177
+ },
178
+ e,
179
+ );
180
+ }
181
+ }
182
+
183
+ // TODO: DEPRECATED
184
+ async getOpenpayDeviceSessionID(
185
+ merchant_id: string,
186
+ public_key: string,
187
+ is_sandbox: boolean,
188
+ ): Promise<string | ErrorResponse> {
189
+ try {
190
+ return await getOpenpayDeviceSessionID(
191
+ merchant_id,
192
+ public_key,
193
+ is_sandbox,
194
+ );
195
+ } catch (e) {
196
+ throw buildErrorResponseFromCatch(e);
197
+ }
198
+ }
199
+
200
+ // TODO: DEPRECATED
201
+ async getSkyflowTokens({
202
+ vault_id,
203
+ vault_url,
204
+ data,
205
+ }: TokensRequest): Promise<any | ErrorResponse> {
206
+ return await getSkyflowTokens({
207
+ vault_id: vault_id,
208
+ vault_url: vault_url,
209
+ data,
210
+ baseUrl: this.baseUrl,
211
+ apiKey: this.apiKeyTonder,
212
+ });
213
+ }
214
+
215
+ _setCartTotal(total: string) {
216
+ this.cartTotal = total;
217
+ }
218
+
219
+ async _checkout({
220
+ card,
221
+ payment_method,
222
+ isSandbox,
223
+ // TODO: DEPRECATED
224
+ returnUrl: returnUrlData
225
+ }: {
226
+ card?: ICardFields | string;
227
+ payment_method?: string;
228
+ isSandbox?: boolean;
229
+ returnUrl?: string;
230
+ }) {
231
+ await this._fetchMerchantData();
232
+ const customer = await this._getCustomer(this.abortController.signal);
233
+ const { vault_id, vault_url } = this.merchantData!;
234
+ let skyflowTokens;
235
+ if (!payment_method || payment_method !== "" || payment_method === null) {
236
+ if (typeof card === "string") {
237
+ skyflowTokens = {
238
+ skyflow_id: card,
239
+ };
240
+ } else {
241
+ skyflowTokens = await getSkyflowTokens({
242
+ vault_id: vault_id,
243
+ vault_url: vault_url,
244
+ data: { ...card, card_number: card!.card_number.replace(/\s+/g, "") },
245
+ baseUrl: this.baseUrl,
246
+ apiKey: this.apiKeyTonder,
247
+ });
248
+ }
249
+ }
250
+
251
+ return await this._handleCheckout({
252
+ card: skyflowTokens,
253
+ payment_method,
254
+ customer,
255
+ isSandbox,
256
+ returnUrl: returnUrlData
257
+ });
258
+ }
259
+
260
+ // TODO: DEPRECATED
261
+ async customerRegister(
262
+ email: string,
263
+ ): Promise<CustomerRegisterResponse | ErrorResponse> {
264
+ try {
265
+ const url = `${this.baseUrl}/api/v1/customer/`;
266
+ const data = { email: email };
267
+ const response = await fetch(url, {
268
+ method: "POST",
269
+ headers: {
270
+ "Content-Type": "application/json",
271
+ Authorization: `Token ${this.apiKeyTonder}`,
272
+ },
273
+ signal: this.abortController.signal,
274
+ body: JSON.stringify(data),
275
+ });
276
+
277
+ if (response.ok)
278
+ return (await response.json()) as CustomerRegisterResponse;
279
+ throw await buildErrorResponse(response);
280
+ } catch (e) {
281
+ throw buildErrorResponseFromCatch(e);
282
+ }
283
+ }
284
+
285
+ // TODO: DEPRECATED
286
+ async createOrder(
287
+ orderItems: CreateOrderRequest,
288
+ ): Promise<CreateOrderResponse | ErrorResponse> {
289
+ try {
290
+ const url = `${this.baseUrl}/api/v1/orders/`;
291
+ const data = orderItems;
292
+ const response = await fetch(url, {
293
+ method: "POST",
294
+ headers: {
295
+ "Content-Type": "application/json",
296
+ Authorization: `Token ${this.apiKeyTonder}`,
297
+ },
298
+ body: JSON.stringify(data),
299
+ });
300
+ if (response.ok) return (await response.json()) as CreateOrderResponse;
301
+ throw await buildErrorResponse(response);
302
+ } catch (e) {
303
+ throw buildErrorResponseFromCatch(e);
304
+ }
305
+ }
306
+
307
+ // TODO: DEPRECATED
308
+ async createPayment(
309
+ paymentItems: CreatePaymentRequest,
310
+ ): Promise<CreatePaymentResponse | ErrorResponse> {
311
+ try {
312
+ const url = `${this.baseUrl}/api/v1/business/${paymentItems.business_pk}/payments/`;
313
+ const data = paymentItems;
314
+ const response = await fetch(url, {
315
+ method: "POST",
316
+ headers: {
317
+ "Content-Type": "application/json",
318
+ Authorization: `Token ${this.apiKeyTonder}`,
319
+ },
320
+ body: JSON.stringify(data),
321
+ });
322
+ if (response.ok) return (await response.json()) as CreatePaymentResponse;
323
+ throw await buildErrorResponse(response);
324
+ } catch (e) {
325
+ throw buildErrorResponseFromCatch(e);
326
+ }
327
+ }
328
+
329
+ // TODO: DEPRECATED
330
+ async startCheckoutRouter(
331
+ routerData: StartCheckoutRequest | StartCheckoutIdRequest,
332
+ ): Promise<StartCheckoutResponse | ErrorResponse | undefined> {
333
+ const checkoutResult = await startCheckoutRouter(
334
+ this.baseUrl,
335
+ this.apiKeyTonder,
336
+ routerData,
337
+ );
338
+ const payload = await this.init3DSRedirect(checkoutResult);
339
+ if (payload) return checkoutResult;
340
+ }
341
+
342
+ // TODO: DEPRECATED
343
+ async init3DSRedirect(checkoutResult: IStartCheckoutResponse) {
344
+ this.process3ds.setPayload(checkoutResult);
345
+ return await this._handle3dsRedirect(checkoutResult);
346
+ }
347
+
348
+ // TODO: DEPRECATED
349
+ async startCheckoutRouterFull(
350
+ routerFullData: StartCheckoutFullRequest,
351
+ ): Promise<StartCheckoutResponse | ErrorResponse | undefined> {
352
+ try {
353
+ const {
354
+ order,
355
+ total,
356
+ customer,
357
+ skyflowTokens,
358
+ return_url,
359
+ isSandbox,
360
+ metadata,
361
+ currency,
362
+ payment_method,
363
+ } = routerFullData;
364
+
365
+ const merchantResult = await this._fetchMerchantData();
366
+
367
+ const customerResult: CustomerRegisterResponse | ErrorResponse =
368
+ await this.customerRegister(customer.email);
369
+
370
+ if (
371
+ customerResult &&
372
+ "auth_token" in customerResult &&
373
+ merchantResult &&
374
+ "reference" in merchantResult
375
+ ) {
376
+ const orderData: CreateOrderRequest = {
377
+ business: this.apiKeyTonder,
378
+ client: customerResult.auth_token,
379
+ billing_address_id: null,
380
+ shipping_address_id: null,
381
+ amount: total,
382
+ reference: merchantResult.reference,
383
+ is_oneclick: true,
384
+ items: order.items,
385
+ };
386
+
387
+ const orderResult = await this.createOrder(orderData);
388
+
389
+ const now = new Date();
390
+
391
+ const dateString = now.toISOString();
392
+
393
+ if (
394
+ "id" in orderResult &&
395
+ "id" in customerResult &&
396
+ "business" in merchantResult
397
+ ) {
398
+ const paymentItems: CreatePaymentRequest = {
399
+ business_pk: merchantResult.business.pk,
400
+ amount: total,
401
+ date: dateString,
402
+ order_id: orderResult.id,
403
+ client_id: customerResult.id,
404
+ };
405
+
406
+ const paymentResult = await this.createPayment(paymentItems);
407
+
408
+ let deviceSessionIdTonder: any;
409
+
410
+ const { openpay_keys, business } = merchantResult;
411
+
412
+ if (openpay_keys.merchant_id && openpay_keys.public_key) {
413
+ deviceSessionIdTonder = await getOpenpayDeviceSessionID(
414
+ openpay_keys.merchant_id,
415
+ openpay_keys.public_key,
416
+ isSandbox,
417
+ );
418
+ }
419
+
420
+ const routerItems: StartCheckoutRequest = {
421
+ name: customer.name,
422
+ last_name: customer.lastname,
423
+ email_client: customer.email,
424
+ phone_number: customer.phone,
425
+ return_url: return_url,
426
+ id_product: "no_id",
427
+ quantity_product: 1,
428
+ id_ship: "0",
429
+ instance_id_ship: "0",
430
+ amount: total,
431
+ title_ship: "shipping",
432
+ description: "transaction",
433
+ device_session_id: deviceSessionIdTonder
434
+ ? deviceSessionIdTonder
435
+ : null,
436
+ token_id: "",
437
+ order_id: "id" in orderResult && orderResult.id,
438
+ business_id: business.pk,
439
+ payment_id: "pk" in paymentResult && paymentResult.pk,
440
+ source: "sdk",
441
+ metadata: metadata,
442
+ browser_info: getBrowserInfo(),
443
+ currency: currency,
444
+ ...(!!payment_method
445
+ ? { payment_method }
446
+ : { card: skyflowTokens }),
447
+ ...(typeof MP_DEVICE_SESSION_ID !== "undefined"
448
+ ? { mp_device_session_id: MP_DEVICE_SESSION_ID }
449
+ : {}),
450
+ };
451
+
452
+ const checkoutResult = await startCheckoutRouter(
453
+ this.baseUrl,
454
+ this.apiKeyTonder,
455
+ routerItems,
456
+ );
457
+ const payload = await this.init3DSRedirect(checkoutResult);
458
+ if (payload) return checkoutResult;
459
+ } else {
460
+ throw new ErrorResponse({
461
+ code: "500",
462
+ body: orderResult as any,
463
+ name: "Keys error",
464
+ message: "Order response errors",
465
+ } as IErrorResponse);
466
+ }
467
+ } else {
468
+ throw new ErrorResponse({
469
+ code: "500",
470
+ body: merchantResult as any,
471
+ name: "Keys error",
472
+ message: "Merchant or customer reposne errors",
473
+ } as IErrorResponse);
474
+ }
475
+ } catch (e) {
476
+ throw buildErrorResponseFromCatch(e);
477
+ }
478
+ }
479
+
480
+ // TODO: DEPRECATED
481
+ async registerCustomerCard(
482
+ secureToken: string,
483
+ customerToken: string,
484
+ data: RegisterCustomerCardRequest,
485
+ ): Promise<RegisterCustomerCardResponse | ErrorResponse> {
486
+ try {
487
+ await this._fetchMerchantData();
488
+
489
+ const response = await fetch(
490
+ `${this.baseUrl}/api/v1/business/${getBusinessId(this.merchantData)}/cards/`,
491
+ {
492
+ method: "POST",
493
+ headers: {
494
+ Authorization: `Token ${customerToken}`,
495
+ "Content-Type": "application/json",
496
+ },
497
+ body: JSON.stringify({ ...data }),
498
+ },
499
+ );
500
+
501
+ if (response.ok)
502
+ return (await response.json()) as RegisterCustomerCardResponse;
503
+ throw await buildErrorResponse(response);
504
+ } catch (error) {
505
+ throw buildErrorResponseFromCatch(error);
506
+ }
507
+ }
508
+
509
+ // TODO: DEPRECATED
510
+ async deleteCustomerCard(
511
+ customerToken: string,
512
+ skyflowId: string = "",
513
+ ): Promise<Boolean | ErrorResponse> {
514
+ try {
515
+ await this._fetchMerchantData();
516
+ const response = await fetch(
517
+ `${this.baseUrl}/api/v1/business/${getBusinessId(this.merchantData)}/cards/${skyflowId}`,
518
+ {
519
+ method: "DELETE",
520
+ headers: {
521
+ Authorization: `Token ${customerToken}`,
522
+ "Content-Type": "application/json",
523
+ },
524
+ signal: this.abortController.signal,
525
+ },
526
+ );
527
+
528
+ if (response.ok) return true;
529
+ throw await buildErrorResponse(response);
530
+ } catch (error) {
531
+ throw buildErrorResponseFromCatch(error);
532
+ }
533
+ }
534
+
535
+ // TODO: DEPRECATED
536
+ async getActiveAPMs(): Promise<APM[]> {
537
+ try {
538
+ const apms_response = await getCustomerAPMs(
539
+ this.baseUrl,
540
+ this.apiKeyTonder,
541
+ );
542
+ const apms_results =
543
+ apms_response &&
544
+ apms_response["results"] &&
545
+ apms_response["results"].length > 0
546
+ ? apms_response["results"]
547
+ : [];
548
+ this.activeAPMs = apms_results
549
+ .filter(
550
+ (apmItem: TonderAPM) => apmItem.category.toLowerCase() !== "cards",
551
+ )
552
+ .map((apmItem: TonderAPM) => {
553
+ const apm: APM = {
554
+ id: apmItem.pk,
555
+ payment_method: apmItem.payment_method,
556
+ priority: apmItem.priority,
557
+ category: apmItem.category,
558
+ ...getPaymentMethodDetails(apmItem.payment_method),
559
+ };
560
+ return apm;
561
+ })
562
+ .sort((a: APM, b: APM) => a.priority - b.priority);
563
+
564
+ return this.activeAPMs;
565
+ } catch (e) {
566
+ console.error("Error getting APMS", e);
567
+ return [];
568
+ }
569
+ }
570
+
571
+ async getSecureToken(token: string): Promise<GetSecureTokenResponse | ErrorResponse> {
572
+ try {
573
+ const response = await fetch(`${this.baseUrl}/api/secure-token/`, {
574
+ method: 'POST',
575
+ headers: {
576
+ 'Authorization': `Token ${token}`,
577
+ 'Content-Type': 'application/json'
578
+ },
579
+ signal: this.abortController.signal
580
+ });
581
+
582
+ if (response.ok) return await response.json() as GetSecureTokenResponse;
583
+ throw await buildErrorResponse(response);
584
+ } catch (error) {
585
+ throw buildErrorResponseFromCatch(error);
586
+ }
587
+ }
588
+ }