@xsolla/payment-client-core 0.0.4 → 0.0.5

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 (144) hide show
  1. package/esm2020/lib/core/device-finger-print/device-finger-print-components.interface.mjs +2 -0
  2. package/esm2020/lib/core/device-finger-print/device-finger-print.service.mjs +167 -0
  3. package/esm2020/lib/core/device-finger-print/fingerprint-js.interface.mjs +2 -0
  4. package/esm2020/lib/core/device-finger-print/hash.type.mjs +2 -0
  5. package/esm2020/lib/core/exceptions-handling/errors/default-terminal-error.class.mjs +8 -0
  6. package/esm2020/lib/core/exceptions-handling/errors/terminal-error.class.mjs +8 -0
  7. package/esm2020/lib/core/exceptions-handling/errors/token-error.class.mjs +7 -0
  8. package/esm2020/lib/core/payment/actions/action-factory-value.interface.mjs +2 -0
  9. package/esm2020/lib/core/payment/actions/action-type-command.map.mjs +5 -0
  10. package/esm2020/lib/core/payment/actions/action.interface.mjs +2 -0
  11. package/esm2020/lib/core/payment/actions/check-status/check-status.action.type.mjs +2 -0
  12. package/esm2020/lib/core/payment/actions/next-action.interface.mjs +2 -0
  13. package/esm2020/lib/core/payment/actions/next-action.service.mjs +47 -0
  14. package/esm2020/lib/core/payment/actions/next-actions.mjs +5 -0
  15. package/esm2020/lib/core/payment/actions/show-fields/show-fields.action.class.mjs +16 -0
  16. package/esm2020/lib/core/payment/actions/show-fields/show-fields.action.token.mjs +11 -0
  17. package/esm2020/lib/core/payment/actions/show-fields/show-fields.action.type.mjs +2 -0
  18. package/esm2020/lib/core/payment/field-names.enum.mjs +64 -0
  19. package/esm2020/lib/core/payment/field.interface.mjs +1 -1
  20. package/esm2020/lib/core/payment/form/common-control-config.interface.mjs +2 -0
  21. package/esm2020/lib/core/payment/form/controls/control-config.mjs +6 -0
  22. package/esm2020/lib/core/payment/form/controls/control-config.service.mjs +39 -0
  23. package/esm2020/lib/core/payment/form/controls/control-type.type.mjs +2 -0
  24. package/esm2020/lib/core/payment/form/controls/text-control.config.mjs +8 -0
  25. package/esm2020/lib/core/payment/form/converters/converter.abstract.mjs +75 -0
  26. package/esm2020/lib/core/payment/form/converters/converters-map.interface.mjs +2 -0
  27. package/esm2020/lib/core/payment/form/converters/converters-map.mjs +9 -0
  28. package/esm2020/lib/core/payment/form/converters/email.converter.mjs +29 -0
  29. package/esm2020/lib/core/payment/form/converters/zip.converter.mjs +64 -0
  30. package/esm2020/lib/core/payment/form/form-state.interface.mjs +2 -0
  31. package/esm2020/lib/core/payment/form/form.module.mjs +33 -0
  32. package/esm2020/lib/core/payment/form/form.service.mjs +28 -0
  33. package/esm2020/lib/core/payment/form/validators/convert.function.mjs +22 -0
  34. package/esm2020/lib/core/payment/form/validators/email-validator.mjs +7 -0
  35. package/esm2020/lib/core/payment/form/validators/required-validator.mjs +6 -0
  36. package/esm2020/lib/core/payment/form/validators/restricted-value.validator.mjs +6 -0
  37. package/esm2020/lib/core/payment/form/validators/validation-error.interface.mjs +2 -0
  38. package/esm2020/lib/core/payment/form/validators/validation-errors.interface.mjs +2 -0
  39. package/esm2020/lib/core/payment/form/validators/validator-fn.type.mjs +2 -0
  40. package/esm2020/lib/core/payment/initialize/initialize-request-params.interface.mjs +2 -0
  41. package/esm2020/lib/core/payment/initialize/initialize-response.class.mjs +43 -0
  42. package/esm2020/lib/core/payment/initialize/initialize-response.token.mjs +8 -0
  43. package/esm2020/lib/core/payment/initialize/initialize.service.mjs +46 -0
  44. package/esm2020/lib/core/payment/payment-form.interface.mjs +2 -0
  45. package/esm2020/lib/core/payment/payment.interface.mjs +1 -1
  46. package/esm2020/lib/core/payment/payment.service.mjs +29 -12
  47. package/esm2020/lib/core/payment/submit/request/submit-request.class.mjs +16 -0
  48. package/esm2020/lib/core/payment/submit/request/submit-request.token.mjs +8 -0
  49. package/esm2020/lib/core/payment/submit/response/submit-response.class.mjs +31 -0
  50. package/esm2020/lib/core/payment/submit/response/submit-response.token.mjs +8 -0
  51. package/esm2020/lib/core/payment/submit/submit.service.mjs +59 -0
  52. package/esm2020/lib/core/payment/sync/field-sync-state.interface.mjs +2 -0
  53. package/esm2020/lib/core/payment/sync/sync-request.class.mjs +31 -0
  54. package/esm2020/lib/core/payment/sync/sync-request.token.mjs +8 -0
  55. package/esm2020/lib/core/payment/sync/sync-response.class.mjs +14 -0
  56. package/esm2020/lib/core/payment/sync/sync-response.token.mjs +8 -0
  57. package/esm2020/lib/core/payment/sync/sync.service.mjs +91 -0
  58. package/esm2020/lib/core/payment/xps-api-part-request.abstract.mjs +8 -0
  59. package/esm2020/lib/core/payment/xps-error.interface.mjs +1 -1
  60. package/esm2020/lib/core/payment/xps-request.abstract.mjs +8 -0
  61. package/esm2020/lib/core/payment/xps-response.interface.mjs +1 -1
  62. package/esm2020/lib/core/xps-boolean.enum.mjs +2 -0
  63. package/esm2020/lib/core-library.module.mjs +31 -4
  64. package/esm2020/lib/core-library.service.mjs +14 -10
  65. package/fesm2015/xsolla-payment-client-core.mjs +1093 -83
  66. package/fesm2015/xsolla-payment-client-core.mjs.map +1 -1
  67. package/fesm2020/xsolla-payment-client-core.mjs +1047 -79
  68. package/fesm2020/xsolla-payment-client-core.mjs.map +1 -1
  69. package/lib/core/device-finger-print/device-finger-print-components.interface.d.ts +4 -0
  70. package/lib/core/device-finger-print/device-finger-print.service.d.ts +44 -0
  71. package/lib/core/device-finger-print/fingerprint-js.interface.d.ts +6 -0
  72. package/lib/core/device-finger-print/hash.type.d.ts +3 -0
  73. package/lib/core/exceptions-handling/errors/default-terminal-error.class.d.ts +4 -0
  74. package/lib/core/exceptions-handling/errors/terminal-error.class.d.ts +5 -0
  75. package/lib/core/exceptions-handling/errors/token-error.class.d.ts +4 -0
  76. package/lib/core/payment/actions/action-factory-value.interface.d.ts +5 -0
  77. package/lib/core/payment/actions/action-type-command.map.d.ts +4 -0
  78. package/lib/core/payment/actions/{check-status.action.type.d.ts → check-status/check-status.action.type.d.ts} +1 -1
  79. package/lib/core/payment/actions/next-action.interface.d.ts +3 -0
  80. package/lib/core/payment/actions/next-action.service.d.ts +16 -0
  81. package/lib/core/payment/actions/next-actions.d.ts +5 -0
  82. package/lib/core/payment/actions/show-fields/show-fields.action.class.d.ts +8 -0
  83. package/lib/core/payment/actions/show-fields/show-fields.action.token.d.ts +4 -0
  84. package/lib/core/payment/actions/show-fields/show-fields.action.type.d.ts +12 -0
  85. package/lib/core/payment/field-names.enum.d.ts +62 -0
  86. package/lib/core/payment/field.interface.d.ts +5 -5
  87. package/lib/core/payment/form/common-control-config.interface.d.ts +9 -0
  88. package/lib/core/payment/form/controls/control-config.d.ts +9 -0
  89. package/lib/core/payment/form/controls/control-config.service.d.ts +15 -0
  90. package/lib/core/payment/form/controls/control-type.type.d.ts +1 -0
  91. package/lib/core/payment/form/controls/text-control.config.d.ts +11 -0
  92. package/lib/core/payment/form/converters/converter.abstract.d.ts +23 -0
  93. package/lib/core/payment/form/converters/converters-map.d.ts +4 -0
  94. package/lib/core/payment/form/converters/converters-map.interface.d.ts +5 -0
  95. package/lib/core/payment/form/converters/email.converter.d.ts +14 -0
  96. package/lib/core/payment/form/converters/zip.converter.d.ts +21 -0
  97. package/lib/core/payment/form/form-state.interface.d.ts +3 -0
  98. package/lib/core/payment/form/form.module.d.ts +7 -0
  99. package/lib/core/payment/form/form.service.d.ts +12 -0
  100. package/lib/core/payment/form/validators/convert.function.d.ts +3 -0
  101. package/lib/core/payment/form/validators/email-validator.d.ts +2 -0
  102. package/lib/core/payment/form/validators/required-validator.d.ts +2 -0
  103. package/lib/core/payment/form/validators/restricted-value.validator.d.ts +2 -0
  104. package/lib/core/payment/form/validators/validation-error.interface.d.ts +4 -0
  105. package/lib/core/payment/form/validators/validation-errors.interface.d.ts +4 -0
  106. package/lib/core/payment/form/validators/validator-fn.type.d.ts +3 -0
  107. package/lib/core/payment/initialize/initialize-response.class.d.ts +7 -0
  108. package/lib/core/payment/initialize/initialize-response.token.d.ts +6 -0
  109. package/lib/core/payment/initialize/initialize.service.d.ts +18 -0
  110. package/lib/core/payment/payment-form.interface.d.ts +39 -0
  111. package/lib/core/payment/payment.interface.d.ts +6 -5
  112. package/lib/core/payment/payment.service.d.ts +18 -7
  113. package/lib/core/payment/submit/request/submit-request.class.d.ts +13 -0
  114. package/lib/core/payment/submit/request/submit-request.token.d.ts +6 -0
  115. package/lib/core/payment/submit/response/submit-response.class.d.ts +26 -0
  116. package/lib/core/payment/submit/response/submit-response.token.d.ts +6 -0
  117. package/lib/core/payment/submit/submit.service.d.ts +21 -0
  118. package/lib/core/payment/sync/field-sync-state.interface.d.ts +5 -0
  119. package/lib/core/payment/sync/sync-request.class.d.ts +15 -0
  120. package/lib/core/payment/sync/sync-request.token.d.ts +6 -0
  121. package/lib/core/payment/sync/sync-response.class.d.ts +11 -0
  122. package/lib/core/payment/sync/sync-response.token.d.ts +6 -0
  123. package/lib/core/payment/sync/sync.service.d.ts +27 -0
  124. package/lib/core/payment/xps-api-part-request.abstract.d.ts +6 -0
  125. package/lib/core/payment/xps-error.interface.d.ts +1 -0
  126. package/lib/core/payment/xps-request.abstract.d.ts +6 -0
  127. package/lib/core/payment/xps-response.interface.d.ts +3 -6
  128. package/lib/core/xps-boolean.enum.d.ts +4 -0
  129. package/lib/core-library.module.d.ts +2 -1
  130. package/lib/core-library.service.d.ts +4 -2
  131. package/package.json +1 -1
  132. package/xsolla-payment-client-core-0.0.5.tgz +0 -0
  133. package/esm2020/lib/core/boolean-string.enum.mjs +0 -6
  134. package/esm2020/lib/core/payment/actions/action.type.mjs +0 -2
  135. package/esm2020/lib/core/payment/actions/check-status.action.type.mjs +0 -2
  136. package/esm2020/lib/core/payment/actions/next-action.type.mjs +0 -2
  137. package/esm2020/lib/core/payment/initialize-request-params.interface.mjs +0 -2
  138. package/esm2020/lib/core/payment/initialize.service.mjs +0 -39
  139. package/lib/core/boolean-string.enum.d.ts +0 -4
  140. package/lib/core/payment/actions/next-action.type.d.ts +0 -2
  141. package/lib/core/payment/initialize.service.d.ts +0 -16
  142. package/xsolla-payment-client-core-0.0.4.tgz +0 -0
  143. /package/lib/core/payment/actions/{action.type.d.ts → action.interface.d.ts} +0 -0
  144. /package/lib/core/payment/{initialize-request-params.interface.d.ts → initialize/initialize-request-params.interface.d.ts} +0 -0
@@ -3,6 +3,7 @@ import { InjectionToken, Injectable, Inject, NgModule } from '@angular/core';
3
3
  import { firstValueFrom, lastValueFrom, map, throwError } from 'rxjs';
4
4
  import * as i1 from '@angular/common/http';
5
5
  import { HttpParams, HttpHeaders, HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
6
+ import { UntypedFormGroup, Validators, UntypedFormControl, ReactiveFormsModule } from '@angular/forms';
6
7
  import { catchError } from 'rxjs/operators';
7
8
  import * as i1$1 from '@angular/router';
8
9
 
@@ -397,6 +398,994 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
397
398
  args: [userBalanceResponseFactoryToken]
398
399
  }] }, { type: SettingsService }, { type: SecureApiClient }]; } });
399
400
 
401
+ class InitializeResponse {
402
+ constructor(response) {
403
+ this.paymentForm = null;
404
+ this.paymentForm = this.extractPaymentForm(response);
405
+ }
406
+ extractPaymentForm(response) {
407
+ if (!response) {
408
+ return null;
409
+ }
410
+ return {
411
+ totalAmount: response.buyData.sum,
412
+ currency: response.buyData.currency,
413
+ fields: Object.keys(response.form).map((key) => response.form[key]),
414
+ taxDisclaimer: response.taxDisclaimer,
415
+ number: response.number,
416
+ barcode: response.barcode,
417
+ instruction: response.instruction,
418
+ offers: response.offers,
419
+ error: response.error,
420
+ errors: response.errors,
421
+ restrictions: response.restrictions,
422
+ info: response.info,
423
+ buyData: response.buyData,
424
+ pid: response.pid,
425
+ messages: response.messages ?? [],
426
+ title: response.title,
427
+ summary: response.summary,
428
+ skipForm: response.skipForm,
429
+ isSavedMethodPayment: !!response.form?.saved_method_id,
430
+ couponCode: response.form?.couponCode?.value || '',
431
+ publicId: response.public_id,
432
+ skipCheckout: response.skipCheckout,
433
+ koreaNotification: response.form.korea_limits_instruction,
434
+ isCheckout: response.isCheckout,
435
+ categories: response.categories,
436
+ hasFatalErrors: response.textAll?.fatal,
437
+ userSession: response.userSession,
438
+ statusText: response.status?.statusData?.stateText ?? null,
439
+ country: response.country ? response.country.iso : null,
440
+ };
441
+ }
442
+ }
443
+
444
+ const initializeResponseFactoryToken = new InjectionToken('InitializeResponse');
445
+ const initializeResponseFactoryProvider = {
446
+ provide: initializeResponseFactoryToken,
447
+ useValue: (...args) => new InitializeResponse(...args),
448
+ };
449
+
450
+ class InitializeService {
451
+ constructor(responseFactory, secureApi, settingsService, countryService) {
452
+ this.responseFactory = responseFactory;
453
+ this.secureApi = secureApi;
454
+ this.settingsService = settingsService;
455
+ this.countryService = countryService;
456
+ this.apiRoute = 'directpayment';
457
+ }
458
+ async request(config) {
459
+ const requestParams = {
460
+ access_token: this.settingsService.token,
461
+ pid: String(config.paymentMethodId),
462
+ country: this.countryService.getCountry(),
463
+ returnUrl: config.returnUrl,
464
+ };
465
+ return lastValueFrom(this.secureApi
466
+ .post(this.apiRoute, new URLSearchParams({ ...requestParams }), {
467
+ headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
468
+ responseType: 'json',
469
+ })
470
+ .pipe(map((response) => this.responseFactory(response)))).catch((error) => {
471
+ throw new ResponseError(error.message);
472
+ });
473
+ }
474
+ }
475
+ InitializeService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, deps: [{ token: initializeResponseFactoryToken }, { token: SecureApiClient }, { token: SettingsService }, { token: CountryService }], target: i0.ɵɵFactoryTarget.Injectable });
476
+ InitializeService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, providedIn: 'root' });
477
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, decorators: [{
478
+ type: Injectable,
479
+ args: [{
480
+ providedIn: 'root',
481
+ }]
482
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
483
+ type: Inject,
484
+ args: [initializeResponseFactoryToken]
485
+ }] }, { type: SecureApiClient }, { type: SettingsService }, { type: CountryService }]; } });
486
+
487
+ class XpsApiPartRequest {
488
+ addXpsParameters(parameters) {
489
+ for (const key in parameters) {
490
+ this[`xps_${key}`] = parameters[key];
491
+ }
492
+ }
493
+ }
494
+
495
+ class TokenError extends AppError {
496
+ constructor() {
497
+ super('XPS API needs token.');
498
+ }
499
+ }
500
+
501
+ class SubmitRequest extends XpsApiPartRequest {
502
+ constructor(parameters) {
503
+ super();
504
+ const { token, dfpHash } = parameters;
505
+ if (token === null) {
506
+ throw new TokenError();
507
+ }
508
+ this.access_token = token;
509
+ if (dfpHash) {
510
+ this.xps_dfp_hash = dfpHash;
511
+ }
512
+ }
513
+ }
514
+
515
+ const submitRequestFactoryToken = new InjectionToken('SubmitRequest');
516
+ const submitRequestFactoryProvider = {
517
+ provide: submitRequestFactoryToken,
518
+ useValue: (...args) => new SubmitRequest(...args),
519
+ };
520
+
521
+ var XpsCommand;
522
+ (function (XpsCommand) {
523
+ XpsCommand["form"] = "form";
524
+ XpsCommand["check"] = "check";
525
+ XpsCommand["status"] = "status";
526
+ XpsCommand["checkout"] = "checkout";
527
+ XpsCommand["account"] = "account";
528
+ XpsCommand["create"] = "create";
529
+ })(XpsCommand || (XpsCommand = {}));
530
+
531
+ var FieldNames;
532
+ (function (FieldNames) {
533
+ FieldNames["address1"] = "address1";
534
+ FieldNames["address2"] = "address2";
535
+ FieldNames["address"] = "address";
536
+ FieldNames["allowRecurrentSubscription"] = "allowRecurrentSubscription";
537
+ FieldNames["allowSubscription"] = "allowSubscription";
538
+ FieldNames["apt"] = "apt";
539
+ FieldNames["availableCardTypes"] = "available_card_types";
540
+ FieldNames["bank"] = "bank";
541
+ FieldNames["birthDate"] = "birth_date";
542
+ FieldNames["cardMonth"] = "card_month";
543
+ FieldNames["cardYear"] = "card_year";
544
+ FieldNames["cardNumber"] = "card_number";
545
+ FieldNames["cardholdername"] = "cardholdername";
546
+ FieldNames["city"] = "city";
547
+ FieldNames["couponCode"] = "couponCode";
548
+ FieldNames["cpfName"] = "cpf_name";
549
+ FieldNames["cpfNumber"] = "cpf_number";
550
+ FieldNames["cvv"] = "cvv";
551
+ FieldNames["description"] = "description";
552
+ FieldNames["email"] = "email";
553
+ FieldNames["psEmail"] = "psEmail";
554
+ FieldNames["euCheck"] = "eu_check";
555
+ FieldNames["extraCvv"] = "extra_cvv";
556
+ FieldNames["extraCardNumber"] = "extra_card_number";
557
+ FieldNames["extraCardType"] = "extra_card_type";
558
+ FieldNames["fName"] = "f_name";
559
+ FieldNames["installments"] = "installments";
560
+ FieldNames["lName"] = "l_name";
561
+ FieldNames["needInstallments"] = "needInstallments";
562
+ FieldNames["personId"] = "person_id";
563
+ FieldNames["personIdAr"] = "person_id_ar";
564
+ FieldNames["personIdCo"] = "person_id_co";
565
+ FieldNames["phone"] = "phone";
566
+ FieldNames["purchaseDescription"] = "purchaseDescription";
567
+ FieldNames["recurrentType"] = "recurrent_type";
568
+ FieldNames["rockstarTaxes"] = "rockstar_taxes";
569
+ FieldNames["state"] = "state";
570
+ FieldNames["street"] = "street";
571
+ FieldNames["streetNumber"] = "street_number";
572
+ FieldNames["take2Taxes"] = "take2_taxes";
573
+ FieldNames["termsAndConditions"] = "termsAndConditions";
574
+ FieldNames["termsAndConditionsAtariPp"] = "termsAndConditionsAtariPP";
575
+ FieldNames["termsAndConditionsAtariTc"] = "termsAndConditionsAtariTC";
576
+ FieldNames["termsAndConditionsHtcEula"] = "termsAndConditionsHtcEula";
577
+ FieldNames["termsAndConditionsRobloxEula"] = "termsAndConditionsRobloxEula";
578
+ FieldNames["termsAndConditionsRolandEula"] = "termsAndConditionsRolandEula";
579
+ FieldNames["termsAndConditionsDeusLoVultEula"] = "termsAndConditionsDeusLoVultEula";
580
+ FieldNames["termsAndConditionsOnzenga"] = "termsAndConditionsOnzenga";
581
+ FieldNames["xsollaTipsAmount"] = "xsollaTipsAmount";
582
+ FieldNames["zip"] = "zip";
583
+ FieldNames["allowSave"] = "allowSave";
584
+ FieldNames["koreaLimitsInstruction"] = "korea_limits_instruction";
585
+ FieldNames["tokenApplePay"] = "token_applepay";
586
+ FieldNames["fixInvoice"] = "fix_invoice";
587
+ FieldNames["fixPid"] = "fix_pid";
588
+ FieldNames["signature"] = "signature";
589
+ FieldNames["qr"] = "qr";
590
+ FieldNames["sum"] = "sum";
591
+ FieldNames["out"] = "out";
592
+ FieldNames["tinkoffDisclaimer"] = "ps.tinkoff.disclaimer";
593
+ })(FieldNames || (FieldNames = {}));
594
+
595
+ class SubmitResponse {
596
+ constructor(parameters, responseNumber = 0) {
597
+ this.responseNumber = responseNumber;
598
+ /* Todo split into properties */
599
+ this.parameters = parameters;
600
+ this.fields = Object.keys(parameters.form).map((key) => parameters.form[key]);
601
+ if (parameters.onlineBanking) {
602
+ this.onlineBanking = {
603
+ url: parameters.onlineBanking.value,
604
+ };
605
+ }
606
+ this.isNeedRedirect =
607
+ parameters.currentCommand === XpsCommand.account ||
608
+ (parameters.currentCommand === XpsCommand.checkout &&
609
+ Boolean(parameters.checkout));
610
+ this.buyData = parameters.buyData;
611
+ this.fixInvoice = this.fields.find((field) => field.name === FieldNames.fixInvoice)?.value;
612
+ this.signature = this.fields.find((field) => field.name === FieldNames.signature)?.value;
613
+ this.hasFatalErrors = parameters.textAll?.fatal;
614
+ this.userSession = parameters.userSession;
615
+ this.pid = parameters.pid;
616
+ this.errors = parameters.errors;
617
+ this.summary = parameters.summary;
618
+ this.title = parameters.title;
619
+ this.currentCommand = parameters.currentCommand;
620
+ this.messages = parameters.messages;
621
+ }
622
+ }
623
+
624
+ const submitResponseFactoryToken = new InjectionToken('SubmitResponse');
625
+ const submitResponseFactoryProvider = {
626
+ provide: submitResponseFactoryToken,
627
+ useValue: (...args) => new SubmitResponse(...args),
628
+ };
629
+
630
+ class TerminalError extends AppError {
631
+ constructor(message, code) {
632
+ super(message);
633
+ this.code = code;
634
+ }
635
+ }
636
+
637
+ class DefaultTerminalError extends TerminalError {
638
+ constructor() {
639
+ const message = `It's not you, it's us, but we can help. Please contact our customer support.`;
640
+ super(message, '1000-0002');
641
+ }
642
+ }
643
+
644
+ class DeviceFingerPrintService {
645
+ constructor(secureApi, settingsService, window) {
646
+ this.secureApi = secureApi;
647
+ this.settingsService = settingsService;
648
+ this.window = window;
649
+ this.apiRoute = 'dfp';
650
+ this.fingerprintApiUrl = 'https://afs.xsolla.com/dfp/api/v1/';
651
+ }
652
+ async init() {
653
+ if (!this.settingsService.isInitialized) {
654
+ return;
655
+ }
656
+ this.fingerprintJs = await this.loadFingerprintJs();
657
+ this.hash = await this.buildHash();
658
+ this.antifraudFingerprintLibrary =
659
+ await this.loadAntifraudFingerprintLibrary();
660
+ }
661
+ // eslint-disable-next-line @typescript-eslint/require-await
662
+ async getHash() {
663
+ return this.hash;
664
+ }
665
+ async loadFingerprintJs() {
666
+ const { default: library, murmurX64Hash128: getHash } = await import('@fingerprintjs/fingerprintjs');
667
+ return { library, getHash };
668
+ }
669
+ async loadAntifraudFingerprintLibrary() {
670
+ const library = await import('@xsolla/antifraud-fingerprint');
671
+ return library.default;
672
+ }
673
+ // eslint-disable-next-line @typescript-eslint/require-await
674
+ async makeAntifraudFingerprint() {
675
+ if (!this.settingsService.token) {
676
+ return null;
677
+ }
678
+ const antifraudFingerprint = this.antifraudFingerprintLibrary;
679
+ try {
680
+ return new antifraudFingerprint({
681
+ api: {
682
+ url: this.fingerprintApiUrl,
683
+ token: this.settingsService.token,
684
+ timeout: 3000,
685
+ },
686
+ retry: {
687
+ num: 1,
688
+ timeout: 500,
689
+ },
690
+ });
691
+ }
692
+ catch (error) {
693
+ return null;
694
+ }
695
+ }
696
+ /**
697
+ *Загружаем библиотеку, генерируем данные,
698
+ *хешируем с помощью BASE64 и отправляем на бэкенд,
699
+ *в ответ получаем dfp_hash.
700
+ **/
701
+ async buildHash() {
702
+ const fingerPrintData = await this.generate();
703
+ const hash = await this.send(fingerPrintData).catch(() => {
704
+ return null;
705
+ });
706
+ return JSON.stringify(hash);
707
+ }
708
+ /**
709
+ *Новая версия библиотеки содержит не все компоненты, некоторые приходится имплементировать самостоятельно
710
+ **/
711
+ getHasLiedResolution() {
712
+ const { screen } = this.window;
713
+ return (screen.width < screen.availWidth || screen.height < screen.availHeight);
714
+ }
715
+ /**
716
+ *Бэкенд заточен под конкретные поля, которые необходимо смапить.
717
+ **/
718
+ getComponents(components) {
719
+ return {
720
+ user_agent: navigator.userAgent,
721
+ language: components.languages.value?.shift()?.shift() ?? '',
722
+ color_depth: components.colorDepth.value,
723
+ device_memory: components.deviceMemory.value,
724
+ hardware_concurrency: components.hardwareConcurrency.value,
725
+ resolution: components.screenResolution.value,
726
+ available_resolution: components.screenResolution.value,
727
+ timezone_offset: new Date().getTimezoneOffset(),
728
+ session_storage: components.sessionStorage.value ? 1 : 0,
729
+ local_storage: components.localStorage.value ? 1 : 0,
730
+ indexed_db: components.indexedDB.value ? 1 : 0,
731
+ open_database: components.openDatabase.value ? 1 : 0,
732
+ navigator_platform: components.platform.value,
733
+ regular_plugins: components.plugins.value?.map((plugin) => plugin.name) ?? [],
734
+ canvas: components.canvas.value?.text,
735
+ webgl: components.canvas.value?.text,
736
+ webgl_vendor: components.vendor.value,
737
+ has_lied_resolution: this.getHasLiedResolution(),
738
+ touch_support: Object.values(components.touchSupport.value ?? {}),
739
+ js_fonts: components.fonts.value,
740
+ };
741
+ }
742
+ /**
743
+ * Получаем данные dfp с помощью FingerprintJS, мапим необходимые поля, добавляем хэш
744
+ **/
745
+ async generate() {
746
+ const { library, getHash } = this.fingerprintJs;
747
+ const fingerprint = await library.load();
748
+ const commonFingerPrintData = await fingerprint.get();
749
+ const fingerPrintData = this.getComponents(commonFingerPrintData.components);
750
+ fingerPrintData.hash = getHash(JSON.stringify(fingerPrintData));
751
+ return fingerPrintData;
752
+ }
753
+ /**
754
+ * Отправка dfp на сервер, в ответ получаем dfp_hash
755
+ **/
756
+ async send(fingerPrintData) {
757
+ const token = this.settingsService.token;
758
+ if (token === null) {
759
+ throw new DefaultTerminalError();
760
+ }
761
+ const requestBody = {
762
+ access_token: token,
763
+ 'dfp[200]': '',
764
+ };
765
+ requestBody['dfp[200]'] = btoa(encodeURIComponent(JSON.stringify(fingerPrintData)));
766
+ return lastValueFrom(this.secureApi.post(this.apiRoute, new URLSearchParams(requestBody), {
767
+ headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
768
+ responseType: 'json',
769
+ }))
770
+ .then((response) => {
771
+ return response.dfp_hash;
772
+ })
773
+ .then(async (hash) => {
774
+ const fingerprint = await this.makeAntifraudFingerprint();
775
+ if (!fingerprint) {
776
+ return null;
777
+ }
778
+ await fingerprint
779
+ ?.dispatch(hash['200'])
780
+ .catch((err) => console.log(err));
781
+ const afsHash = await fingerprint.hash();
782
+ return { '301': afsHash, ...hash };
783
+ })
784
+ .catch((error) => {
785
+ const response = error.getHttpErrorData().response;
786
+ throw new TerminalError(response.data?.errors[0]?.message ?? '', response.data?.errors[0]?.support_code ?? '');
787
+ });
788
+ }
789
+ }
790
+ DeviceFingerPrintService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: DeviceFingerPrintService, deps: [{ token: SecureApiClient }, { token: SettingsService }, { token: windowToken }], target: i0.ɵɵFactoryTarget.Injectable });
791
+ DeviceFingerPrintService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: DeviceFingerPrintService, providedIn: 'root' });
792
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: DeviceFingerPrintService, decorators: [{
793
+ type: Injectable,
794
+ args: [{
795
+ providedIn: 'root',
796
+ }]
797
+ }], ctorParameters: function () { return [{ type: SecureApiClient }, { type: SettingsService }, { type: undefined, decorators: [{
798
+ type: Inject,
799
+ args: [windowToken]
800
+ }] }]; } });
801
+
802
+ class SubmitService {
803
+ constructor(requestFactory, responseFactory, settingsService, deviceFingerPrintService, secureApi) {
804
+ this.requestFactory = requestFactory;
805
+ this.responseFactory = responseFactory;
806
+ this.settingsService = settingsService;
807
+ this.deviceFingerPrintService = deviceFingerPrintService;
808
+ this.secureApi = secureApi;
809
+ this.directPaymentApiRoute = 'directpayment';
810
+ }
811
+ // NB: Never add 'async' statement for this method!
812
+ // 'Async' statement wraps current promise into another.
813
+ // In this way two promises become unequal, that can broke XPS API requests logic.
814
+ // eslint-disable-next-line @typescript-eslint/promise-function-async
815
+ request(fields, form) {
816
+ const responsePromise = this.deviceFingerPrintService
817
+ .getHash()
818
+ // eslint-disable-next-line @typescript-eslint/promise-function-async
819
+ .then((dfpHash) => {
820
+ const request = this.requestFactory({
821
+ token: this.settingsService.token,
822
+ fields,
823
+ form,
824
+ dfpHash,
825
+ });
826
+ return lastValueFrom(this.secureApi.post(this.directPaymentApiRoute, request, {
827
+ headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
828
+ responseType: 'json',
829
+ }))
830
+ .then((response) => this.responseFactory(response))
831
+ .catch((error) => {
832
+ throw new ResponseError(error.message);
833
+ });
834
+ });
835
+ return responsePromise;
836
+ }
837
+ }
838
+ SubmitService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SubmitService, deps: [{ token: submitRequestFactoryToken }, { token: submitResponseFactoryToken }, { token: SettingsService }, { token: DeviceFingerPrintService }, { token: SecureApiClient }], target: i0.ɵɵFactoryTarget.Injectable });
839
+ SubmitService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SubmitService, providedIn: 'root' });
840
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SubmitService, decorators: [{
841
+ type: Injectable,
842
+ args: [{ providedIn: 'root' }]
843
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
844
+ type: Inject,
845
+ args: [submitRequestFactoryToken]
846
+ }] }, { type: undefined, decorators: [{
847
+ type: Inject,
848
+ args: [submitResponseFactoryToken]
849
+ }] }, { type: SettingsService }, { type: DeviceFingerPrintService }, { type: SecureApiClient }]; } });
850
+
851
+ class XpsRequest {
852
+ addXpsParameters(parameters) {
853
+ for (const key in parameters) {
854
+ this[`xps_${key}`] = parameters[key];
855
+ }
856
+ }
857
+ }
858
+
859
+ /* eslint-disable @typescript-eslint/naming-convention */
860
+ class SyncRequest extends XpsRequest {
861
+ constructor(parameters) {
862
+ super();
863
+ this.xps_fix_command = 'calculate';
864
+ this.access_token = parameters.token;
865
+ const fieldsValues = this.getFieldsValues(parameters.changedField, parameters.fields, parameters.form);
866
+ this.addXpsParameters({
867
+ ...fieldsValues,
868
+ change_element: parameters.changedField.name,
869
+ });
870
+ }
871
+ getFieldsValues(changedField, fields, form) {
872
+ const fieldsMap = this.getFieldsMap(fields);
873
+ return changedField?.javascript?.change.params.reduce((xpsParams, fieldName) => {
874
+ const formControl = form.get(fieldName);
875
+ const field = fieldsMap.get(fieldName);
876
+ if (formControl || field) {
877
+ xpsParams[fieldName] = formControl?.value ?? field?.value;
878
+ }
879
+ return xpsParams;
880
+ }, {});
881
+ }
882
+ getFieldsMap(fields) {
883
+ const map = new Map();
884
+ fields.forEach((field) => map.set(field.name, field));
885
+ return map;
886
+ }
887
+ }
888
+
889
+ const syncRequestFactoryToken = new InjectionToken('SyncRequest');
890
+ const syncRequestFactoryProvider = {
891
+ provide: syncRequestFactoryToken,
892
+ useValue: (...args) => new SyncRequest(...args),
893
+ };
894
+
895
+ class SyncResponse {
896
+ constructor(changedField, response) {
897
+ const fieldError = response?.errors?.find((error) => error.element_name === changedField.name);
898
+ if (fieldError) {
899
+ this.rewritableError = {
900
+ code: fieldError.code,
901
+ message: fieldError.message,
902
+ };
903
+ }
904
+ this.fields = Object.keys(response.form).map((key) => response.form[key]);
905
+ this.parameters = response;
906
+ }
907
+ }
908
+
909
+ const syncResponseFactoryToken = new InjectionToken('SyncResponse');
910
+ const syncResponseFactoryProvider = {
911
+ provide: syncResponseFactoryToken,
912
+ useValue: (...args) => new SyncResponse(...args),
913
+ };
914
+
915
+ class SyncService {
916
+ constructor(requestFactory, responseFactory, secureApi, settingsService) {
917
+ this.requestFactory = requestFactory;
918
+ this.responseFactory = responseFactory;
919
+ this.secureApi = secureApi;
920
+ this.settingsService = settingsService;
921
+ this.apiRoute = 'directpayment';
922
+ this.prevFieldSyncStates = {};
923
+ this.form = new UntypedFormGroup({});
924
+ this.fields = [];
925
+ }
926
+ setup(form, fields) {
927
+ this.reset();
928
+ this.form = form;
929
+ this.fields = fields;
930
+ }
931
+ reset() {
932
+ this.prevFieldSyncStates = {};
933
+ this.form = new UntypedFormGroup({});
934
+ this.fields = [];
935
+ }
936
+ async validate(field) {
937
+ if (!this.isReadyField(field)) {
938
+ return Promise.resolve(null);
939
+ }
940
+ const control = this.form.get(field.name);
941
+ const value = control?.value;
942
+ const prevFieldState = this.getPrevFieldSyncState(field);
943
+ const isInitialValue = value === field.value && !prevFieldState;
944
+ if (isInitialValue) {
945
+ return Promise.resolve(null);
946
+ }
947
+ if (prevFieldState && value === prevFieldState.value) {
948
+ return Promise.resolve(prevFieldState.result);
949
+ }
950
+ const requestPromise = this.request(field);
951
+ this.setPrevFieldSyncState(field, value, requestPromise);
952
+ return requestPromise.then((response) => {
953
+ return response.rewritableError ?? null;
954
+ });
955
+ }
956
+ async request(field) {
957
+ const requestParams = this.requestFactory({
958
+ token: this.settingsService.token,
959
+ changedField: field,
960
+ fields: this.fields,
961
+ form: this.form,
962
+ });
963
+ return lastValueFrom(this.secureApi.post(this.apiRoute, new URLSearchParams(requestParams), {
964
+ headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
965
+ responseType: 'json',
966
+ })).then((response) => {
967
+ return this.responseFactory(field, response);
968
+ });
969
+ }
970
+ isReadyField(field) {
971
+ const isSyncEnabled = !!field.javascript?.change;
972
+ const isExistsInForm = !!this.form?.get(field.name);
973
+ return isSyncEnabled && isExistsInForm;
974
+ }
975
+ getPrevFieldSyncState(field) {
976
+ return this.prevFieldSyncStates[field.name];
977
+ }
978
+ setPrevFieldSyncState(field, value, result) {
979
+ this.prevFieldSyncStates[field.name] = { value, result };
980
+ }
981
+ }
982
+ SyncService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SyncService, deps: [{ token: syncRequestFactoryToken }, { token: syncResponseFactoryToken }, { token: SecureApiClient }, { token: SettingsService }], target: i0.ɵɵFactoryTarget.Injectable });
983
+ SyncService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SyncService, providedIn: 'root' });
984
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SyncService, decorators: [{
985
+ type: Injectable,
986
+ args: [{
987
+ providedIn: 'root',
988
+ }]
989
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
990
+ type: Inject,
991
+ args: [syncRequestFactoryToken]
992
+ }] }, { type: undefined, decorators: [{
993
+ type: Inject,
994
+ args: [syncResponseFactoryToken]
995
+ }] }, { type: SecureApiClient }, { type: SettingsService }]; } });
996
+
997
+ class ControlConfig {
998
+ constructor() {
999
+ this.shouldHideUserInput = false;
1000
+ }
1001
+ }
1002
+
1003
+ class TextControlConfig extends ControlConfig {
1004
+ constructor() {
1005
+ super(...arguments);
1006
+ this.controlType = 'text';
1007
+ }
1008
+ }
1009
+
1010
+ function convert(validator, message) {
1011
+ return (control) => {
1012
+ const errors = validator(control);
1013
+ if (!errors) {
1014
+ return errors;
1015
+ }
1016
+ const firstErrorKey = Object.keys(errors)[0];
1017
+ let error = errors[firstErrorKey];
1018
+ error = typeof error === 'object' && error !== null ? error : {};
1019
+ const rewritableError = { ...error };
1020
+ rewritableError.message = message;
1021
+ if (error[firstErrorKey] != null) {
1022
+ rewritableError.value = error[firstErrorKey];
1023
+ }
1024
+ if (rewritableError.requiredLength) {
1025
+ rewritableError.number = rewritableError.requiredLength;
1026
+ }
1027
+ errors.rewritableError = rewritableError;
1028
+ return errors;
1029
+ };
1030
+ }
1031
+
1032
+ const emailRegexp = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i; // eslint-disable-line
1033
+ function emailValidator() {
1034
+ return convert(Validators.pattern(emailRegexp), 'Enter a valid email');
1035
+ }
1036
+
1037
+ function requiredValidator() {
1038
+ return convert(Validators.required, 'Required');
1039
+ }
1040
+
1041
+ class Converter {
1042
+ constructor(syncService) {
1043
+ this.syncService = syncService;
1044
+ }
1045
+ convertToConfig(field, formState) {
1046
+ const config = this.createControlConfig(field, formState);
1047
+ if (formState?.disabled) {
1048
+ config.disabled = true;
1049
+ }
1050
+ return config;
1051
+ }
1052
+ convertToFormControl(field) {
1053
+ return new UntypedFormControl(this.getValue(field), this.getValidators(field), this.getAsyncValidators(field));
1054
+ }
1055
+ getValidators(field) {
1056
+ const validators = [];
1057
+ if (field.isMandatory === "1" /* XpsBoolean.true */) {
1058
+ validators.push(requiredValidator());
1059
+ }
1060
+ if (field.regex) {
1061
+ const match = /^\/(.*)\/([gim]*)$/.exec(field.regex);
1062
+ if (match) {
1063
+ const pattern = new RegExp(match[1], match[2]);
1064
+ const errorMessage = field.validation_error_msg
1065
+ ? field.validation_error_msg
1066
+ : 'Enter valid data';
1067
+ validators.push(convert(Validators.pattern(pattern), errorMessage));
1068
+ }
1069
+ }
1070
+ return validators;
1071
+ }
1072
+ getAsyncValidators(field) {
1073
+ return async () => this.syncService.validate(field);
1074
+ }
1075
+ createDefaultControlConfig(controlConfigClass, field) {
1076
+ const config = new controlConfigClass();
1077
+ this.copyCommonOptions(config, field);
1078
+ return config;
1079
+ }
1080
+ getValue(field) {
1081
+ return field.value;
1082
+ }
1083
+ getDataType() {
1084
+ return 'text';
1085
+ }
1086
+ getAutocomplete() {
1087
+ return 'off';
1088
+ }
1089
+ shouldHideUserInput() {
1090
+ return false;
1091
+ }
1092
+ getCommonControlConfig(field) {
1093
+ return {
1094
+ name: field.name,
1095
+ title: field.title,
1096
+ labelHint: field.label_hint,
1097
+ dataType: this.getDataType(),
1098
+ readonly: field.isReadonly === "1" /* XpsBoolean.true */,
1099
+ placeholder: field.example,
1100
+ autocomplete: this.getAutocomplete(),
1101
+ };
1102
+ }
1103
+ copyCommonOptions(target, field) {
1104
+ const commonControlConfig = this.getCommonControlConfig(field);
1105
+ Object.keys(commonControlConfig).forEach((sourceKey) => {
1106
+ if (!(sourceKey in target)) {
1107
+ target[sourceKey] = commonControlConfig[sourceKey];
1108
+ }
1109
+ });
1110
+ }
1111
+ }
1112
+
1113
+ class EmailConverter extends Converter {
1114
+ constructor(syncService) {
1115
+ super(syncService);
1116
+ }
1117
+ getValidators(field) {
1118
+ return super.getValidators(field).concat([emailValidator()]);
1119
+ }
1120
+ createControlConfig(field) {
1121
+ const config = this.createDefaultControlConfig(TextControlConfig, field);
1122
+ config.autocomplete = 'email';
1123
+ config.icon = 'mail';
1124
+ return config;
1125
+ }
1126
+ getDataType() {
1127
+ return 'email';
1128
+ }
1129
+ }
1130
+ EmailConverter.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: EmailConverter, deps: [{ token: SyncService }], target: i0.ɵɵFactoryTarget.Injectable });
1131
+ EmailConverter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: EmailConverter });
1132
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: EmailConverter, decorators: [{
1133
+ type: Injectable
1134
+ }], ctorParameters: function () { return [{ type: SyncService }]; } });
1135
+
1136
+ const restrictedValueValidator = (restrictedValue) => {
1137
+ return ({ value }) => {
1138
+ return value !== restrictedValue ? null : { valueAllowed: false };
1139
+ };
1140
+ };
1141
+
1142
+ class ZipConverter extends Converter {
1143
+ constructor(syncService, countryService) {
1144
+ super(syncService);
1145
+ this.countryService = countryService;
1146
+ this.minLength = 3;
1147
+ this.maxLength = 10;
1148
+ this.usCountryLength = 5;
1149
+ }
1150
+ get isUsCountry() {
1151
+ return this.countryService.getCountry() === 'US';
1152
+ }
1153
+ getValidators(field) {
1154
+ const minLength = this.isUsCountry ? this.usCountryLength : this.minLength;
1155
+ const maxLength = this.isUsCountry ? this.usCountryLength : this.maxLength;
1156
+ const validators = super
1157
+ .getValidators(field)
1158
+ .concat([
1159
+ convert(Validators.minLength(minLength), 'Enter at least ${minLength} characters'),
1160
+ convert(Validators.maxLength(maxLength), 'Enter no more than ${maxLength} characters'),
1161
+ ]);
1162
+ if (this.isUsCountry) {
1163
+ validators.push(convert(restrictedValueValidator('00000'), 'Enter a valid ZIP code'));
1164
+ }
1165
+ return validators;
1166
+ }
1167
+ createControlConfig(field) {
1168
+ const config = this.createDefaultControlConfig(TextControlConfig, field);
1169
+ config.icon = 'location';
1170
+ if (this.isUsCountry) {
1171
+ config.maskConfig = {
1172
+ mask: () => new Array(this.usCountryLength).fill('9').join(''),
1173
+ guide: false,
1174
+ unmaskModelValue: true,
1175
+ showMask: true,
1176
+ };
1177
+ config.inputMode = 'numeric';
1178
+ }
1179
+ else {
1180
+ config.maxLength = this.maxLength;
1181
+ }
1182
+ return config;
1183
+ }
1184
+ getAutocomplete() {
1185
+ return 'postal-code';
1186
+ }
1187
+ getDataType() {
1188
+ return 'text';
1189
+ }
1190
+ }
1191
+ ZipConverter.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ZipConverter, deps: [{ token: SyncService }, { token: CountryService }], target: i0.ɵɵFactoryTarget.Injectable });
1192
+ ZipConverter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ZipConverter });
1193
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ZipConverter, decorators: [{
1194
+ type: Injectable
1195
+ }], ctorParameters: function () { return [{ type: SyncService }, { type: CountryService }]; } });
1196
+
1197
+ const convertersMapToken = new InjectionToken('ConvertersTokensMap');
1198
+ const convertersMap = {
1199
+ zip: ZipConverter,
1200
+ email: EmailConverter,
1201
+ };
1202
+
1203
+ class ControlConfigService {
1204
+ constructor(convertersMap, injector) {
1205
+ this.convertersMap = convertersMap;
1206
+ this.injector = injector;
1207
+ }
1208
+ getFormControl(field) {
1209
+ const converter = this.getConverter(field);
1210
+ if (!converter) {
1211
+ return null;
1212
+ }
1213
+ return converter.convertToFormControl(field);
1214
+ }
1215
+ getConverter(field) {
1216
+ if (!field) {
1217
+ return null;
1218
+ }
1219
+ const sanitizedName = field.name.replace(/^fix_/i, '');
1220
+ let converter = this.convertersMap[sanitizedName];
1221
+ if (!converter) {
1222
+ converter = this.convertersMap[field.type];
1223
+ }
1224
+ if (!converter) {
1225
+ return null;
1226
+ }
1227
+ return this.injector.get(converter);
1228
+ }
1229
+ }
1230
+ ControlConfigService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ControlConfigService, deps: [{ token: convertersMapToken }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
1231
+ ControlConfigService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ControlConfigService });
1232
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ControlConfigService, decorators: [{
1233
+ type: Injectable
1234
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
1235
+ type: Inject,
1236
+ args: [convertersMapToken]
1237
+ }] }, { type: i0.Injector }]; } });
1238
+
1239
+ class FormService {
1240
+ constructor(controlConfigService) {
1241
+ this.controlConfigService = controlConfigService;
1242
+ }
1243
+ createForm(fields) {
1244
+ const controls = this.getVisibleFields(fields).reduce((result, field) => {
1245
+ const formControl = this.controlConfigService.getFormControl(field);
1246
+ if (formControl) {
1247
+ result[field.name] = formControl;
1248
+ }
1249
+ return result;
1250
+ }, {});
1251
+ return new UntypedFormGroup(controls);
1252
+ }
1253
+ getVisibleFields(fields) {
1254
+ return fields.filter(({ isVisible }) => isVisible === "1" /* XpsBoolean.true */);
1255
+ }
1256
+ }
1257
+ FormService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: FormService, deps: [{ token: ControlConfigService }], target: i0.ɵɵFactoryTarget.Injectable });
1258
+ FormService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: FormService });
1259
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: FormService, decorators: [{
1260
+ type: Injectable
1261
+ }], ctorParameters: function () { return [{ type: ControlConfigService }]; } });
1262
+
1263
+ class ShowFieldsAction {
1264
+ constructor(submitResponse) {
1265
+ this.type = 'show_fields';
1266
+ this.data = {
1267
+ fields: [],
1268
+ errors: [],
1269
+ messages: [],
1270
+ order: {},
1271
+ };
1272
+ this.data.fields = submitResponse.fields;
1273
+ this.data.errors = submitResponse.errors;
1274
+ this.data.messages = submitResponse.messages;
1275
+ this.data.order = submitResponse.summary;
1276
+ }
1277
+ }
1278
+
1279
+ const showFieldsActionFactoryToken = new InjectionToken('ShowFieldsAction');
1280
+ const showFieldsActionFactoryProvider = {
1281
+ provide: showFieldsActionFactoryToken,
1282
+ useValue: {
1283
+ factory: (...args) => new ShowFieldsAction(...args),
1284
+ type: 'show_fields',
1285
+ },
1286
+ };
1287
+
1288
+ const nextActionsToken = new InjectionToken('Action');
1289
+ const nextActions = [showFieldsActionFactoryProvider];
1290
+
1291
+ const actionTypeCommandMap = {
1292
+ [XpsCommand.check]: 'show_fields',
1293
+ };
1294
+
1295
+ class NextActionService {
1296
+ constructor(nextActionTokens, injector) {
1297
+ this.nextActionTokens = nextActionTokens;
1298
+ this.injector = injector;
1299
+ this.nextActionsMap = new Map();
1300
+ this.fillNextActionsMap();
1301
+ }
1302
+ getNextAction(submitResponse) {
1303
+ if (!submitResponse.currentCommand) {
1304
+ return null;
1305
+ }
1306
+ const nextActionFactory = this.findNextAction(submitResponse.currentCommand);
1307
+ if (nextActionFactory) {
1308
+ return nextActionFactory(submitResponse);
1309
+ }
1310
+ throw new Error('Next action is undefined.');
1311
+ }
1312
+ fillNextActionsMap() {
1313
+ this.nextActionTokens.forEach((nextAction) => {
1314
+ const item = this.injector.get(nextAction.provide);
1315
+ this.nextActionsMap.set(item.type, item.factory);
1316
+ });
1317
+ }
1318
+ findNextAction(command) {
1319
+ const actionType = actionTypeCommandMap[command];
1320
+ if (!actionType) {
1321
+ return;
1322
+ }
1323
+ return this.nextActionsMap.get(actionType);
1324
+ }
1325
+ }
1326
+ NextActionService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: NextActionService, deps: [{ token: nextActionsToken }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
1327
+ NextActionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: NextActionService, providedIn: 'root' });
1328
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: NextActionService, decorators: [{
1329
+ type: Injectable,
1330
+ args: [{
1331
+ providedIn: 'root',
1332
+ }]
1333
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
1334
+ type: Inject,
1335
+ args: [nextActionsToken]
1336
+ }] }, { type: i0.Injector }]; } });
1337
+
1338
+ class PaymentService {
1339
+ constructor(initializeService, submitService, syncService, formService, nextActionService) {
1340
+ this.initializeService = initializeService;
1341
+ this.submitService = submitService;
1342
+ this.syncService = syncService;
1343
+ this.formService = formService;
1344
+ this.nextActionService = nextActionService;
1345
+ this.form = null;
1346
+ this.data = null;
1347
+ this.fields = [];
1348
+ }
1349
+ async initialize(config) {
1350
+ this.data = await this.initializeService.request(config);
1351
+ this.fields = this.getFields();
1352
+ this.form = this.formService.createForm(this.fields);
1353
+ this.syncService.setup(this.form, this.fields);
1354
+ return this.fields;
1355
+ }
1356
+ async submit(fields, form) {
1357
+ const submitResponse = await this.submitService.request(fields, form);
1358
+ return this.nextActionService.getNextAction(submitResponse);
1359
+ }
1360
+ getFields() {
1361
+ return this.data?.paymentForm?.fields ?? [];
1362
+ }
1363
+ async validate(field) {
1364
+ return this.syncService.validate(field);
1365
+ }
1366
+ runThreeDs() {
1367
+ throw new Error('Method not implemented.');
1368
+ }
1369
+ getFinanceDetails() {
1370
+ throw new Error('Method not implemented.');
1371
+ }
1372
+ getStatus() {
1373
+ throw new Error('Method not implemented.');
1374
+ }
1375
+ changeFieldValue(name, value) {
1376
+ const formControl = this.form?.get(name);
1377
+ formControl?.setValue(value);
1378
+ }
1379
+ }
1380
+ PaymentService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PaymentService, deps: [{ token: InitializeService }, { token: SubmitService }, { token: SyncService }, { token: FormService }, { token: NextActionService }], target: i0.ɵɵFactoryTarget.Injectable });
1381
+ PaymentService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PaymentService, providedIn: 'root' });
1382
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PaymentService, decorators: [{
1383
+ type: Injectable,
1384
+ args: [{
1385
+ providedIn: 'root',
1386
+ }]
1387
+ }], ctorParameters: function () { return [{ type: InitializeService }, { type: SubmitService }, { type: SyncService }, { type: FormService }, { type: NextActionService }]; } });
1388
+
400
1389
  class RefundPolicyService {
401
1390
  constructor(settingsService) {
402
1391
  this.settingsService = settingsService;
@@ -499,84 +1488,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
499
1488
  }]
500
1489
  }], ctorParameters: function () { return [{ type: SettingsService }, { type: RefundPolicyService }, { type: SecureConnectionService }, { type: DisclaimerService }]; } });
501
1490
 
502
- class InitializeService {
503
- constructor(secureApi, settingsService, countryService) {
504
- this.secureApi = secureApi;
505
- this.settingsService = settingsService;
506
- this.countryService = countryService;
507
- this.apiRoute = 'directpayment';
508
- }
509
- async request(config) {
510
- const requestParams = {
511
- access_token: this.settingsService.token,
512
- pid: String(config.paymentMethodId),
513
- country: this.countryService.getCountry(),
514
- returnUrl: config.returnUrl,
515
- };
516
- return lastValueFrom(this.secureApi.post(this.apiRoute, new URLSearchParams({ ...requestParams }), {
517
- headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
518
- responseType: 'json',
519
- })).catch((error) => {
520
- throw new ResponseError(error.message);
521
- });
522
- }
523
- }
524
- InitializeService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, deps: [{ token: SecureApiClient }, { token: SettingsService }, { token: CountryService }], target: i0.ɵɵFactoryTarget.Injectable });
525
- InitializeService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, providedIn: 'root' });
526
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, decorators: [{
527
- type: Injectable,
528
- args: [{
529
- providedIn: 'root',
530
- }]
531
- }], ctorParameters: function () { return [{ type: SecureApiClient }, { type: SettingsService }, { type: CountryService }]; } });
532
-
533
- class PaymentService {
534
- constructor(initializeService) {
535
- this.initializeService = initializeService;
536
- this.data = null;
537
- }
538
- async initialize(config) {
539
- this.data = await this.initializeService.request(config);
540
- return this.data;
541
- }
542
- submit() {
543
- throw new Error('Method not implemented.');
544
- }
545
- getFields() {
546
- throw new Error('Method not implemented.');
547
- }
548
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
549
- validate(field) {
550
- throw new Error('Method not implemented.');
551
- }
552
- runThreeDs() {
553
- throw new Error('Method not implemented.');
554
- }
555
- getFinanceDetails() {
556
- throw new Error('Method not implemented.');
557
- }
558
- getStatus() {
559
- throw new Error('Method not implemented.');
560
- }
561
- }
562
- PaymentService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PaymentService, deps: [{ token: InitializeService }], target: i0.ɵɵFactoryTarget.Injectable });
563
- PaymentService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PaymentService, providedIn: 'root' });
564
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PaymentService, decorators: [{
565
- type: Injectable,
566
- args: [{
567
- providedIn: 'root',
568
- }]
569
- }], ctorParameters: function () { return [{ type: InitializeService }]; } });
570
-
571
1491
  class CoreLibraryService {
572
- constructor(settingsService, countryService, paymentMethodsService, savedMethodsService, userBalanceService, legalService, paymentService) {
1492
+ constructor(settingsService, countryService, paymentMethodsService, savedMethodsService, userBalanceService, paymentService, deviceFingerPrintService, legalService) {
573
1493
  this.settingsService = settingsService;
574
1494
  this.countryService = countryService;
575
1495
  this.paymentMethodsService = paymentMethodsService;
576
1496
  this.savedMethodsService = savedMethodsService;
577
1497
  this.userBalanceService = userBalanceService;
578
- this.legalService = legalService;
579
1498
  this.paymentService = paymentService;
1499
+ this.deviceFingerPrintService = deviceFingerPrintService;
1500
+ this.legalService = legalService;
580
1501
  this.paymentMethods = {
581
1502
  getList: async () => this.paymentMethodsService.getList(),
582
1503
  getQuickMethods: async () => this.paymentMethodsService.getQuickMethods(),
@@ -585,7 +1506,8 @@ class CoreLibraryService {
585
1506
  };
586
1507
  }
587
1508
  async init(configuration) {
588
- return this.settingsService.init(configuration);
1509
+ await this.settingsService.init(configuration);
1510
+ await this.deviceFingerPrintService.init();
589
1511
  }
590
1512
  setCountry(country) {
591
1513
  this.countryService.setCountry(country);
@@ -593,9 +1515,10 @@ class CoreLibraryService {
593
1515
  createPayment(config) {
594
1516
  return {
595
1517
  initialize: async () => this.paymentService.initialize(config),
596
- submit: () => this.paymentService.submit(),
1518
+ submit: async (fields, form) => this.paymentService.submit(fields, form),
597
1519
  getFields: () => this.paymentService.getFields(),
598
- validate: (field) => this.paymentService.validate(field),
1520
+ changeFieldValue: (name, value) => this.paymentService.changeFieldValue(name, value),
1521
+ validate: async (field) => this.paymentService.validate(field),
599
1522
  getFinanceDetails: () => this.paymentService.getFinanceDetails(),
600
1523
  runThreeDs: () => this.paymentService.runThreeDs(),
601
1524
  getStatus: () => this.paymentService.getStatus(),
@@ -605,14 +1528,14 @@ class CoreLibraryService {
605
1528
  return this.legalService.getLegalComponentConfig();
606
1529
  }
607
1530
  }
608
- CoreLibraryService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryService, deps: [{ token: SettingsService }, { token: CountryService }, { token: PaymentMethodsService }, { token: SavedMethodsService }, { token: UserBalanceService }, { token: LegalService }, { token: PaymentService }], target: i0.ɵɵFactoryTarget.Injectable });
1531
+ CoreLibraryService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryService, deps: [{ token: SettingsService }, { token: CountryService }, { token: PaymentMethodsService }, { token: SavedMethodsService }, { token: UserBalanceService }, { token: PaymentService }, { token: DeviceFingerPrintService }, { token: LegalService }], target: i0.ɵɵFactoryTarget.Injectable });
609
1532
  CoreLibraryService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryService, providedIn: 'root' });
610
1533
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryService, decorators: [{
611
1534
  type: Injectable,
612
1535
  args: [{
613
1536
  providedIn: 'root',
614
1537
  }]
615
- }], ctorParameters: function () { return [{ type: SettingsService }, { type: CountryService }, { type: PaymentMethodsService }, { type: SavedMethodsService }, { type: UserBalanceService }, { type: LegalService }, { type: PaymentService }]; } });
1538
+ }], ctorParameters: function () { return [{ type: SettingsService }, { type: CountryService }, { type: PaymentMethodsService }, { type: SavedMethodsService }, { type: UserBalanceService }, { type: PaymentService }, { type: DeviceFingerPrintService }, { type: LegalService }]; } });
616
1539
 
617
1540
  class HttpError extends AppError {
618
1541
  constructor(error, req) {
@@ -669,10 +1592,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
669
1592
  type: Injectable
670
1593
  }], ctorParameters: function () { return [{ type: i1$1.Router }]; } });
671
1594
 
1595
+ class FormModule {
1596
+ }
1597
+ FormModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: FormModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1598
+ FormModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.7", ngImport: i0, type: FormModule, imports: [ReactiveFormsModule] });
1599
+ FormModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: FormModule, providers: [
1600
+ FormService,
1601
+ ControlConfigService,
1602
+ ZipConverter,
1603
+ EmailConverter,
1604
+ { provide: convertersMapToken, useValue: convertersMap },
1605
+ ], imports: [ReactiveFormsModule] });
1606
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: FormModule, decorators: [{
1607
+ type: NgModule,
1608
+ args: [{
1609
+ imports: [ReactiveFormsModule],
1610
+ providers: [
1611
+ FormService,
1612
+ ControlConfigService,
1613
+ ZipConverter,
1614
+ EmailConverter,
1615
+ { provide: convertersMapToken, useValue: convertersMap },
1616
+ ],
1617
+ }]
1618
+ }] });
1619
+
672
1620
  class CoreLibraryModule {
673
1621
  }
674
1622
  CoreLibraryModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
675
- CoreLibraryModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryModule, imports: [HttpClientModule] });
1623
+ CoreLibraryModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryModule, imports: [HttpClientModule, FormModule] });
676
1624
  CoreLibraryModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryModule, providers: [
677
1625
  {
678
1626
  provide: HTTP_INTERCEPTORS,
@@ -683,11 +1631,21 @@ CoreLibraryModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", versi
683
1631
  paymentMethodsResponseFactoryProvider,
684
1632
  savedMethodsResponseFactoryProvider,
685
1633
  userBalanceResponseFactoryProvider,
686
- ], imports: [HttpClientModule] });
1634
+ initializeResponseFactoryProvider,
1635
+ submitRequestFactoryProvider,
1636
+ submitResponseFactoryProvider,
1637
+ syncRequestFactoryProvider,
1638
+ syncResponseFactoryProvider,
1639
+ {
1640
+ provide: nextActionsToken,
1641
+ useValue: nextActions,
1642
+ },
1643
+ ...nextActions,
1644
+ ], imports: [HttpClientModule, FormModule] });
687
1645
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryModule, decorators: [{
688
1646
  type: NgModule,
689
1647
  args: [{
690
- imports: [HttpClientModule],
1648
+ imports: [HttpClientModule, FormModule],
691
1649
  providers: [
692
1650
  {
693
1651
  provide: HTTP_INTERCEPTORS,
@@ -698,6 +1656,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
698
1656
  paymentMethodsResponseFactoryProvider,
699
1657
  savedMethodsResponseFactoryProvider,
700
1658
  userBalanceResponseFactoryProvider,
1659
+ initializeResponseFactoryProvider,
1660
+ submitRequestFactoryProvider,
1661
+ submitResponseFactoryProvider,
1662
+ syncRequestFactoryProvider,
1663
+ syncResponseFactoryProvider,
1664
+ {
1665
+ provide: nextActionsToken,
1666
+ useValue: nextActions,
1667
+ },
1668
+ ...nextActions,
701
1669
  ],
702
1670
  }]
703
1671
  }] });