@tonder.io/ionic-lite-sdk 0.0.41-beta.1 → 0.0.42-beta.2

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