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

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 (55) hide show
  1. package/.gitlab-ci.yml +28 -28
  2. package/README.md +532 -532
  3. package/dist/classes/BaseInlineCheckout.d.ts +1 -1
  4. package/dist/classes/liteCheckout.d.ts +1 -1
  5. package/dist/data/cardApi.d.ts +3 -3
  6. package/dist/index.js +1 -1
  7. package/dist/types/liteInlineCheckout.d.ts +1 -1
  8. package/jest.config.ts +14 -14
  9. package/package.json +41 -41
  10. package/rollup.config.js +16 -16
  11. package/src/classes/3dsHandler.ts +347 -347
  12. package/src/classes/BaseInlineCheckout.ts +424 -424
  13. package/src/classes/errorResponse.ts +16 -16
  14. package/src/classes/liteCheckout.ts +589 -591
  15. package/src/data/api.ts +20 -20
  16. package/src/data/businessApi.ts +18 -18
  17. package/src/data/cardApi.ts +91 -87
  18. package/src/data/checkoutApi.ts +84 -84
  19. package/src/data/customerApi.ts +31 -31
  20. package/src/data/openPayApi.ts +12 -12
  21. package/src/data/paymentMethodApi.ts +37 -37
  22. package/src/data/skyflowApi.ts +20 -20
  23. package/src/helpers/constants.ts +63 -63
  24. package/src/helpers/mercadopago.ts +15 -15
  25. package/src/helpers/skyflow.ts +91 -91
  26. package/src/helpers/utils.ts +120 -120
  27. package/src/helpers/validations.ts +55 -55
  28. package/src/index.ts +12 -12
  29. package/src/shared/catalog/paymentMethodsCatalog.ts +247 -247
  30. package/src/shared/constants/messages.ts +10 -10
  31. package/src/shared/constants/paymentMethodAPM.ts +63 -63
  32. package/src/shared/constants/tonderUrl.ts +8 -8
  33. package/src/types/card.ts +35 -35
  34. package/src/types/checkout.ts +123 -123
  35. package/src/types/commons.ts +143 -143
  36. package/src/types/customer.ts +22 -22
  37. package/src/types/liteInlineCheckout.ts +216 -216
  38. package/src/types/paymentMethod.ts +23 -23
  39. package/src/types/requests.ts +114 -114
  40. package/src/types/responses.ts +192 -192
  41. package/src/types/skyflow.ts +17 -17
  42. package/src/types/transaction.ts +101 -101
  43. package/src/types/validations.d.ts +11 -11
  44. package/tests/classes/liteCheckout.test.ts +57 -57
  45. package/tests/methods/createOrder.test.ts +141 -141
  46. package/tests/methods/createPayment.test.ts +121 -121
  47. package/tests/methods/customerRegister.test.ts +118 -118
  48. package/tests/methods/getBusiness.test.ts +114 -114
  49. package/tests/methods/getCustomerCards.test.ts +112 -112
  50. package/tests/methods/registerCustomerCard.test.ts +117 -117
  51. package/tests/methods/startCheckoutRouter.test.ts +119 -119
  52. package/tests/methods/startCheckoutRouterFull.test.ts +138 -138
  53. package/tests/utils/defaultMock.ts +21 -21
  54. package/tests/utils/mockClasses.ts +659 -659
  55. 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
+ }