@xsolla/payment-client-core 0.1.4 → 0.1.5-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/esm2020/lib/core/device-finger-print/device-finger-print.service.mjs +26 -126
  2. package/esm2020/lib/core/device-finger-print/hash.type.mjs +1 -1
  3. package/esm2020/lib/core/encrypt-credit-card/encrypt-credit-card.service.mjs +72 -0
  4. package/esm2020/lib/core/encrypt-credit-card/encrypted-card.interface.mjs +2 -0
  5. package/esm2020/lib/core/encrypt-credit-card/open-card.interface.mjs +2 -0
  6. package/esm2020/lib/core/exceptions-handling/errors/encrypt-card-error.mjs +9 -0
  7. package/esm2020/lib/core/payment/actions/check-status/check-status.action.class.mjs +2 -3
  8. package/esm2020/lib/core/payment/actions/next-action.interface.mjs +1 -1
  9. package/esm2020/lib/core/payment/actions/next-actions.mjs +3 -1
  10. package/esm2020/lib/core/payment/actions/three-ds/three-ds.action.class.mjs +7 -0
  11. package/esm2020/lib/core/payment/actions/three-ds/three-ds.action.token.mjs +11 -0
  12. package/esm2020/lib/core/payment/actions/three-ds/three-ds.action.type.mjs +2 -0
  13. package/esm2020/lib/core/payment/credit-card-payment-methods-id.variable.mjs +15 -0
  14. package/esm2020/lib/core/payment/form/controls/phone-control.config.mjs +8 -0
  15. package/esm2020/lib/core/payment/form/converters/birth-date.converter.mjs +38 -0
  16. package/esm2020/lib/core/payment/form/converters/card-expiration.converter.mjs +36 -0
  17. package/esm2020/lib/core/payment/form/converters/cardholder-name.converter.mjs +25 -0
  18. package/esm2020/lib/core/payment/form/converters/converters-map.mjs +21 -1
  19. package/esm2020/lib/core/payment/form/converters/cpf-name-regex.variable.mjs +2 -0
  20. package/esm2020/lib/core/payment/form/converters/cpf-name.converter.mjs +34 -0
  21. package/esm2020/lib/core/payment/form/converters/cpf-number.converter.mjs +31 -0
  22. package/esm2020/lib/core/payment/form/converters/cvv.converter.mjs +50 -0
  23. package/esm2020/lib/core/payment/form/converters/phone.converter.mjs +37 -0
  24. package/esm2020/lib/core/payment/form/converters/street-number/street-number-from-state.interface.mjs +2 -0
  25. package/esm2020/lib/core/payment/form/converters/street-number/street-number.converter.mjs +28 -0
  26. package/esm2020/lib/core/payment/form/converters/text.converter.mjs +19 -0
  27. package/esm2020/lib/core/payment/form/form.module.mjs +28 -1
  28. package/esm2020/lib/core/payment/form/validators/birth-date.validator.mjs +37 -0
  29. package/esm2020/lib/core/payment/form/validators/max-length-validator.mjs +6 -0
  30. package/esm2020/lib/core/payment/form/validators/min-length-validator.mjs +6 -0
  31. package/esm2020/lib/core/payment/form/validators/phone-validator.mjs +6 -0
  32. package/esm2020/lib/core/payment/initialize/initialize-request-params.interface.mjs +1 -1
  33. package/esm2020/lib/core/payment/initialize/initialize.service.mjs +28 -19
  34. package/esm2020/lib/core/payment/initialize/response/initialize-response.class.mjs +43 -0
  35. package/esm2020/lib/core/payment/initialize/response/initialize-response.token.mjs +8 -0
  36. package/esm2020/lib/core/payment/payment.interface.mjs +1 -1
  37. package/esm2020/lib/core/payment/payment.service.mjs +19 -5
  38. package/esm2020/lib/core/payment/status/check-status/check-status.service.mjs +8 -13
  39. package/esm2020/lib/core/payment/status/check-status/response/check-status-response.class.mjs +1 -1
  40. package/esm2020/lib/core/payment/submit/submit.service.mjs +13 -16
  41. package/esm2020/lib/core/payment/sync/field-async-validation.interface.mjs +1 -1
  42. package/esm2020/lib/core/payment/sync/field-sync-state.interface.mjs +1 -1
  43. package/esm2020/lib/core/payment/sync/request/sync-request.class.mjs +31 -0
  44. package/esm2020/lib/core/payment/sync/request/sync-request.token.mjs +8 -0
  45. package/esm2020/lib/core/payment/sync/response/sync-response.class.mjs +17 -0
  46. package/esm2020/lib/core/payment/sync/response/sync-response.token.mjs +8 -0
  47. package/esm2020/lib/core/payment/sync/sync.service.mjs +15 -15
  48. package/esm2020/lib/core/payment/three-ds/api/notify-dfp-status/notify-dfp-status.service.mjs +49 -0
  49. package/esm2020/lib/core/payment/three-ds/api/notify-dfp-status/request/notify-dfp-status-request.class.mjs +8 -0
  50. package/esm2020/lib/core/payment/three-ds/api/notify-dfp-status/request/notify-dfp-status-request.token.mjs +8 -0
  51. package/esm2020/lib/core/payment/three-ds/api/status-three-ds/request/status-three-ds-request.class.mjs +7 -0
  52. package/esm2020/lib/core/payment/three-ds/api/status-three-ds/request/status-three-ds-request.token.mjs +8 -0
  53. package/esm2020/lib/core/payment/three-ds/api/status-three-ds/response/status-three-ds-response.class.mjs +7 -0
  54. package/esm2020/lib/core/payment/three-ds/api/status-three-ds/response/status-three-ds-response.token.mjs +8 -0
  55. package/esm2020/lib/core/payment/three-ds/api/status-three-ds/status-three-ds-response.interface.mjs +2 -0
  56. package/esm2020/lib/core/payment/three-ds/api/status-three-ds/status-three-ds.service.mjs +60 -0
  57. package/esm2020/lib/core/payment/three-ds/api/status-three-ds/status-types.enum.mjs +7 -0
  58. package/esm2020/lib/core/payment/three-ds/api/status-three-ds/three-ds-checkout-form.interface.mjs +2 -0
  59. package/esm2020/lib/core/payment/three-ds/dfp-collect/dfp-collect.service.mjs +105 -0
  60. package/esm2020/lib/core/payment/three-ds/reinsurance-check/reinsurance-check.service.mjs +41 -0
  61. package/esm2020/lib/core/payment/three-ds/reinsurance-check/timer.interface.mjs +2 -0
  62. package/esm2020/lib/core/payment/three-ds/three-ds-20/status-update.interface.mjs +2 -0
  63. package/esm2020/lib/core/payment/three-ds/three-ds-20/three-ds20.service.mjs +109 -0
  64. package/esm2020/lib/core/payment/three-ds/three-ds-form.interface.mjs +2 -0
  65. package/esm2020/lib/core/payment/three-ds/three-ds-status-websocket-types.enum.mjs +5 -0
  66. package/esm2020/lib/core/payment/three-ds/three-ds.service.mjs +40 -0
  67. package/esm2020/lib/core/payment/xps-api/xps-api.service.mjs +79 -0
  68. package/esm2020/lib/core/payment/xps-request-params.interface.mjs +2 -0
  69. package/esm2020/lib/core/payment/xps-request.interface.mjs +2 -0
  70. package/esm2020/lib/core/payment/xps-response.error.mjs +7 -0
  71. package/esm2020/lib/core/payment/xps-response.interface.mjs +1 -1
  72. package/esm2020/lib/core-library.module.mjs +13 -4
  73. package/esm2020/lib/core-library.service.mjs +2 -2
  74. package/fesm2015/xsolla-payment-client-core.mjs +1899 -1057
  75. package/fesm2015/xsolla-payment-client-core.mjs.map +1 -1
  76. package/fesm2020/xsolla-payment-client-core.mjs +1852 -1017
  77. package/fesm2020/xsolla-payment-client-core.mjs.map +1 -1
  78. package/lib/core/device-finger-print/device-finger-print.service.d.ts +3 -31
  79. package/lib/core/device-finger-print/hash.type.d.ts +1 -1
  80. package/lib/core/encrypt-credit-card/encrypt-credit-card.service.d.ts +16 -0
  81. package/lib/core/encrypt-credit-card/encrypted-card.interface.d.ts +6 -0
  82. package/lib/core/encrypt-credit-card/open-card.interface.d.ts +6 -0
  83. package/lib/core/exceptions-handling/errors/encrypt-card-error.d.ts +5 -0
  84. package/lib/core/payment/actions/next-action.interface.d.ts +2 -1
  85. package/lib/core/payment/actions/three-ds/three-ds.action.class.d.ts +8 -0
  86. package/lib/core/payment/actions/three-ds/three-ds.action.token.d.ts +4 -0
  87. package/lib/core/payment/actions/three-ds/three-ds.action.type.d.ts +5 -0
  88. package/lib/core/payment/credit-card-payment-methods-id.variable.d.ts +6 -0
  89. package/lib/core/payment/form/controls/phone-control.config.d.ts +6 -0
  90. package/lib/core/payment/form/converters/birth-date.converter.d.ts +13 -0
  91. package/lib/core/payment/form/converters/card-expiration.converter.d.ts +16 -0
  92. package/lib/core/payment/form/converters/cardholder-name.converter.d.ts +13 -0
  93. package/lib/core/payment/form/converters/cpf-name-regex.variable.d.ts +1 -0
  94. package/lib/core/payment/form/converters/cpf-name.converter.d.ts +13 -0
  95. package/lib/core/payment/form/converters/cpf-number.converter.d.ts +11 -0
  96. package/lib/core/payment/form/converters/cvv.converter.d.ts +18 -0
  97. package/lib/core/payment/form/converters/phone.converter.d.ts +13 -0
  98. package/lib/core/payment/form/converters/street-number/street-number-from-state.interface.d.ts +3 -0
  99. package/lib/core/payment/form/converters/street-number/street-number.converter.d.ts +14 -0
  100. package/lib/core/payment/form/converters/text.converter.d.ts +11 -0
  101. package/lib/core/payment/form/validators/birth-date.validator.d.ts +2 -0
  102. package/lib/core/payment/form/validators/max-length-validator.d.ts +2 -0
  103. package/lib/core/payment/form/validators/min-length-validator.d.ts +2 -0
  104. package/lib/core/payment/form/validators/phone-validator.d.ts +2 -0
  105. package/lib/core/payment/initialize/initialize-request-params.interface.d.ts +1 -0
  106. package/lib/core/payment/initialize/initialize.service.d.ts +8 -6
  107. package/lib/core/payment/initialize/{initialize-response.class.d.ts → response/initialize-response.class.d.ts} +2 -2
  108. package/lib/core/payment/payment.interface.d.ts +2 -2
  109. package/lib/core/payment/payment.service.d.ts +4 -2
  110. package/lib/core/payment/status/check-status/check-status.service.d.ts +3 -4
  111. package/lib/core/payment/submit/submit.service.d.ts +5 -4
  112. package/lib/core/payment/sync/field-async-validation.interface.d.ts +1 -1
  113. package/lib/core/payment/sync/field-sync-state.interface.d.ts +1 -1
  114. package/lib/core/payment/sync/{sync-request.class.d.ts → request/sync-request.class.d.ts} +3 -3
  115. package/lib/core/payment/sync/{sync-response.class.d.ts → response/sync-response.class.d.ts} +2 -2
  116. package/lib/core/payment/sync/sync.service.d.ts +8 -7
  117. package/lib/core/payment/three-ds/api/notify-dfp-status/notify-dfp-status.service.d.ts +14 -0
  118. package/lib/core/payment/three-ds/api/notify-dfp-status/request/notify-dfp-status-request.class.d.ts +10 -0
  119. package/lib/core/payment/three-ds/api/notify-dfp-status/request/notify-dfp-status-request.token.d.ts +6 -0
  120. package/lib/core/payment/three-ds/api/status-three-ds/request/status-three-ds-request.class.d.ts +5 -0
  121. package/lib/core/payment/three-ds/api/status-three-ds/request/status-three-ds-request.token.d.ts +6 -0
  122. package/lib/core/payment/three-ds/api/status-three-ds/response/status-three-ds-response.class.d.ts +7 -0
  123. package/lib/core/payment/three-ds/api/status-three-ds/response/status-three-ds-response.token.d.ts +6 -0
  124. package/lib/core/payment/three-ds/api/status-three-ds/status-three-ds-response.interface.d.ts +7 -0
  125. package/lib/core/payment/three-ds/api/status-three-ds/status-three-ds.service.d.ts +21 -0
  126. package/lib/core/payment/three-ds/api/status-three-ds/status-types.enum.d.ts +5 -0
  127. package/lib/core/payment/three-ds/api/status-three-ds/three-ds-checkout-form.interface.d.ts +7 -0
  128. package/lib/core/payment/three-ds/dfp-collect/dfp-collect.service.d.ts +20 -0
  129. package/lib/core/payment/three-ds/reinsurance-check/reinsurance-check.service.d.ts +12 -0
  130. package/lib/core/payment/three-ds/reinsurance-check/timer.interface.d.ts +9 -0
  131. package/lib/core/payment/three-ds/three-ds-20/status-update.interface.d.ts +12 -0
  132. package/lib/core/payment/three-ds/three-ds-20/three-ds20.service.d.ts +32 -0
  133. package/lib/core/payment/three-ds/three-ds-form.interface.d.ts +11 -0
  134. package/lib/core/payment/three-ds/three-ds-status-websocket-types.enum.d.ts +3 -0
  135. package/lib/core/payment/three-ds/three-ds.service.d.ts +14 -0
  136. package/lib/core/payment/xps-api/xps-api.service.d.ts +20 -0
  137. package/lib/core/payment/xps-request-params.interface.d.ts +3 -0
  138. package/lib/core/payment/xps-request.interface.d.ts +10 -0
  139. package/lib/core/payment/xps-response.error.d.ts +4 -0
  140. package/lib/core/payment/xps-response.interface.d.ts +2 -10
  141. package/package.json +2 -3
  142. package/xsolla-payment-client-core-0.1.5-2.tgz +0 -0
  143. package/esm2020/lib/core/device-finger-print/device-finger-print-components.interface.mjs +0 -2
  144. package/esm2020/lib/core/device-finger-print/fingerprint-js.interface.mjs +0 -2
  145. package/esm2020/lib/core/exceptions-handling/errors/default-terminal-error.class.mjs +0 -8
  146. package/esm2020/lib/core/payment/initialize/initialize-response.class.mjs +0 -43
  147. package/esm2020/lib/core/payment/initialize/initialize-response.token.mjs +0 -8
  148. package/esm2020/lib/core/payment/sync/sync-request.class.mjs +0 -31
  149. package/esm2020/lib/core/payment/sync/sync-request.token.mjs +0 -8
  150. package/esm2020/lib/core/payment/sync/sync-response.class.mjs +0 -17
  151. package/esm2020/lib/core/payment/sync/sync-response.token.mjs +0 -8
  152. package/esm2020/lib/core/payment/xps-request.abstract.mjs +0 -8
  153. package/lib/core/device-finger-print/device-finger-print-components.interface.d.ts +0 -4
  154. package/lib/core/device-finger-print/fingerprint-js.interface.d.ts +0 -6
  155. package/lib/core/exceptions-handling/errors/default-terminal-error.class.d.ts +0 -4
  156. package/lib/core/payment/xps-request.abstract.d.ts +0 -6
  157. package/xsolla-payment-client-core-0.1.4.tgz +0 -0
  158. /package/lib/core/payment/initialize/{initialize-response.token.d.ts → response/initialize-response.token.d.ts} +0 -0
  159. /package/lib/core/payment/sync/{sync-request.token.d.ts → request/sync-request.token.d.ts} +0 -0
  160. /package/lib/core/payment/sync/{sync-response.token.d.ts → response/sync-response.token.d.ts} +0 -0
@@ -1,8 +1,9 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, Injectable, Inject, isDevMode, NgModule } from '@angular/core';
3
- import { firstValueFrom, lastValueFrom, map, Subject, tap, BehaviorSubject, filter as filter$1, takeUntil, skip, throwError } from 'rxjs';
3
+ import { firstValueFrom, lastValueFrom, map, Subject, BehaviorSubject, filter as filter$1, takeUntil, skip, 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 JSEncrypt from 'jsencrypt';
6
7
  import { UntypedFormGroup, Validators, UntypedFormControl, ReactiveFormsModule } from '@angular/forms';
7
8
  import { filter, map as map$1, catchError } from 'rxjs/operators';
8
9
  import * as i1$1 from '@angular/router';
@@ -580,6 +581,15 @@ var InputEventName;
580
581
  InputEventName["focus"] = "focus";
581
582
  })(InputEventName || (InputEventName = {}));
582
583
 
584
+ class ShowErrorsAction {
585
+ constructor(errors) {
586
+ this.type = 'show_errors';
587
+ this.data = {
588
+ errors,
589
+ };
590
+ }
591
+ }
592
+
583
593
  class InitializeResponse {
584
594
  constructor(response) {
585
595
  this.paymentForm = null;
@@ -629,14 +639,90 @@ const initializeResponseFactoryProvider = {
629
639
  useValue: (...args) => new InitializeResponse(...args),
630
640
  };
631
641
 
632
- class ShowErrorsAction {
633
- constructor(errors) {
634
- this.type = 'show_errors';
635
- this.data = {
636
- errors,
642
+ const masterCardAndVisaPaymentMethodId = 26;
643
+ const maestroPaymentMethodId = 490;
644
+ const creditCardPaymentMethodId = 1380;
645
+ const americanExpressMethodId = 714;
646
+ const specialCards = [
647
+ maestroPaymentMethodId,
648
+ masterCardAndVisaPaymentMethodId,
649
+ americanExpressMethodId,
650
+ ];
651
+ const cardsWith3ds = [
652
+ masterCardAndVisaPaymentMethodId,
653
+ maestroPaymentMethodId,
654
+ creditCardPaymentMethodId,
655
+ ];
656
+
657
+ class XpsApiService {
658
+ constructor(window, secureApiClient, settingsService, countryService) {
659
+ this.window = window;
660
+ this.secureApiClient = secureApiClient;
661
+ this.settingsService = settingsService;
662
+ this.countryService = countryService;
663
+ this.directPaymentApiRoute = 'directpayment';
664
+ }
665
+ async directPaymentRequest(parameters) {
666
+ const pid = parameters.pid?.toString() ??
667
+ parameters.xps_fix_pid ??
668
+ '';
669
+ const paymentWithSavedMethod = parameters.paymentWithSavedMethod ??
670
+ parameters.xps_paymentWithSavedMethod ??
671
+ '';
672
+ const requestParams = {
673
+ ...this.collectAnalyticsParameters(pid, paymentWithSavedMethod),
674
+ ...this.collectUserSessionId(),
675
+ country: this.countryService.getCountry(),
676
+ ...parameters,
637
677
  };
678
+ return lastValueFrom(this.secureApiClient.post(this.directPaymentApiRoute, new URLSearchParams({ ...requestParams }), {
679
+ headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
680
+ responseType: 'json',
681
+ }));
682
+ }
683
+ collectAnalyticsParameters(paymentMethodId, paymentWithSavedMethod) {
684
+ const parameters = {};
685
+ parameters.paymentWithSavedMethod = paymentWithSavedMethod
686
+ ? paymentWithSavedMethod
687
+ : "0" /* XpsBoolean.false */;
688
+ if (!paymentMethodId) {
689
+ return parameters;
690
+ }
691
+ /* If payment method with 3DSecure */
692
+ if (cardsWith3ds.includes(Number(paymentMethodId))) {
693
+ parameters.container3DS = JSON.stringify({
694
+ browserjavaenabled: this.window.navigator.javaEnabled(),
695
+ browserlanguage: this.window.navigator.language,
696
+ browsercolordepth: this.window.screen.colorDepth,
697
+ browserscreenheight: this.window.screen.availHeight,
698
+ browserscreenwidth: this.window.screen.availWidth,
699
+ browsertz: new Date().getTimezoneOffset(),
700
+ browserappname: this.window.navigator.appName,
701
+ browserlocaltime: new Date().toString(),
702
+ browserplatform: this.window.navigator.platform || '',
703
+ browsercookiesenabled: this.window.navigator.cookieEnabled,
704
+ });
705
+ }
706
+ return parameters;
707
+ }
708
+ collectUserSessionId() {
709
+ const parameters = {};
710
+ parameters.xps_idUserSession = this.settingsService.user.session_id ?? '';
711
+ parameters.user_session_id = this.settingsService.user.session_id ?? '';
712
+ return parameters;
638
713
  }
639
714
  }
715
+ XpsApiService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: XpsApiService, deps: [{ token: windowToken }, { token: SecureApiClient }, { token: SettingsService }, { token: CountryService }], target: i0.ɵɵFactoryTarget.Injectable });
716
+ XpsApiService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: XpsApiService, providedIn: 'root' });
717
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: XpsApiService, decorators: [{
718
+ type: Injectable,
719
+ args: [{
720
+ providedIn: 'root',
721
+ }]
722
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
723
+ type: Inject,
724
+ args: [windowToken]
725
+ }] }, { type: SecureApiClient }, { type: SettingsService }, { type: CountryService }]; } });
640
726
 
641
727
  class ShowFieldsAction {
642
728
  constructor(submitResponse) {
@@ -669,9 +755,8 @@ const showFieldsActionFactoryProvider = {
669
755
  class CheckStatusAction {
670
756
  constructor(submitResponse) {
671
757
  this.type = 'check_status';
672
- const status = submitResponse.parameters.status;
673
758
  this.data = {
674
- invoice: status?.invoice,
759
+ invoice: parseInt(submitResponse.parameters.form.fix_invoice?.value),
675
760
  signature: submitResponse.parameters.form.signature?.value,
676
761
  locale: submitResponse.parameters.form.locale?.value,
677
762
  testPs: submitResponse.parameters.form.testPs?.value,
@@ -759,6 +844,22 @@ const showErrorsActionFactoryProvider = {
759
844
  },
760
845
  };
761
846
 
847
+ class ThreeDsAction {
848
+ constructor(statusUpdate) {
849
+ this.type = '3DS';
850
+ this.data = statusUpdate;
851
+ }
852
+ }
853
+
854
+ const threeDsActionFactoryToken = new InjectionToken('ThreeDsAction');
855
+ const threeDsActionFactoryProvider = {
856
+ provide: threeDsActionFactoryToken,
857
+ useValue: {
858
+ factory: (...args) => new ThreeDsAction(...args),
859
+ isSuitable: () => false,
860
+ },
861
+ };
862
+
762
863
  const nextActionsToken = new InjectionToken('Action');
763
864
  const nextActions = [
764
865
  showFieldsActionFactoryProvider,
@@ -768,6 +869,7 @@ const nextActions = [
768
869
  const flowUpdateNextActions = [
769
870
  statusUpdatedActionFactoryProvider,
770
871
  showErrorsActionFactoryProvider,
872
+ threeDsActionFactoryProvider,
771
873
  ];
772
874
 
773
875
  class NextActionService {
@@ -825,1048 +927,1042 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
825
927
  args: [nextActionsToken]
826
928
  }] }, { type: i0.Injector }]; } });
827
929
 
828
- class InitializeService {
829
- constructor(responseFactory, secureApi, settingsService, countryService, nextActionService) {
830
- this.responseFactory = responseFactory;
831
- this.secureApi = secureApi;
832
- this.settingsService = settingsService;
833
- this.countryService = countryService;
834
- this.nextActionService = nextActionService;
835
- this.apiRoute = 'directpayment';
836
- // TODO PAYMENTS-15743: replace with new refer id for headless core
837
- this.ps4ReferId = '22';
838
- }
839
- async request(config) {
840
- const requestParams = {
841
- access_token: this.settingsService.token,
842
- pid: String(config.paymentMethodId),
843
- refer: this.ps4ReferId,
844
- country: this.countryService.getCountry(),
845
- returnUrl: config.returnUrl,
846
- };
847
- return lastValueFrom(this.secureApi
848
- .post(this.apiRoute, new URLSearchParams({ ...requestParams }), {
849
- headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
850
- responseType: 'json',
851
- })
852
- .pipe(map((response) => this.responseFactory(response)), tap((response) => {
853
- if (response.paymentForm?.errors?.length) {
854
- this.nextActionService.emitFlowUpdates(new ShowErrorsAction(response.paymentForm.errors));
855
- }
856
- }))).catch((error) => {
857
- throw new ResponseError(error.message);
858
- });
859
- }
860
- }
861
- 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 }, { token: NextActionService }], target: i0.ɵɵFactoryTarget.Injectable });
862
- InitializeService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, providedIn: 'root' });
863
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, decorators: [{
864
- type: Injectable,
865
- args: [{
866
- providedIn: 'root',
867
- }]
868
- }], ctorParameters: function () { return [{ type: undefined, decorators: [{
869
- type: Inject,
870
- args: [initializeResponseFactoryToken]
871
- }] }, { type: SecureApiClient }, { type: SettingsService }, { type: CountryService }, { type: NextActionService }]; } });
930
+ var ErrorTags;
931
+ (function (ErrorTags) {
932
+ ErrorTags["APP"] = "appError";
933
+ ErrorTags["HTTP"] = "httpError";
934
+ ErrorTags["JS"] = "jsError";
935
+ ErrorTags["WS"] = "webSocket";
936
+ ErrorTags["ENCRYPT"] = "encrypt";
937
+ ErrorTags["APPLEPAY"] = "applepay";
938
+ ErrorTags["HEADLESS_UI"] = "headlessUi";
939
+ ErrorTags["GOOGLEPAY"] = "googlepay";
940
+ ErrorTags["PAYTM"] = "paytm";
941
+ })(ErrorTags || (ErrorTags = {}));
872
942
 
873
- class XpsApiPartRequest {
874
- addXpsParameters(parameters) {
875
- for (const key in parameters) {
876
- this[`xps_${key}`] = parameters[key];
943
+ class TaggedError extends Error {
944
+ constructor(message, tags) {
945
+ super(message);
946
+ this.tags = [];
947
+ this.parentTag = ErrorTags.HEADLESS_UI;
948
+ this.tags = this.childTag
949
+ ? [this.parentTag, this.childTag]
950
+ : [this.parentTag];
951
+ if (tags) {
952
+ const newTags = tags.filter((t, i, arr) => !this.tags.includes(t) && arr.indexOf(t) == i);
953
+ this.tags = [...this.tags, ...newTags];
877
954
  }
878
955
  }
879
956
  }
880
957
 
881
- class TokenError extends AppError {
882
- constructor() {
883
- super('XPS API needs token.');
958
+ class EncryptCreditCardError extends TaggedError {
959
+ constructor(message, tags) {
960
+ tags = tags ? [...tags, ErrorTags.ENCRYPT] : [ErrorTags.ENCRYPT];
961
+ super(message, tags);
884
962
  }
885
963
  }
886
964
 
887
- class SubmitRequest extends XpsApiPartRequest {
888
- constructor(parameters) {
889
- super();
890
- const { token, fields, form, dfpHash } = parameters;
891
- if (token === null) {
892
- throw new TokenError();
893
- }
894
- this.access_token = token;
895
- if (dfpHash) {
896
- this.xps_dfp_hash = dfpHash;
897
- }
898
- this.addXpsParameters(this.getFieldsValues(fields, form));
899
- }
900
- getFieldsValues(fields, form) {
901
- return fields.reduce((xpsParams, field) => {
902
- const formControl = form.get(field.name);
903
- xpsParams[field.name] = formControl ? formControl.value : field?.value;
904
- return xpsParams;
905
- }, {});
906
- }
907
- }
965
+ const fourBlockMask = '9999 9999 9999 9999';
908
966
 
909
- const submitRequestFactoryToken = new InjectionToken('SubmitRequest');
910
- const submitRequestFactoryProvider = {
911
- provide: submitRequestFactoryToken,
912
- useValue: (...args) => new SubmitRequest(...args),
967
+ var CreditCardTypes;
968
+ (function (CreditCardTypes) {
969
+ CreditCardTypes["DEFAULT"] = "0";
970
+ CreditCardTypes["VISA"] = "1";
971
+ CreditCardTypes["MASTERCARD"] = "2";
972
+ CreditCardTypes["MAESTRO"] = "3";
973
+ CreditCardTypes["AMERICAN_EXPRESS"] = "4";
974
+ CreditCardTypes["DINERS_CLUBS"] = "5";
975
+ CreditCardTypes["DISCOVER"] = "6";
976
+ CreditCardTypes["JCB"] = "9";
977
+ CreditCardTypes["DANKORT"] = "11";
978
+ CreditCardTypes["HIPERCARD"] = "12";
979
+ CreditCardTypes["ELO"] = "13";
980
+ CreditCardTypes["AURA"] = "14";
981
+ CreditCardTypes["NARANJA"] = "15";
982
+ CreditCardTypes["MIR"] = "16";
983
+ CreditCardTypes["CHINA_UNION_PAY"] = "17";
984
+ CreditCardTypes["POSTEPAY"] = "18";
985
+ })(CreditCardTypes || (CreditCardTypes = {}));
986
+
987
+ const visa = {
988
+ id: CreditCardTypes.VISA,
989
+ minLength: 13,
990
+ maxLength: 16,
991
+ iconName: 'visa',
992
+ mask: fourBlockMask,
993
+ checkNumber(number) {
994
+ return number.startsWith('4');
995
+ },
913
996
  };
914
997
 
915
- const submitResponseFactoryToken = new InjectionToken('SubmitResponse');
916
- const submitResponseFactoryProvider = {
917
- provide: submitResponseFactoryToken,
918
- useValue: (...args) => new SubmitResponse(...args),
998
+ const mastercard = {
999
+ id: CreditCardTypes.MASTERCARD,
1000
+ minLength: 16,
1001
+ maxLength: 16,
1002
+ iconName: 'mastercard',
1003
+ mask: fourBlockMask,
1004
+ checkNumber(number) {
1005
+ const subLength = 6;
1006
+ const cardNumberSub = number.substring(0, subLength);
1007
+ return (new RegExp(/^5[1-5]/).test(number) ||
1008
+ (cardNumberSub >= '222100' && cardNumberSub <= '272099'));
1009
+ },
919
1010
  };
920
1011
 
921
- class TerminalError extends AppError {
922
- constructor(message, code) {
923
- super(message);
924
- this.code = code;
925
- }
926
- }
1012
+ const defaultMask = '9999 9999 9999 9999 999';
927
1013
 
928
- class DefaultTerminalError extends TerminalError {
929
- constructor() {
930
- const message = `It's not you, it's us, but we can help. Please contact our customer support.`;
931
- super(message, '1000-0002');
932
- }
933
- }
1014
+ const maestro = {
1015
+ id: CreditCardTypes.MAESTRO,
1016
+ minLength: 12,
1017
+ maxLength: 19,
1018
+ iconName: 'maestro',
1019
+ mask: defaultMask,
1020
+ checkNumber(number) {
1021
+ return new RegExp(/^(5018)|^(5020)|^(5038)|^(5893)|^(6304)|^(6759)|^(6761)|^(6762)|^(6763)|^(0604)|^(6706)|^(6771)|^(6709)/).test(number);
1022
+ },
1023
+ maxCvvLength: 3,
1024
+ };
934
1025
 
935
- class DeviceFingerPrintService {
936
- constructor(secureApi, settingsService, window) {
937
- this.secureApi = secureApi;
938
- this.settingsService = settingsService;
939
- this.window = window;
940
- this.apiRoute = 'dfp';
941
- this.fingerprintApiUrl = 'https://afs.xsolla.com/dfp/api/v1/';
942
- }
943
- async init() {
944
- if (!this.settingsService.isInitialized) {
945
- return;
946
- }
947
- this.fingerprintJs = await this.loadFingerprintJs();
948
- this.hash = await this.buildHash();
949
- this.antifraudFingerprintLibrary =
950
- await this.loadAntifraudFingerprintLibrary();
951
- }
952
- // eslint-disable-next-line @typescript-eslint/require-await
953
- async getHash() {
954
- return this.hash;
955
- }
956
- async loadFingerprintJs() {
957
- const { default: library, murmurX64Hash128: getHash } = await import('@fingerprintjs/fingerprintjs');
958
- return { library, getHash };
959
- }
960
- async loadAntifraudFingerprintLibrary() {
961
- const library = await import('@xsolla/antifraud-fingerprint');
962
- return library.default;
963
- }
964
- // eslint-disable-next-line @typescript-eslint/require-await
965
- async makeAntifraudFingerprint() {
966
- if (!this.settingsService.token) {
967
- return null;
968
- }
969
- const antifraudFingerprint = this.antifraudFingerprintLibrary;
970
- try {
971
- return new antifraudFingerprint({
972
- api: {
973
- url: this.fingerprintApiUrl,
974
- token: this.settingsService.token,
975
- timeout: 3000,
976
- },
977
- retry: {
978
- num: 1,
979
- timeout: 500,
980
- },
981
- });
982
- }
983
- catch (error) {
984
- return null;
985
- }
986
- }
987
- /**
988
- *Загружаем библиотеку, генерируем данные,
989
- *хешируем с помощью BASE64 и отправляем на бэкенд,
990
- *в ответ получаем dfp_hash.
991
- **/
992
- async buildHash() {
993
- const fingerPrintData = await this.generate();
994
- const hash = await this.send(fingerPrintData).catch(() => {
995
- return null;
996
- });
997
- return JSON.stringify(hash);
998
- }
999
- /**
1000
- *Новая версия библиотеки содержит не все компоненты, некоторые приходится имплементировать самостоятельно
1001
- **/
1002
- getHasLiedResolution() {
1003
- const { screen } = this.window;
1004
- return (screen.width < screen.availWidth || screen.height < screen.availHeight);
1005
- }
1006
- /**
1007
- *Бэкенд заточен под конкретные поля, которые необходимо смапить.
1008
- **/
1009
- getComponents(components) {
1010
- return {
1011
- user_agent: navigator.userAgent,
1012
- language: components.languages.value?.shift()?.shift() ?? '',
1013
- color_depth: components.colorDepth.value,
1014
- device_memory: components.deviceMemory.value,
1015
- hardware_concurrency: components.hardwareConcurrency.value,
1016
- resolution: components.screenResolution.value,
1017
- available_resolution: components.screenResolution.value,
1018
- timezone_offset: new Date().getTimezoneOffset(),
1019
- session_storage: components.sessionStorage.value ? 1 : 0,
1020
- local_storage: components.localStorage.value ? 1 : 0,
1021
- indexed_db: components.indexedDB.value ? 1 : 0,
1022
- open_database: components.openDatabase.value ? 1 : 0,
1023
- navigator_platform: components.platform.value,
1024
- regular_plugins: components.plugins.value?.map((plugin) => plugin.name) ?? [],
1025
- canvas: components.canvas.value?.text,
1026
- webgl: components.canvas.value?.text,
1027
- webgl_vendor: components.vendor.value,
1028
- has_lied_resolution: this.getHasLiedResolution(),
1029
- touch_support: Object.values(components.touchSupport.value ?? {}),
1030
- js_fonts: components.fonts.value,
1031
- };
1032
- }
1033
- /**
1034
- * Получаем данные dfp с помощью FingerprintJS, мапим необходимые поля, добавляем хэш
1035
- **/
1036
- async generate() {
1037
- const { library, getHash } = this.fingerprintJs;
1038
- const fingerprint = await library.load();
1039
- const commonFingerPrintData = await fingerprint.get();
1040
- const fingerPrintData = this.getComponents(commonFingerPrintData.components);
1041
- fingerPrintData.hash = getHash(JSON.stringify(fingerPrintData));
1042
- return fingerPrintData;
1043
- }
1044
- /**
1045
- * Отправка dfp на сервер, в ответ получаем dfp_hash
1046
- **/
1047
- async send(fingerPrintData) {
1048
- const token = this.settingsService.token;
1049
- if (token === null) {
1050
- throw new DefaultTerminalError();
1051
- }
1052
- const requestBody = {
1053
- access_token: token,
1054
- 'dfp[200]': '',
1055
- };
1056
- requestBody['dfp[200]'] = btoa(encodeURIComponent(JSON.stringify(fingerPrintData)));
1057
- return lastValueFrom(this.secureApi.post(this.apiRoute, new URLSearchParams(requestBody), {
1058
- headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
1059
- responseType: 'json',
1060
- }))
1061
- .then((response) => {
1062
- return response.dfp_hash;
1063
- })
1064
- .then(async (hash) => {
1065
- const fingerprint = await this.makeAntifraudFingerprint();
1066
- if (!fingerprint) {
1067
- return null;
1068
- }
1069
- await fingerprint
1070
- ?.dispatch(hash['200'])
1071
- .catch((err) => console.log(err));
1072
- const afsHash = await fingerprint.hash();
1073
- return { '301': afsHash, ...hash };
1074
- })
1075
- .catch((error) => {
1076
- const response = error.getHttpErrorData().response;
1077
- throw new TerminalError(response.data?.errors[0]?.message ?? '', response.data?.errors[0]?.support_code ?? '');
1078
- });
1079
- }
1080
- }
1081
- 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 });
1082
- DeviceFingerPrintService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: DeviceFingerPrintService, providedIn: 'root' });
1083
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: DeviceFingerPrintService, decorators: [{
1084
- type: Injectable,
1085
- args: [{
1086
- providedIn: 'root',
1087
- }]
1088
- }], ctorParameters: function () { return [{ type: SecureApiClient }, { type: SettingsService }, { type: undefined, decorators: [{
1089
- type: Inject,
1090
- args: [windowToken]
1091
- }] }]; } });
1026
+ const americanExpress = {
1027
+ id: CreditCardTypes.AMERICAN_EXPRESS,
1028
+ minLength: 15,
1029
+ maxLength: 15,
1030
+ iconName: 'american-express',
1031
+ mask: '9999 999999 99999',
1032
+ checkNumber(number) {
1033
+ return new RegExp(/^(34)|^(37)/).test(number);
1034
+ },
1035
+ maxCvvLength: 4,
1036
+ };
1092
1037
 
1093
- class SubmitService {
1094
- constructor(requestFactory, responseFactory, settingsService, deviceFingerPrintService, secureApi) {
1095
- this.requestFactory = requestFactory;
1096
- this.responseFactory = responseFactory;
1097
- this.settingsService = settingsService;
1098
- this.deviceFingerPrintService = deviceFingerPrintService;
1099
- this.secureApi = secureApi;
1100
- this.directPaymentApiRoute = 'directpayment';
1101
- }
1102
- // NB: Never add 'async' statement for this method!
1103
- // 'Async' statement wraps current promise into another.
1104
- // In this way two promises become unequal, that can broke XPS API requests logic.
1105
- // eslint-disable-next-line @typescript-eslint/promise-function-async
1106
- request(fields, form) {
1107
- const responsePromise = this.deviceFingerPrintService
1108
- .getHash()
1109
- // eslint-disable-next-line @typescript-eslint/promise-function-async
1110
- .then((dfpHash) => {
1111
- const requestParams = this.requestFactory({
1112
- token: this.settingsService.token,
1113
- fields,
1114
- form,
1115
- dfpHash,
1116
- });
1117
- return lastValueFrom(this.secureApi.post(this.directPaymentApiRoute, new URLSearchParams({ ...requestParams }), {
1118
- headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
1119
- responseType: 'json',
1120
- }))
1121
- .then((response) => this.responseFactory(response))
1122
- .catch((error) => {
1123
- throw new ResponseError(error.message);
1124
- });
1125
- });
1126
- return responsePromise;
1127
- }
1128
- }
1129
- 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 });
1130
- SubmitService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SubmitService, providedIn: 'root' });
1131
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SubmitService, decorators: [{
1132
- type: Injectable,
1133
- args: [{ providedIn: 'root' }]
1134
- }], ctorParameters: function () { return [{ type: undefined, decorators: [{
1135
- type: Inject,
1136
- args: [submitRequestFactoryToken]
1137
- }] }, { type: undefined, decorators: [{
1138
- type: Inject,
1139
- args: [submitResponseFactoryToken]
1140
- }] }, { type: SettingsService }, { type: DeviceFingerPrintService }, { type: SecureApiClient }]; } });
1038
+ const dinersClubs = {
1039
+ id: CreditCardTypes.DINERS_CLUBS,
1040
+ minLength: 14,
1041
+ maxLength: 14,
1042
+ iconName: 'dinersclub',
1043
+ mask: '9999 9999 9999 99',
1044
+ checkNumber(number) {
1045
+ const regex = /^(36[0-9]|3(?:0[0-59]|[68][0-9])[0-9])/;
1046
+ return regex.test(number);
1047
+ },
1048
+ };
1141
1049
 
1142
- class EmitDataService {
1143
- constructor() {
1144
- this.dataSubject = new Subject();
1145
- this.data$ = this.dataSubject.asObservable();
1146
- }
1147
- emit(data) {
1148
- this.dataSubject.next(data);
1149
- }
1150
- }
1050
+ const discover = {
1051
+ id: CreditCardTypes.DISCOVER,
1052
+ minLength: 16,
1053
+ maxLength: 19,
1054
+ iconName: 'discover',
1055
+ mask: defaultMask,
1056
+ checkNumber(number) {
1057
+ return new RegExp(/^(6011)|^(622(1(2[6-9]|[3-9][0-9])|[2-8][0-9]{2}|9([01][0-9]|2[0-5])))|^(64[4-9])|^65/).test(number);
1058
+ },
1059
+ };
1151
1060
 
1152
- class XpsRequest {
1153
- addXpsParameters(parameters) {
1154
- for (const key in parameters) {
1155
- this[`xps_${key}`] = parameters[key];
1156
- }
1157
- }
1158
- }
1061
+ const jcb = {
1062
+ id: CreditCardTypes.JCB,
1063
+ minLength: 15,
1064
+ maxLength: 16,
1065
+ iconName: 'jcb',
1066
+ mask: fourBlockMask,
1067
+ checkNumber(number) {
1068
+ return new RegExp(/^35(2[89]|[3-8][0-9])/).test(number);
1069
+ },
1070
+ };
1159
1071
 
1160
- /* eslint-disable @typescript-eslint/naming-convention */
1161
- class SyncRequest extends XpsRequest {
1162
- constructor(parameters) {
1163
- super();
1164
- this.xps_fix_command = 'calculate';
1165
- this.access_token = parameters.token;
1166
- const fieldsValues = this.getFieldsValues(parameters.changedField, parameters.fields, parameters.form);
1167
- this.addXpsParameters({
1168
- ...fieldsValues,
1169
- change_element: parameters.changedField.name,
1170
- });
1171
- }
1172
- getFieldsValues(changedField, fields, form) {
1173
- const fieldsMap = this.getFieldsMap(fields);
1174
- return changedField?.javascript?.change.params.reduce((xpsParams, fieldName) => {
1175
- const formControl = form.get(fieldName);
1176
- const field = fieldsMap.get(fieldName);
1177
- if (formControl || field) {
1178
- xpsParams[fieldName] = formControl?.value ?? field?.value;
1179
- }
1180
- return xpsParams;
1181
- }, {});
1182
- }
1183
- getFieldsMap(fields) {
1184
- const map = new Map();
1185
- fields.forEach((field) => map.set(field.name, field));
1186
- return map;
1187
- }
1188
- }
1072
+ const dankort = {
1073
+ id: CreditCardTypes.DANKORT,
1074
+ minLength: 16,
1075
+ maxLength: 16,
1076
+ iconName: 'dankort',
1077
+ mask: fourBlockMask,
1078
+ checkNumber(number) {
1079
+ const subLength = 4;
1080
+ const cardNumberSub = number.substring(0, subLength);
1081
+ return cardNumberSub === '5019';
1082
+ },
1083
+ };
1189
1084
 
1190
- const syncRequestFactoryToken = new InjectionToken('SyncRequest');
1191
- const syncRequestFactoryProvider = {
1192
- provide: syncRequestFactoryToken,
1193
- useValue: (...args) => new SyncRequest(...args),
1085
+ const hipercard = {
1086
+ id: CreditCardTypes.HIPERCARD,
1087
+ minLength: 13,
1088
+ maxLength: 19,
1089
+ iconName: 'hipercard',
1090
+ mask: defaultMask,
1091
+ checkNumber(number) {
1092
+ return new RegExp(/^((606282|637095|637568)[0-9]|38[0-9]{14,17})/).test(number);
1093
+ },
1194
1094
  };
1195
1095
 
1196
- class SyncResponse {
1197
- constructor(changedField, response) {
1198
- this.error = null;
1199
- const fieldError = response?.errors?.find((error) => error.element_name === changedField.name);
1200
- if (fieldError) {
1201
- this.error = {
1202
- asyncError: {
1203
- code: fieldError.code,
1204
- message: fieldError.message,
1205
- },
1206
- };
1207
- }
1208
- this.fields = Object.keys(response.form).map((key) => response.form[key]);
1209
- this.parameters = response;
1210
- }
1211
- }
1096
+ const elo = {
1097
+ id: CreditCardTypes.ELO,
1098
+ minLength: 16,
1099
+ maxLength: 19,
1100
+ iconName: 'elo',
1101
+ mask: defaultMask,
1102
+ checkNumber(number) {
1103
+ return new RegExp(/^(40117[8-9]|431274|438935|451416|457393|45763[1-2]|506(699|7[0-6][0-9]|77[0-8])|509\d{3}|504175|627780|636297|636368|65003[1-3]|6500(3[5-9]|4[0-9]|5[0-1])|6504(0[5-9]|[1-3][0-9])|650(4[8-9][0-9]|5[0-2][0-9]|53[0-8])|6505(4[1-9]|[5-8][0-9]|9[0-8])|6507(0[0-9]|1[0-8])|65072[0-7]|6509(0[1-9]|1[0-9]|20)|6516(5[2-9]|[6-7][0-9])|6550([0-1][0-9]|2[1-9]|[3-4][0-9]|5[0-8]))/).test(number);
1104
+ },
1105
+ };
1212
1106
 
1213
- const syncResponseFactoryToken = new InjectionToken('SyncResponse');
1214
- const syncResponseFactoryProvider = {
1215
- provide: syncResponseFactoryToken,
1216
- useValue: (...args) => new SyncResponse(...args),
1107
+ const aura = {
1108
+ id: CreditCardTypes.AURA,
1109
+ minLength: 16,
1110
+ maxLength: 19,
1111
+ iconName: 'aura',
1112
+ mask: defaultMask,
1113
+ checkNumber(number) {
1114
+ const subLength = 8;
1115
+ const cardNumberSub = number.substring(0, subLength);
1116
+ return ['50786000', '50786018', '50786019'].includes(cardNumberSub);
1117
+ },
1217
1118
  };
1218
1119
 
1219
- class SyncService extends EmitDataService {
1220
- constructor(requestFactory, responseFactory, secureApi, nextActionService, settingsService) {
1221
- super();
1222
- this.requestFactory = requestFactory;
1223
- this.responseFactory = responseFactory;
1224
- this.secureApi = secureApi;
1225
- this.nextActionService = nextActionService;
1226
- this.settingsService = settingsService;
1227
- this.apiRoute = 'directpayment';
1228
- this.prevFieldSyncStates = {};
1229
- this.form = new UntypedFormGroup({});
1230
- this.fields = [];
1231
- this.fieldAsyncValidation = new Subject();
1232
- }
1233
- get fieldAsyncValidation$() {
1234
- return this.fieldAsyncValidation.asObservable();
1235
- }
1236
- setup(form, fields) {
1237
- this.reset();
1238
- this.form = form;
1239
- this.fields = fields;
1240
- }
1241
- reset() {
1242
- this.prevFieldSyncStates = {};
1243
- this.form = new UntypedFormGroup({});
1244
- this.fields = [];
1245
- }
1246
- async validate(field) {
1247
- if (!this.isReadyField(field)) {
1248
- return Promise.resolve(null);
1249
- }
1250
- const control = this.form.get(field.name);
1251
- const value = control?.value;
1252
- const prevFieldState = this.getPrevFieldSyncState(field);
1253
- const isInitialValue = value === field.value && !prevFieldState;
1254
- if (isInitialValue) {
1255
- return Promise.resolve(null);
1256
- }
1257
- if (prevFieldState && value === prevFieldState.value) {
1258
- return Promise.resolve(prevFieldState.result).then((response) => {
1259
- return response?.error ?? null;
1260
- });
1261
- }
1262
- const requestPromise = this.request(field);
1263
- this.setPrevFieldSyncState(field, value, requestPromise);
1264
- return requestPromise.then((response) => {
1265
- this.fieldAsyncValidation.next({
1266
- value,
1267
- field,
1268
- response,
1269
- });
1270
- return response.error ?? null;
1271
- });
1120
+ const naranja = {
1121
+ id: CreditCardTypes.NARANJA,
1122
+ minLength: 12,
1123
+ maxLength: 19,
1124
+ iconName: 'naranja',
1125
+ mask: defaultMask,
1126
+ checkNumber(number) {
1127
+ const subLength = 6;
1128
+ const cardNumberSub = number.substring(0, subLength);
1129
+ return cardNumberSub === '589562';
1130
+ },
1131
+ };
1132
+
1133
+ const mir = {
1134
+ id: CreditCardTypes.MIR,
1135
+ minLength: 16,
1136
+ maxLength: 16,
1137
+ iconName: 'mir',
1138
+ mask: defaultMask,
1139
+ checkNumber(number) {
1140
+ const subLength = 4;
1141
+ const cardNumberSub = number.substring(0, subLength);
1142
+ return cardNumberSub >= '2200' && cardNumberSub <= '2204';
1143
+ },
1144
+ };
1145
+
1146
+ const chinaUnionPay = {
1147
+ id: CreditCardTypes.CHINA_UNION_PAY,
1148
+ minLength: 16,
1149
+ maxLength: 19,
1150
+ iconName: 'unionpay',
1151
+ mask: '999 9999 9999 99999999',
1152
+ checkNumber(number) {
1153
+ return number.startsWith('62');
1154
+ },
1155
+ };
1156
+
1157
+ const defaultCard = {
1158
+ id: CreditCardTypes.DEFAULT,
1159
+ minLength: 12,
1160
+ maxLength: 19,
1161
+ iconName: null,
1162
+ mask: defaultMask,
1163
+ checkNumber() {
1164
+ return false;
1165
+ },
1166
+ };
1167
+
1168
+ const postePay = {
1169
+ id: CreditCardTypes.POSTEPAY,
1170
+ minLength: 12,
1171
+ maxLength: 19,
1172
+ iconName: 'poste_pay',
1173
+ mask: '9999 9999 9999 9999 999',
1174
+ checkNumber(number) {
1175
+ const regex = /^(5018)|^(5020)|^(5038)|^(5893)|^(6304)|^(6759)|^(6761)|^(6762)|^(6763)|^(0604)|^(6706)|^(6771)|^(6709)/;
1176
+ return regex.test(number);
1177
+ },
1178
+ };
1179
+
1180
+ /**
1181
+ * order does matter
1182
+ * settings with more specific pattern should be placed above
1183
+ * Example:
1184
+ * - 12*
1185
+ * - 12
1186
+ * - 1
1187
+ * "12*" pattern should be checked first, otherwise pattern "1" will be taken
1188
+ * before "12*" checked
1189
+ */
1190
+ const orderedCardSettings = [
1191
+ aura,
1192
+ naranja,
1193
+ maestro,
1194
+ postePay,
1195
+ elo,
1196
+ discover,
1197
+ dankort,
1198
+ hipercard,
1199
+ mir,
1200
+ jcb,
1201
+ dinersClubs,
1202
+ americanExpress,
1203
+ mastercard,
1204
+ chinaUnionPay,
1205
+ visa,
1206
+ defaultCard,
1207
+ ];
1208
+
1209
+ const creditCardsMap = {
1210
+ [CreditCardTypes.DEFAULT]: defaultCard,
1211
+ [CreditCardTypes.VISA]: visa,
1212
+ [CreditCardTypes.MASTERCARD]: mastercard,
1213
+ [CreditCardTypes.MAESTRO]: maestro,
1214
+ [CreditCardTypes.AMERICAN_EXPRESS]: americanExpress,
1215
+ [CreditCardTypes.DINERS_CLUBS]: dinersClubs,
1216
+ [CreditCardTypes.DISCOVER]: discover,
1217
+ [CreditCardTypes.JCB]: jcb,
1218
+ [CreditCardTypes.DANKORT]: dankort,
1219
+ [CreditCardTypes.HIPERCARD]: hipercard,
1220
+ [CreditCardTypes.ELO]: elo,
1221
+ [CreditCardTypes.AURA]: aura,
1222
+ [CreditCardTypes.NARANJA]: naranja,
1223
+ [CreditCardTypes.MIR]: mir,
1224
+ [CreditCardTypes.CHINA_UNION_PAY]: chinaUnionPay,
1225
+ [CreditCardTypes.POSTEPAY]: postePay,
1226
+ };
1227
+
1228
+ class CreditCardService {
1229
+ getBinNumber(cardNumber) {
1230
+ const binNumberLength = 6;
1231
+ return cardNumber.replace(/\s+/g, '').substring(0, binNumberLength);
1272
1232
  }
1273
- getSyncValidationErrors(field) {
1274
- const control = this.form.get(field.name);
1275
- return control?.errors ?? null;
1233
+ getAccountSuffix(cardNumber) {
1234
+ const accountSuffixLength = 4;
1235
+ return cardNumber
1236
+ .replace(/\s+/g, '')
1237
+ .substring(cardNumber.length - accountSuffixLength);
1276
1238
  }
1277
- async request(field) {
1278
- const requestParams = this.requestFactory({
1279
- token: this.settingsService.token,
1280
- changedField: field,
1281
- fields: this.fields,
1282
- form: this.form,
1239
+ getTypeByNumber(cardNumber) {
1240
+ cardNumber = cardNumber.replace(/\s+/g, '');
1241
+ const cardSettings = orderedCardSettings.find((settings) => {
1242
+ const isNumberMatched = settings.checkNumber(cardNumber);
1243
+ return isNumberMatched ? settings.id : false;
1283
1244
  });
1284
- return lastValueFrom(this.secureApi.post(this.apiRoute, new URLSearchParams(requestParams), {
1285
- headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
1286
- responseType: 'json',
1287
- })).then((response) => {
1288
- if (response.errors?.length) {
1289
- this.nextActionService.emitFlowUpdates(new ShowErrorsAction(response.errors));
1290
- }
1291
- this.emit(response);
1292
- return this.responseFactory(field, response);
1245
+ return cardSettings ? cardSettings.id : defaultCard.id;
1246
+ }
1247
+ getCreditCardSettings(cardType) {
1248
+ const creditCard = creditCardsMap[cardType];
1249
+ if (!creditCard) {
1250
+ return defaultCard;
1251
+ }
1252
+ return creditCard;
1253
+ }
1254
+ }
1255
+ CreditCardService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CreditCardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1256
+ CreditCardService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CreditCardService, providedIn: 'root' });
1257
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CreditCardService, decorators: [{
1258
+ type: Injectable,
1259
+ args: [{
1260
+ providedIn: 'root',
1261
+ }]
1262
+ }] });
1263
+
1264
+ class EncryptCreditCardService {
1265
+ constructor(creditCardService) {
1266
+ this.creditCardService = creditCardService;
1267
+ this.secureFieldNames = [
1268
+ 'xps_card_number',
1269
+ 'xps_cvv',
1270
+ 'xps_extra_cvv',
1271
+ 'xps_card_year',
1272
+ 'xps_card_month',
1273
+ ];
1274
+ this.jsEncrypt = new JSEncrypt();
1275
+ }
1276
+ setPublicKey(publicKey) {
1277
+ this.jsEncrypt.setPublicKey(publicKey);
1278
+ }
1279
+ encryptCreditCard(request) {
1280
+ if (request.xps_card_number) {
1281
+ const openCard = this.createOpenCard(request);
1282
+ request.xps_open_card = JSON.stringify(openCard);
1283
+ }
1284
+ const encryptedCard = this.createEncryptedCard(request);
1285
+ if (!request.xps_encrypted_card && JSON.stringify(encryptedCard) !== '{}') {
1286
+ request.xps_encrypted_card = this.encrypt(JSON.stringify(encryptedCard));
1287
+ }
1288
+ this.secureFieldNames.forEach((secureFieldName) => {
1289
+ delete request[secureFieldName];
1293
1290
  });
1291
+ return request;
1294
1292
  }
1295
- isReadyField(field) {
1296
- const isSyncEnabled = !!field.javascript?.change;
1297
- const isExistsInForm = !!this.form?.get(field.name);
1298
- return isSyncEnabled && isExistsInForm;
1293
+ encrypt(value) {
1294
+ if (!this.jsEncrypt?.getPublicKey()) {
1295
+ throw new EncryptCreditCardError('Empty public key');
1296
+ }
1297
+ const encryptedValue = this.jsEncrypt.encrypt(value);
1298
+ if (!encryptedValue) {
1299
+ throw new EncryptCreditCardError('Encryption returns false instead of encrypted string');
1300
+ }
1301
+ return encryptedValue;
1302
+ }
1303
+ createEncryptedCard(request) {
1304
+ const encryptedCard = {
1305
+ card_number: request.xps_card_number,
1306
+ card_year: request.xps_card_year,
1307
+ card_month: request.xps_card_month,
1308
+ cvv: request.xps_cvv,
1309
+ };
1310
+ if (request.xps_extra_cvv) {
1311
+ encryptedCard.cvv = request.xps_extra_cvv;
1312
+ }
1313
+ return encryptedCard;
1299
1314
  }
1300
- getPrevFieldSyncState(field) {
1301
- return this.prevFieldSyncStates[field.name];
1315
+ createOpenCard(request) {
1316
+ return {
1317
+ card_bin: this.creditCardService.getBinNumber(request.xps_card_number),
1318
+ card_suffix: this.creditCardService.getAccountSuffix(request.xps_card_number),
1319
+ card_year: request.xps_card_year,
1320
+ card_month: request.xps_card_month,
1321
+ };
1302
1322
  }
1303
- setPrevFieldSyncState(field, value, result) {
1304
- this.prevFieldSyncStates[field.name] = { value, result };
1323
+ }
1324
+ EncryptCreditCardService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: EncryptCreditCardService, deps: [{ token: CreditCardService }], target: i0.ɵɵFactoryTarget.Injectable });
1325
+ EncryptCreditCardService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: EncryptCreditCardService, providedIn: 'root' });
1326
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: EncryptCreditCardService, decorators: [{
1327
+ type: Injectable,
1328
+ args: [{ providedIn: 'root' }]
1329
+ }], ctorParameters: function () { return [{ type: CreditCardService }]; } });
1330
+
1331
+ class InitializeService {
1332
+ constructor(responseFactory, xpsApiService, settingsService, countryService, nextActionService, encryptCreditCardService) {
1333
+ this.responseFactory = responseFactory;
1334
+ this.xpsApiService = xpsApiService;
1335
+ this.settingsService = settingsService;
1336
+ this.countryService = countryService;
1337
+ this.nextActionService = nextActionService;
1338
+ this.encryptCreditCardService = encryptCreditCardService;
1339
+ // TODO PAYMENTS-15743: replace with new refer id for headless core
1340
+ this.ps4ReferId = '22';
1341
+ }
1342
+ async request(config) {
1343
+ const requestParams = {
1344
+ access_token: this.settingsService.token,
1345
+ pid: String(config.paymentMethodId),
1346
+ refer: this.ps4ReferId,
1347
+ country: this.countryService.getCountry(),
1348
+ returnUrl: config.returnUrl,
1349
+ };
1350
+ return this.xpsApiService
1351
+ .directPaymentRequest(requestParams)
1352
+ .then((response) => {
1353
+ const initializeResponse = this.responseFactory(response);
1354
+ if (initializeResponse.paymentForm?.errors?.length) {
1355
+ this.nextActionService.emitFlowUpdates(new ShowErrorsAction(initializeResponse.paymentForm.errors));
1356
+ }
1357
+ if (initializeResponse.paymentForm) {
1358
+ this.setCreditCardEncryptKey(initializeResponse.paymentForm);
1359
+ }
1360
+ return initializeResponse;
1361
+ })
1362
+ .catch((error) => {
1363
+ throw new ResponseError(error.message);
1364
+ });
1365
+ }
1366
+ setCreditCardEncryptKey(paymentForm) {
1367
+ const publicKeyField = paymentForm.fields.find((field) => field.name === 'public_key');
1368
+ if (!publicKeyField) {
1369
+ return;
1370
+ }
1371
+ this.encryptCreditCardService.setPublicKey(atob(publicKeyField.value));
1305
1372
  }
1306
1373
  }
1307
- SyncService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SyncService, deps: [{ token: syncRequestFactoryToken }, { token: syncResponseFactoryToken }, { token: SecureApiClient }, { token: NextActionService }, { token: SettingsService }], target: i0.ɵɵFactoryTarget.Injectable });
1308
- SyncService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SyncService, providedIn: 'root' });
1309
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SyncService, decorators: [{
1374
+ InitializeService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, deps: [{ token: initializeResponseFactoryToken }, { token: XpsApiService }, { token: SettingsService }, { token: CountryService }, { token: NextActionService }, { token: EncryptCreditCardService }], target: i0.ɵɵFactoryTarget.Injectable });
1375
+ InitializeService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, providedIn: 'root' });
1376
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, decorators: [{
1310
1377
  type: Injectable,
1311
1378
  args: [{
1312
1379
  providedIn: 'root',
1313
1380
  }]
1314
1381
  }], ctorParameters: function () { return [{ type: undefined, decorators: [{
1315
1382
  type: Inject,
1316
- args: [syncRequestFactoryToken]
1317
- }] }, { type: undefined, decorators: [{
1318
- type: Inject,
1319
- args: [syncResponseFactoryToken]
1320
- }] }, { type: SecureApiClient }, { type: NextActionService }, { type: SettingsService }]; } });
1383
+ args: [initializeResponseFactoryToken]
1384
+ }] }, { type: XpsApiService }, { type: SettingsService }, { type: CountryService }, { type: NextActionService }, { type: EncryptCreditCardService }]; } });
1321
1385
 
1322
- class ControlConfig {
1323
- constructor() {
1324
- this.shouldHideUserInput = false;
1386
+ class XpsApiPartRequest {
1387
+ addXpsParameters(parameters) {
1388
+ for (const key in parameters) {
1389
+ this[`xps_${key}`] = parameters[key];
1390
+ }
1325
1391
  }
1326
1392
  }
1327
1393
 
1328
- class TextControlConfig extends ControlConfig {
1394
+ class TokenError extends AppError {
1329
1395
  constructor() {
1330
- super(...arguments);
1331
- this.controlType = 'text';
1396
+ super('XPS API needs token.');
1332
1397
  }
1333
1398
  }
1334
1399
 
1335
- function convert(validator, message) {
1336
- return (control) => {
1337
- const errors = validator(control);
1338
- if (!errors) {
1339
- return errors;
1400
+ class SubmitRequest extends XpsApiPartRequest {
1401
+ constructor(parameters) {
1402
+ super();
1403
+ const { token, fields, form, dfpHash } = parameters;
1404
+ if (token === null) {
1405
+ throw new TokenError();
1340
1406
  }
1341
- const firstErrorKey = Object.keys(errors)[0];
1342
- const firstError = errors[firstErrorKey];
1343
- const error = typeof firstError === 'object' && firstError !== null ? firstError : {};
1344
- error.message = message;
1345
- errors[firstErrorKey] = error;
1346
- return errors;
1347
- };
1407
+ this.access_token = token;
1408
+ if (dfpHash) {
1409
+ this.xps_dfp_hash = dfpHash;
1410
+ }
1411
+ this.addXpsParameters(this.getFieldsValues(fields, form));
1412
+ }
1413
+ getFieldsValues(fields, form) {
1414
+ return fields.reduce((xpsParams, field) => {
1415
+ const formControl = form.get(field.name);
1416
+ xpsParams[field.name] = formControl ? formControl.value : field?.value;
1417
+ return xpsParams;
1418
+ }, {});
1419
+ }
1348
1420
  }
1349
1421
 
1350
- 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
1351
- function convertedEmailValidator() {
1352
- return convert(Validators.pattern(emailRegexp), 'Enter a valid email');
1353
- }
1422
+ const submitRequestFactoryToken = new InjectionToken('SubmitRequest');
1423
+ const submitRequestFactoryProvider = {
1424
+ provide: submitRequestFactoryToken,
1425
+ useValue: (...args) => new SubmitRequest(...args),
1426
+ };
1354
1427
 
1355
- function convertedRequiredValidator() {
1356
- return convert(Validators.required, 'Required');
1357
- }
1428
+ const submitResponseFactoryToken = new InjectionToken('SubmitResponse');
1429
+ const submitResponseFactoryProvider = {
1430
+ provide: submitResponseFactoryToken,
1431
+ useValue: (...args) => new SubmitResponse(...args),
1432
+ };
1358
1433
 
1359
- class Converter {
1360
- constructor(syncService) {
1361
- this.syncService = syncService;
1434
+ class DeviceFingerPrintService {
1435
+ constructor(settingsService) {
1436
+ this.settingsService = settingsService;
1362
1437
  }
1363
- convertToConfig(field, formState) {
1364
- const config = this.createControlConfig(field, formState);
1365
- if (formState?.disabled) {
1366
- config.disabled = true;
1438
+ init() {
1439
+ if (!this.settingsService.isInitialized) {
1440
+ return;
1367
1441
  }
1368
- return config;
1369
- }
1370
- convertToFormControl(field) {
1371
- return new UntypedFormControl(this.getValue(field), this.getValidators(field), this.getAsyncValidators(field));
1442
+ this.antifraudFingerprintLibrary = this.loadAntifraudFingerprintLibrary();
1443
+ this.hash = this.buildHash();
1372
1444
  }
1373
- getValidators(field) {
1374
- const validators = [];
1375
- if (field.isMandatory === "1" /* XpsBoolean.true */) {
1376
- validators.push(convertedRequiredValidator());
1377
- }
1378
- if (field.regex) {
1379
- const match = /^\/(.*)\/([gim]*)$/.exec(field.regex);
1380
- if (match) {
1381
- const pattern = new RegExp(match[1], match[2]);
1382
- const errorMessage = field.validation_error_msg
1383
- ? field.validation_error_msg
1384
- : 'Enter valid data';
1385
- validators.push(convert(Validators.pattern(pattern), errorMessage));
1386
- }
1387
- }
1388
- return validators;
1445
+ async getHash() {
1446
+ return this.hash;
1389
1447
  }
1390
- getAsyncValidators(field) {
1391
- return async () => this.syncService.validate(field);
1448
+ async loadAntifraudFingerprintLibrary() {
1449
+ const library = await import('@xsolla/antifraud-fingerprint');
1450
+ return library.AntifraudFingerprint;
1392
1451
  }
1393
- createDefaultControlConfig(controlConfigClass, field) {
1394
- const config = new controlConfigClass();
1395
- this.copyCommonOptions(config, field);
1396
- return config;
1452
+ async buildHash() {
1453
+ const hash = await this.generate();
1454
+ return JSON.stringify(hash);
1397
1455
  }
1398
- getValue(field) {
1399
- return field.value;
1456
+ async generate() {
1457
+ const fingerprint = await this.makeAntifraudFingerprint();
1458
+ if (!fingerprint) {
1459
+ return null;
1460
+ }
1461
+ await fingerprint.dispatch().catch((err) => console.log(err));
1462
+ const afsHash = await fingerprint.hash();
1463
+ return { '301': afsHash };
1400
1464
  }
1401
- getDataType() {
1402
- return 'text';
1465
+ async makeAntifraudFingerprint() {
1466
+ if (!this.settingsService.token) {
1467
+ return null;
1468
+ }
1469
+ const antifraudFingerprint = await this
1470
+ .antifraudFingerprintLibrary;
1471
+ try {
1472
+ return new antifraudFingerprint({
1473
+ api: {
1474
+ url: 'https://afs.xsolla.com/dfp/api/v1/',
1475
+ token: this.settingsService.token,
1476
+ timeout: 3000,
1477
+ },
1478
+ retry: {
1479
+ num: 1,
1480
+ timeout: 500,
1481
+ },
1482
+ });
1483
+ }
1484
+ catch (error) {
1485
+ return null;
1486
+ }
1403
1487
  }
1404
- getAutocomplete() {
1405
- return 'off';
1488
+ }
1489
+ DeviceFingerPrintService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: DeviceFingerPrintService, deps: [{ token: SettingsService }], target: i0.ɵɵFactoryTarget.Injectable });
1490
+ DeviceFingerPrintService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: DeviceFingerPrintService, providedIn: 'root' });
1491
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: DeviceFingerPrintService, decorators: [{
1492
+ type: Injectable,
1493
+ args: [{
1494
+ providedIn: 'root',
1495
+ }]
1496
+ }], ctorParameters: function () { return [{ type: SettingsService }]; } });
1497
+
1498
+ class SubmitService {
1499
+ constructor(requestFactory, responseFactory, settingsService, deviceFingerPrintService, xpsApiService, encryptCreditCardService) {
1500
+ this.requestFactory = requestFactory;
1501
+ this.responseFactory = responseFactory;
1502
+ this.settingsService = settingsService;
1503
+ this.deviceFingerPrintService = deviceFingerPrintService;
1504
+ this.xpsApiService = xpsApiService;
1505
+ this.encryptCreditCardService = encryptCreditCardService;
1406
1506
  }
1407
- shouldHideUserInput() {
1408
- return false;
1507
+ // NB: Never add 'async' statement for this method!
1508
+ // 'Async' statement wraps current promise into another.
1509
+ // In this way two promises become unequal, that can broke XPS API requests logic.
1510
+ // eslint-disable-next-line @typescript-eslint/promise-function-async
1511
+ request(fields, form) {
1512
+ return (this.deviceFingerPrintService
1513
+ .getHash()
1514
+ // eslint-disable-next-line @typescript-eslint/promise-function-async
1515
+ .then((dfpHash) => {
1516
+ const requestParams = this.requestFactory({
1517
+ token: this.settingsService.token,
1518
+ fields,
1519
+ form,
1520
+ dfpHash,
1521
+ });
1522
+ const encryptedRequest = this.encryptCreditCardService.encryptCreditCard(requestParams);
1523
+ return this.xpsApiService
1524
+ .directPaymentRequest(encryptedRequest)
1525
+ .then((response) => this.responseFactory(response))
1526
+ .catch((error) => {
1527
+ throw new ResponseError(error.message);
1528
+ });
1529
+ }));
1409
1530
  }
1410
- getCommonControlConfig(field) {
1411
- return {
1412
- name: field.name,
1413
- title: field.title,
1414
- labelHint: field.label_hint,
1415
- dataType: this.getDataType(),
1416
- readonly: field.isReadonly === "1" /* XpsBoolean.true */,
1417
- placeholder: field.example,
1418
- autocomplete: this.getAutocomplete(),
1419
- };
1531
+ }
1532
+ 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: XpsApiService }, { token: EncryptCreditCardService }], target: i0.ɵɵFactoryTarget.Injectable });
1533
+ SubmitService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SubmitService, providedIn: 'root' });
1534
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SubmitService, decorators: [{
1535
+ type: Injectable,
1536
+ args: [{ providedIn: 'root' }]
1537
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
1538
+ type: Inject,
1539
+ args: [submitRequestFactoryToken]
1540
+ }] }, { type: undefined, decorators: [{
1541
+ type: Inject,
1542
+ args: [submitResponseFactoryToken]
1543
+ }] }, { type: SettingsService }, { type: DeviceFingerPrintService }, { type: XpsApiService }, { type: EncryptCreditCardService }]; } });
1544
+
1545
+ class EmitDataService {
1546
+ constructor() {
1547
+ this.dataSubject = new Subject();
1548
+ this.data$ = this.dataSubject.asObservable();
1420
1549
  }
1421
- copyCommonOptions(target, field) {
1422
- const commonControlConfig = this.getCommonControlConfig(field);
1423
- Object.keys(commonControlConfig).forEach((sourceKey) => {
1424
- if (!(sourceKey in target)) {
1425
- target[sourceKey] = commonControlConfig[sourceKey];
1426
- }
1427
- });
1550
+ emit(data) {
1551
+ this.dataSubject.next(data);
1428
1552
  }
1429
1553
  }
1430
1554
 
1431
- class EmailConverter extends Converter {
1432
- constructor(syncService) {
1433
- super(syncService);
1434
- }
1435
- getValidators(field) {
1436
- return super.getValidators(field).concat([convertedEmailValidator()]);
1555
+ /* eslint-disable @typescript-eslint/naming-convention */
1556
+ class SyncRequest extends XpsApiPartRequest {
1557
+ constructor(parameters) {
1558
+ super();
1559
+ this.xps_fix_command = 'calculate';
1560
+ this.access_token = parameters.token;
1561
+ const fieldsValues = this.getFieldsValues(parameters.changedField, parameters.fields, parameters.form);
1562
+ this.addXpsParameters({
1563
+ ...fieldsValues,
1564
+ change_element: parameters.changedField.name,
1565
+ });
1437
1566
  }
1438
- createControlConfig(field) {
1439
- const config = this.createDefaultControlConfig(TextControlConfig, field);
1440
- config.autocomplete = 'email';
1441
- config.icon = 'mail';
1442
- return config;
1567
+ getFieldsValues(changedField, fields, form) {
1568
+ const fieldsMap = this.getFieldsMap(fields);
1569
+ return changedField?.javascript?.change.params.reduce((xpsParams, fieldName) => {
1570
+ const formControl = form.get(fieldName);
1571
+ const field = fieldsMap.get(fieldName);
1572
+ if (formControl || field) {
1573
+ xpsParams[fieldName] = formControl?.value ?? field?.value;
1574
+ }
1575
+ return xpsParams;
1576
+ }, {});
1443
1577
  }
1444
- getDataType() {
1445
- return 'email';
1578
+ getFieldsMap(fields) {
1579
+ const map = new Map();
1580
+ fields.forEach((field) => map.set(field.name, field));
1581
+ return map;
1446
1582
  }
1447
1583
  }
1448
- EmailConverter.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: EmailConverter, deps: [{ token: SyncService }], target: i0.ɵɵFactoryTarget.Injectable });
1449
- EmailConverter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: EmailConverter });
1450
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: EmailConverter, decorators: [{
1451
- type: Injectable
1452
- }], ctorParameters: function () { return [{ type: SyncService }]; } });
1453
1584
 
1454
- const restrictedValueValidator = (restrictedValue) => {
1455
- return ({ value }) => {
1456
- return value !== restrictedValue ? null : { valueAllowed: false };
1457
- };
1585
+ const syncRequestFactoryToken = new InjectionToken('SyncRequest');
1586
+ const syncRequestFactoryProvider = {
1587
+ provide: syncRequestFactoryToken,
1588
+ useValue: (...args) => new SyncRequest(...args),
1458
1589
  };
1459
1590
 
1460
- class ZipConverter extends Converter {
1461
- constructor(syncService, countryService) {
1462
- super(syncService);
1463
- this.countryService = countryService;
1464
- this.minLength = 3;
1465
- this.maxLength = 10;
1466
- this.usCountryLength = 5;
1467
- }
1468
- get isUsCountry() {
1469
- return this.countryService.getCountry() === 'US';
1591
+ class SyncResponse {
1592
+ constructor(changedField, response) {
1593
+ this.error = null;
1594
+ const fieldError = response?.errors?.find((error) => error.element_name === changedField.name);
1595
+ if (fieldError) {
1596
+ this.error = {
1597
+ asyncError: {
1598
+ code: fieldError.code,
1599
+ message: fieldError.message,
1600
+ },
1601
+ };
1602
+ }
1603
+ this.fields = Object.keys(response.form).map((key) => response.form[key]);
1604
+ this.parameters = response;
1470
1605
  }
1471
- getValidators(field) {
1472
- const minLength = this.isUsCountry ? this.usCountryLength : this.minLength;
1473
- const maxLength = this.isUsCountry ? this.usCountryLength : this.maxLength;
1474
- const validators = super
1475
- .getValidators(field)
1476
- .concat([
1477
- convert(Validators.minLength(minLength), `Enter at least ${minLength} characters`),
1478
- convert(Validators.maxLength(maxLength), `Enter no more than ${maxLength} characters`),
1479
- ]);
1480
- if (this.isUsCountry) {
1481
- validators.push(convert(restrictedValueValidator('00000'), 'Enter a valid ZIP code'));
1482
- }
1483
- return validators;
1606
+ }
1607
+
1608
+ const syncResponseFactoryToken = new InjectionToken('SyncResponse');
1609
+ const syncResponseFactoryProvider = {
1610
+ provide: syncResponseFactoryToken,
1611
+ useValue: (...args) => new SyncResponse(...args),
1612
+ };
1613
+
1614
+ class SyncService extends EmitDataService {
1615
+ constructor(requestFactory, responseFactory, xpsApiService, nextActionService, settingsService, encryptCreditCardService) {
1616
+ super();
1617
+ this.requestFactory = requestFactory;
1618
+ this.responseFactory = responseFactory;
1619
+ this.xpsApiService = xpsApiService;
1620
+ this.nextActionService = nextActionService;
1621
+ this.settingsService = settingsService;
1622
+ this.encryptCreditCardService = encryptCreditCardService;
1623
+ this.prevFieldSyncStates = {};
1624
+ this.form = new UntypedFormGroup({});
1625
+ this.fields = [];
1626
+ this.fieldAsyncValidation = new Subject();
1484
1627
  }
1485
- createControlConfig(field) {
1486
- const config = this.createDefaultControlConfig(TextControlConfig, field);
1487
- config.icon = 'location';
1488
- if (this.isUsCountry) {
1489
- config.maskConfig = {
1490
- guide: false,
1491
- unmaskModelValue: true,
1492
- showMask: true,
1493
- };
1494
- config.inputMode = 'numeric';
1495
- if (masksFunctionsMap['zip']) {
1496
- config.maskConfig.mask = masksFunctionsMap['zip'];
1497
- }
1628
+ get fieldAsyncValidation$() {
1629
+ return this.fieldAsyncValidation.asObservable();
1630
+ }
1631
+ setup(form, fields) {
1632
+ this.reset();
1633
+ this.form = form;
1634
+ this.fields = fields;
1635
+ }
1636
+ reset() {
1637
+ this.prevFieldSyncStates = {};
1638
+ this.form = new UntypedFormGroup({});
1639
+ this.fields = [];
1640
+ }
1641
+ async validate(field) {
1642
+ if (!this.isReadyField(field)) {
1643
+ return Promise.resolve(null);
1498
1644
  }
1499
- else {
1500
- config.maxLength = this.maxLength;
1645
+ const control = this.form.get(field.name);
1646
+ const value = control?.value;
1647
+ const prevFieldState = this.getPrevFieldSyncState(field);
1648
+ const isInitialValue = value === field.value && !prevFieldState;
1649
+ if (isInitialValue) {
1650
+ return Promise.resolve(null);
1501
1651
  }
1502
- return config;
1652
+ if (prevFieldState && value === prevFieldState.value) {
1653
+ return Promise.resolve(prevFieldState.result).then((response) => {
1654
+ return response?.error ?? null;
1655
+ });
1656
+ }
1657
+ const requestPromise = this.request(field);
1658
+ this.setPrevFieldSyncState(field, value, requestPromise);
1659
+ return requestPromise.then((response) => {
1660
+ this.fieldAsyncValidation.next({
1661
+ value,
1662
+ field,
1663
+ response,
1664
+ });
1665
+ return response.error ?? null;
1666
+ });
1503
1667
  }
1504
- getAutocomplete() {
1505
- return 'postal-code';
1668
+ getSyncValidationErrors(field) {
1669
+ const control = this.form.get(field.name);
1670
+ return control?.errors ?? null;
1506
1671
  }
1507
- getDataType() {
1508
- return 'text';
1672
+ async request(field) {
1673
+ const requestParams = this.requestFactory({
1674
+ token: this.settingsService.token,
1675
+ changedField: field,
1676
+ fields: this.fields,
1677
+ form: this.form,
1678
+ });
1679
+ const encryptedRequest = this.encryptCreditCardService.encryptCreditCard(requestParams);
1680
+ return this.xpsApiService
1681
+ .directPaymentRequest(encryptedRequest)
1682
+ .then((response) => {
1683
+ if (response.errors?.length) {
1684
+ this.nextActionService.emitFlowUpdates(new ShowErrorsAction(response.errors));
1685
+ }
1686
+ this.emit(response);
1687
+ return this.responseFactory(field, response);
1688
+ });
1509
1689
  }
1510
- }
1511
- 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 });
1512
- ZipConverter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ZipConverter });
1513
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ZipConverter, decorators: [{
1514
- type: Injectable
1515
- }], ctorParameters: function () { return [{ type: SyncService }, { type: CountryService }]; } });
1516
-
1517
- function isEmptyInputValue(value) {
1518
- return value == null || value.length === 0;
1519
- }
1520
-
1521
- function isString(value) {
1522
- return typeof value === 'string';
1523
- }
1524
-
1525
- /**
1526
- * Checks number match Luhn algorithm.
1527
- * Based on http://en.wikipedia.org/wiki/Luhn.
1528
- */
1529
- const luhnFormulaValidator = ({ value }) => {
1530
- if (isEmptyInputValue(value) || !isString(value)) {
1531
- return null;
1690
+ isReadyField(field) {
1691
+ const isSyncEnabled = !!field.javascript?.change;
1692
+ const isExistsInForm = !!this.form?.get(field.name);
1693
+ return isSyncEnabled && isExistsInForm;
1532
1694
  }
1533
- const error = {
1534
- rewritableError: {
1535
- message: `Enter a valid card number`,
1536
- },
1537
- };
1538
- if (/[^0-9 -]+/.test(value)) {
1539
- // accept only spaces, digits and dashes
1540
- return error;
1695
+ getPrevFieldSyncState(field) {
1696
+ return this.prevFieldSyncStates[field.name];
1541
1697
  }
1542
- let resultSum = 0;
1543
- let digit = 0;
1544
- let isEven = false;
1545
- const modBase = 10;
1546
- const digitRadix = 10;
1547
- const maxNumber = 9;
1548
- const digits = value.replace(/\D/g, '');
1549
- // Checks if number match Luhn algorithm
1550
- // based on http://en.wikipedia.org/wiki/Luhn
1551
- for (let index = digits.length - 1; index >= 0; index--) {
1552
- const char = digits.charAt(index);
1553
- digit = parseInt(char, digitRadix);
1554
- if (isEven && (digit *= 2) > maxNumber) {
1555
- digit -= maxNumber;
1556
- }
1557
- resultSum += digit;
1558
- isEven = !isEven;
1698
+ setPrevFieldSyncState(field, value, result) {
1699
+ this.prevFieldSyncStates[field.name] = { value, result };
1559
1700
  }
1560
- return resultSum % modBase === 0 ? null : error;
1561
- };
1701
+ }
1702
+ SyncService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SyncService, deps: [{ token: syncRequestFactoryToken }, { token: syncResponseFactoryToken }, { token: XpsApiService }, { token: NextActionService }, { token: SettingsService }, { token: EncryptCreditCardService }], target: i0.ɵɵFactoryTarget.Injectable });
1703
+ SyncService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SyncService, providedIn: 'root' });
1704
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SyncService, decorators: [{
1705
+ type: Injectable,
1706
+ args: [{
1707
+ providedIn: 'root',
1708
+ }]
1709
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
1710
+ type: Inject,
1711
+ args: [syncRequestFactoryToken]
1712
+ }] }, { type: undefined, decorators: [{
1713
+ type: Inject,
1714
+ args: [syncResponseFactoryToken]
1715
+ }] }, { type: XpsApiService }, { type: NextActionService }, { type: SettingsService }, { type: EncryptCreditCardService }]; } });
1562
1716
 
1563
- class CardNumberConfig extends ControlConfig {
1717
+ class ControlConfig {
1564
1718
  constructor() {
1565
- super(...arguments);
1566
- this.controlType = 'card-number';
1567
- this.availableCardTypes = [];
1568
- this.customError = '';
1719
+ this.shouldHideUserInput = false;
1569
1720
  }
1570
1721
  }
1571
1722
 
1572
- const fourBlockMask = '9999 9999 9999 9999';
1573
-
1574
- var CreditCardTypes;
1575
- (function (CreditCardTypes) {
1576
- CreditCardTypes["DEFAULT"] = "0";
1577
- CreditCardTypes["VISA"] = "1";
1578
- CreditCardTypes["MASTERCARD"] = "2";
1579
- CreditCardTypes["MAESTRO"] = "3";
1580
- CreditCardTypes["AMERICAN_EXPRESS"] = "4";
1581
- CreditCardTypes["DINERS_CLUBS"] = "5";
1582
- CreditCardTypes["DISCOVER"] = "6";
1583
- CreditCardTypes["JCB"] = "9";
1584
- CreditCardTypes["DANKORT"] = "11";
1585
- CreditCardTypes["HIPERCARD"] = "12";
1586
- CreditCardTypes["ELO"] = "13";
1587
- CreditCardTypes["AURA"] = "14";
1588
- CreditCardTypes["NARANJA"] = "15";
1589
- CreditCardTypes["MIR"] = "16";
1590
- CreditCardTypes["CHINA_UNION_PAY"] = "17";
1591
- CreditCardTypes["POSTEPAY"] = "18";
1592
- })(CreditCardTypes || (CreditCardTypes = {}));
1723
+ class TextControlConfig extends ControlConfig {
1724
+ constructor() {
1725
+ super(...arguments);
1726
+ this.controlType = 'text';
1727
+ }
1728
+ }
1593
1729
 
1594
- const visa = {
1595
- id: CreditCardTypes.VISA,
1596
- minLength: 13,
1597
- maxLength: 16,
1598
- iconName: 'visa',
1599
- mask: fourBlockMask,
1600
- checkNumber(number) {
1601
- return number.startsWith('4');
1602
- },
1603
- };
1730
+ function convert(validator, message) {
1731
+ return (control) => {
1732
+ const errors = validator(control);
1733
+ if (!errors) {
1734
+ return errors;
1735
+ }
1736
+ const firstErrorKey = Object.keys(errors)[0];
1737
+ const firstError = errors[firstErrorKey];
1738
+ const error = typeof firstError === 'object' && firstError !== null ? firstError : {};
1739
+ error.message = message;
1740
+ errors[firstErrorKey] = error;
1741
+ return errors;
1742
+ };
1743
+ }
1604
1744
 
1605
- const mastercard = {
1606
- id: CreditCardTypes.MASTERCARD,
1607
- minLength: 16,
1608
- maxLength: 16,
1609
- iconName: 'mastercard',
1610
- mask: fourBlockMask,
1611
- checkNumber(number) {
1612
- const subLength = 6;
1613
- const cardNumberSub = number.substring(0, subLength);
1614
- return (new RegExp(/^5[1-5]/).test(number) ||
1615
- (cardNumberSub >= '222100' && cardNumberSub <= '272099'));
1616
- },
1617
- };
1745
+ 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
1746
+ function convertedEmailValidator() {
1747
+ return convert(Validators.pattern(emailRegexp), 'Enter a valid email');
1748
+ }
1618
1749
 
1619
- const defaultMask = '9999 9999 9999 9999 999';
1750
+ function convertedRequiredValidator() {
1751
+ return convert(Validators.required, 'Required');
1752
+ }
1620
1753
 
1621
- const maestro = {
1622
- id: CreditCardTypes.MAESTRO,
1623
- minLength: 12,
1624
- maxLength: 19,
1625
- iconName: 'maestro',
1626
- mask: defaultMask,
1627
- checkNumber(number) {
1628
- return new RegExp(/^(5018)|^(5020)|^(5038)|^(5893)|^(6304)|^(6759)|^(6761)|^(6762)|^(6763)|^(0604)|^(6706)|^(6771)|^(6709)/).test(number);
1629
- },
1630
- maxCvvLength: 3,
1631
- };
1632
-
1633
- const americanExpress = {
1634
- id: CreditCardTypes.AMERICAN_EXPRESS,
1635
- minLength: 15,
1636
- maxLength: 15,
1637
- iconName: 'american-express',
1638
- mask: '9999 999999 99999',
1639
- checkNumber(number) {
1640
- return new RegExp(/^(34)|^(37)/).test(number);
1641
- },
1642
- maxCvvLength: 4,
1643
- };
1644
-
1645
- const dinersClubs = {
1646
- id: CreditCardTypes.DINERS_CLUBS,
1647
- minLength: 14,
1648
- maxLength: 14,
1649
- iconName: 'dinersclub',
1650
- mask: '9999 9999 9999 99',
1651
- checkNumber(number) {
1652
- const regex = /^(36[0-9]|3(?:0[0-59]|[68][0-9])[0-9])/;
1653
- return regex.test(number);
1654
- },
1655
- };
1656
-
1657
- const discover = {
1658
- id: CreditCardTypes.DISCOVER,
1659
- minLength: 16,
1660
- maxLength: 19,
1661
- iconName: 'discover',
1662
- mask: defaultMask,
1663
- checkNumber(number) {
1664
- return new RegExp(/^(6011)|^(622(1(2[6-9]|[3-9][0-9])|[2-8][0-9]{2}|9([01][0-9]|2[0-5])))|^(64[4-9])|^65/).test(number);
1665
- },
1666
- };
1667
-
1668
- const jcb = {
1669
- id: CreditCardTypes.JCB,
1670
- minLength: 15,
1671
- maxLength: 16,
1672
- iconName: 'jcb',
1673
- mask: fourBlockMask,
1674
- checkNumber(number) {
1675
- return new RegExp(/^35(2[89]|[3-8][0-9])/).test(number);
1676
- },
1677
- };
1678
-
1679
- const dankort = {
1680
- id: CreditCardTypes.DANKORT,
1681
- minLength: 16,
1682
- maxLength: 16,
1683
- iconName: 'dankort',
1684
- mask: fourBlockMask,
1685
- checkNumber(number) {
1686
- const subLength = 4;
1687
- const cardNumberSub = number.substring(0, subLength);
1688
- return cardNumberSub === '5019';
1689
- },
1690
- };
1691
-
1692
- const hipercard = {
1693
- id: CreditCardTypes.HIPERCARD,
1694
- minLength: 13,
1695
- maxLength: 19,
1696
- iconName: 'hipercard',
1697
- mask: defaultMask,
1698
- checkNumber(number) {
1699
- return new RegExp(/^((606282|637095|637568)[0-9]|38[0-9]{14,17})/).test(number);
1700
- },
1701
- };
1702
-
1703
- const elo = {
1704
- id: CreditCardTypes.ELO,
1705
- minLength: 16,
1706
- maxLength: 19,
1707
- iconName: 'elo',
1708
- mask: defaultMask,
1709
- checkNumber(number) {
1710
- return new RegExp(/^(40117[8-9]|431274|438935|451416|457393|45763[1-2]|506(699|7[0-6][0-9]|77[0-8])|509\d{3}|504175|627780|636297|636368|65003[1-3]|6500(3[5-9]|4[0-9]|5[0-1])|6504(0[5-9]|[1-3][0-9])|650(4[8-9][0-9]|5[0-2][0-9]|53[0-8])|6505(4[1-9]|[5-8][0-9]|9[0-8])|6507(0[0-9]|1[0-8])|65072[0-7]|6509(0[1-9]|1[0-9]|20)|6516(5[2-9]|[6-7][0-9])|6550([0-1][0-9]|2[1-9]|[3-4][0-9]|5[0-8]))/).test(number);
1711
- },
1712
- };
1713
-
1714
- const aura = {
1715
- id: CreditCardTypes.AURA,
1716
- minLength: 16,
1717
- maxLength: 19,
1718
- iconName: 'aura',
1719
- mask: defaultMask,
1720
- checkNumber(number) {
1721
- const subLength = 8;
1722
- const cardNumberSub = number.substring(0, subLength);
1723
- return ['50786000', '50786018', '50786019'].includes(cardNumberSub);
1724
- },
1725
- };
1726
-
1727
- const naranja = {
1728
- id: CreditCardTypes.NARANJA,
1729
- minLength: 12,
1730
- maxLength: 19,
1731
- iconName: 'naranja',
1732
- mask: defaultMask,
1733
- checkNumber(number) {
1734
- const subLength = 6;
1735
- const cardNumberSub = number.substring(0, subLength);
1736
- return cardNumberSub === '589562';
1737
- },
1738
- };
1739
-
1740
- const mir = {
1741
- id: CreditCardTypes.MIR,
1742
- minLength: 16,
1743
- maxLength: 16,
1744
- iconName: 'mir',
1745
- mask: defaultMask,
1746
- checkNumber(number) {
1747
- const subLength = 4;
1748
- const cardNumberSub = number.substring(0, subLength);
1749
- return cardNumberSub >= '2200' && cardNumberSub <= '2204';
1750
- },
1751
- };
1752
-
1753
- const chinaUnionPay = {
1754
- id: CreditCardTypes.CHINA_UNION_PAY,
1755
- minLength: 16,
1756
- maxLength: 19,
1757
- iconName: 'unionpay',
1758
- mask: '999 9999 9999 99999999',
1759
- checkNumber(number) {
1760
- return number.startsWith('62');
1761
- },
1762
- };
1763
-
1764
- const defaultCard = {
1765
- id: CreditCardTypes.DEFAULT,
1766
- minLength: 12,
1767
- maxLength: 19,
1768
- iconName: null,
1769
- mask: defaultMask,
1770
- checkNumber() {
1754
+ class Converter {
1755
+ constructor(syncService) {
1756
+ this.syncService = syncService;
1757
+ }
1758
+ convertToConfig(field, formState) {
1759
+ const config = this.createControlConfig(field, formState);
1760
+ if (formState?.disabled) {
1761
+ config.disabled = true;
1762
+ }
1763
+ return config;
1764
+ }
1765
+ convertToFormControl(field) {
1766
+ return new UntypedFormControl(this.getValue(field), this.getValidators(field), this.getAsyncValidators(field));
1767
+ }
1768
+ getValidators(field) {
1769
+ const validators = [];
1770
+ if (field.isMandatory === "1" /* XpsBoolean.true */) {
1771
+ validators.push(convertedRequiredValidator());
1772
+ }
1773
+ if (field.regex) {
1774
+ const match = /^\/(.*)\/([gim]*)$/.exec(field.regex);
1775
+ if (match) {
1776
+ const pattern = new RegExp(match[1], match[2]);
1777
+ const errorMessage = field.validation_error_msg
1778
+ ? field.validation_error_msg
1779
+ : 'Enter valid data';
1780
+ validators.push(convert(Validators.pattern(pattern), errorMessage));
1781
+ }
1782
+ }
1783
+ return validators;
1784
+ }
1785
+ getAsyncValidators(field) {
1786
+ return async () => this.syncService.validate(field);
1787
+ }
1788
+ createDefaultControlConfig(controlConfigClass, field) {
1789
+ const config = new controlConfigClass();
1790
+ this.copyCommonOptions(config, field);
1791
+ return config;
1792
+ }
1793
+ getValue(field) {
1794
+ return field.value;
1795
+ }
1796
+ getDataType() {
1797
+ return 'text';
1798
+ }
1799
+ getAutocomplete() {
1800
+ return 'off';
1801
+ }
1802
+ shouldHideUserInput() {
1771
1803
  return false;
1772
- },
1773
- };
1804
+ }
1805
+ getCommonControlConfig(field) {
1806
+ return {
1807
+ name: field.name,
1808
+ title: field.title,
1809
+ labelHint: field.label_hint,
1810
+ dataType: this.getDataType(),
1811
+ readonly: field.isReadonly === "1" /* XpsBoolean.true */,
1812
+ placeholder: field.example,
1813
+ autocomplete: this.getAutocomplete(),
1814
+ };
1815
+ }
1816
+ copyCommonOptions(target, field) {
1817
+ const commonControlConfig = this.getCommonControlConfig(field);
1818
+ Object.keys(commonControlConfig).forEach((sourceKey) => {
1819
+ if (!(sourceKey in target)) {
1820
+ target[sourceKey] = commonControlConfig[sourceKey];
1821
+ }
1822
+ });
1823
+ }
1824
+ }
1774
1825
 
1775
- const postePay = {
1776
- id: CreditCardTypes.POSTEPAY,
1777
- minLength: 12,
1778
- maxLength: 19,
1779
- iconName: 'poste_pay',
1780
- mask: '9999 9999 9999 9999 999',
1781
- checkNumber(number) {
1782
- const regex = /^(5018)|^(5020)|^(5038)|^(5893)|^(6304)|^(6759)|^(6761)|^(6762)|^(6763)|^(0604)|^(6706)|^(6771)|^(6709)/;
1783
- return regex.test(number);
1784
- },
1826
+ class EmailConverter extends Converter {
1827
+ constructor(syncService) {
1828
+ super(syncService);
1829
+ }
1830
+ getValidators(field) {
1831
+ return super.getValidators(field).concat([convertedEmailValidator()]);
1832
+ }
1833
+ createControlConfig(field) {
1834
+ const config = this.createDefaultControlConfig(TextControlConfig, field);
1835
+ config.autocomplete = 'email';
1836
+ config.icon = 'mail';
1837
+ return config;
1838
+ }
1839
+ getDataType() {
1840
+ return 'email';
1841
+ }
1842
+ }
1843
+ EmailConverter.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: EmailConverter, deps: [{ token: SyncService }], target: i0.ɵɵFactoryTarget.Injectable });
1844
+ EmailConverter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: EmailConverter });
1845
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: EmailConverter, decorators: [{
1846
+ type: Injectable
1847
+ }], ctorParameters: function () { return [{ type: SyncService }]; } });
1848
+
1849
+ const restrictedValueValidator = (restrictedValue) => {
1850
+ return ({ value }) => {
1851
+ return value !== restrictedValue ? null : { valueAllowed: false };
1852
+ };
1785
1853
  };
1786
1854
 
1787
- /**
1788
- * order does matter
1789
- * settings with more specific pattern should be placed above
1790
- * Example:
1791
- * - 12*
1792
- * - 12
1793
- * - 1
1794
- * "12*" pattern should be checked first, otherwise pattern "1" will be taken
1795
- * before "12*" checked
1796
- */
1797
- const orderedCardSettings = [
1798
- aura,
1799
- naranja,
1800
- maestro,
1801
- postePay,
1802
- elo,
1803
- discover,
1804
- dankort,
1805
- hipercard,
1806
- mir,
1807
- jcb,
1808
- dinersClubs,
1809
- americanExpress,
1810
- mastercard,
1811
- chinaUnionPay,
1812
- visa,
1813
- defaultCard,
1814
- ];
1855
+ class ZipConverter extends Converter {
1856
+ constructor(syncService, countryService) {
1857
+ super(syncService);
1858
+ this.countryService = countryService;
1859
+ this.minLength = 3;
1860
+ this.maxLength = 10;
1861
+ this.usCountryLength = 5;
1862
+ }
1863
+ get isUsCountry() {
1864
+ return this.countryService.getCountry() === 'US';
1865
+ }
1866
+ getValidators(field) {
1867
+ const minLength = this.isUsCountry ? this.usCountryLength : this.minLength;
1868
+ const maxLength = this.isUsCountry ? this.usCountryLength : this.maxLength;
1869
+ const validators = super
1870
+ .getValidators(field)
1871
+ .concat([
1872
+ convert(Validators.minLength(minLength), `Enter at least ${minLength} characters`),
1873
+ convert(Validators.maxLength(maxLength), `Enter no more than ${maxLength} characters`),
1874
+ ]);
1875
+ if (this.isUsCountry) {
1876
+ validators.push(convert(restrictedValueValidator('00000'), 'Enter a valid ZIP code'));
1877
+ }
1878
+ return validators;
1879
+ }
1880
+ createControlConfig(field) {
1881
+ const config = this.createDefaultControlConfig(TextControlConfig, field);
1882
+ config.icon = 'location';
1883
+ if (this.isUsCountry) {
1884
+ config.maskConfig = {
1885
+ guide: false,
1886
+ unmaskModelValue: true,
1887
+ showMask: true,
1888
+ };
1889
+ config.inputMode = 'numeric';
1890
+ if (masksFunctionsMap['zip']) {
1891
+ config.maskConfig.mask = masksFunctionsMap['zip'];
1892
+ }
1893
+ }
1894
+ else {
1895
+ config.maxLength = this.maxLength;
1896
+ }
1897
+ return config;
1898
+ }
1899
+ getAutocomplete() {
1900
+ return 'postal-code';
1901
+ }
1902
+ getDataType() {
1903
+ return 'text';
1904
+ }
1905
+ }
1906
+ 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 });
1907
+ ZipConverter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ZipConverter });
1908
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ZipConverter, decorators: [{
1909
+ type: Injectable
1910
+ }], ctorParameters: function () { return [{ type: SyncService }, { type: CountryService }]; } });
1815
1911
 
1816
- const creditCardsMap = {
1817
- [CreditCardTypes.DEFAULT]: defaultCard,
1818
- [CreditCardTypes.VISA]: visa,
1819
- [CreditCardTypes.MASTERCARD]: mastercard,
1820
- [CreditCardTypes.MAESTRO]: maestro,
1821
- [CreditCardTypes.AMERICAN_EXPRESS]: americanExpress,
1822
- [CreditCardTypes.DINERS_CLUBS]: dinersClubs,
1823
- [CreditCardTypes.DISCOVER]: discover,
1824
- [CreditCardTypes.JCB]: jcb,
1825
- [CreditCardTypes.DANKORT]: dankort,
1826
- [CreditCardTypes.HIPERCARD]: hipercard,
1827
- [CreditCardTypes.ELO]: elo,
1828
- [CreditCardTypes.AURA]: aura,
1829
- [CreditCardTypes.NARANJA]: naranja,
1830
- [CreditCardTypes.MIR]: mir,
1831
- [CreditCardTypes.CHINA_UNION_PAY]: chinaUnionPay,
1832
- [CreditCardTypes.POSTEPAY]: postePay,
1833
- };
1912
+ function isEmptyInputValue(value) {
1913
+ return value == null || value.length === 0;
1914
+ }
1834
1915
 
1835
- class CreditCardService {
1836
- getBinNumber(cardNumber) {
1837
- const binNumberLength = 6;
1838
- return cardNumber.replace(/\s+/g, '').substring(0, binNumberLength);
1839
- }
1840
- getAccountSuffix(cardNumber) {
1841
- const accountSuffixLength = 4;
1842
- return cardNumber
1843
- .replace(/\s+/g, '')
1844
- .substring(cardNumber.length - accountSuffixLength);
1916
+ function isString(value) {
1917
+ return typeof value === 'string';
1918
+ }
1919
+
1920
+ /**
1921
+ * Checks number match Luhn algorithm.
1922
+ * Based on http://en.wikipedia.org/wiki/Luhn.
1923
+ */
1924
+ const luhnFormulaValidator = ({ value }) => {
1925
+ if (isEmptyInputValue(value) || !isString(value)) {
1926
+ return null;
1845
1927
  }
1846
- getTypeByNumber(cardNumber) {
1847
- cardNumber = cardNumber.replace(/\s+/g, '');
1848
- const cardSettings = orderedCardSettings.find((settings) => {
1849
- const isNumberMatched = settings.checkNumber(cardNumber);
1850
- return isNumberMatched ? settings.id : false;
1851
- });
1852
- return cardSettings ? cardSettings.id : defaultCard.id;
1928
+ const error = {
1929
+ rewritableError: {
1930
+ message: `Enter a valid card number`,
1931
+ },
1932
+ };
1933
+ if (/[^0-9 -]+/.test(value)) {
1934
+ // accept only spaces, digits and dashes
1935
+ return error;
1853
1936
  }
1854
- getCreditCardSettings(cardType) {
1855
- const creditCard = creditCardsMap[cardType];
1856
- if (!creditCard) {
1857
- return defaultCard;
1937
+ let resultSum = 0;
1938
+ let digit = 0;
1939
+ let isEven = false;
1940
+ const modBase = 10;
1941
+ const digitRadix = 10;
1942
+ const maxNumber = 9;
1943
+ const digits = value.replace(/\D/g, '');
1944
+ // Checks if number match Luhn algorithm
1945
+ // based on http://en.wikipedia.org/wiki/Luhn
1946
+ for (let index = digits.length - 1; index >= 0; index--) {
1947
+ const char = digits.charAt(index);
1948
+ digit = parseInt(char, digitRadix);
1949
+ if (isEven && (digit *= 2) > maxNumber) {
1950
+ digit -= maxNumber;
1858
1951
  }
1859
- return creditCard;
1952
+ resultSum += digit;
1953
+ isEven = !isEven;
1954
+ }
1955
+ return resultSum % modBase === 0 ? null : error;
1956
+ };
1957
+
1958
+ class CardNumberConfig extends ControlConfig {
1959
+ constructor() {
1960
+ super(...arguments);
1961
+ this.controlType = 'card-number';
1962
+ this.availableCardTypes = [];
1963
+ this.customError = '';
1860
1964
  }
1861
1965
  }
1862
- CreditCardService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CreditCardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1863
- CreditCardService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CreditCardService, providedIn: 'root' });
1864
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CreditCardService, decorators: [{
1865
- type: Injectable,
1866
- args: [{
1867
- providedIn: 'root',
1868
- }]
1869
- }] });
1870
1966
 
1871
1967
  class CreditCardMinLengthValidator {
1872
1968
  constructor(creditService) {
@@ -1889,55 +1985,363 @@ class CreditCardMinLengthValidator {
1889
1985
  };
1890
1986
  }
1891
1987
  }
1892
- CreditCardMinLengthValidator.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CreditCardMinLengthValidator, deps: [{ token: CreditCardService }], target: i0.ɵɵFactoryTarget.Injectable });
1893
- CreditCardMinLengthValidator.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CreditCardMinLengthValidator });
1894
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CreditCardMinLengthValidator, decorators: [{
1988
+ CreditCardMinLengthValidator.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CreditCardMinLengthValidator, deps: [{ token: CreditCardService }], target: i0.ɵɵFactoryTarget.Injectable });
1989
+ CreditCardMinLengthValidator.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CreditCardMinLengthValidator });
1990
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CreditCardMinLengthValidator, decorators: [{
1991
+ type: Injectable
1992
+ }], ctorParameters: function () { return [{ type: CreditCardService }]; } });
1993
+
1994
+ class CardNumberConverter extends Converter {
1995
+ constructor(syncService, maxLengthValidator, minLengthValidator) {
1996
+ super(syncService);
1997
+ this.maxLengthValidator = maxLengthValidator;
1998
+ this.minLengthValidator = minLengthValidator;
1999
+ }
2000
+ getValidators(field) {
2001
+ return super
2002
+ .getValidators(field)
2003
+ .concat([
2004
+ luhnFormulaValidator,
2005
+ this.minLengthValidator.validate,
2006
+ this.maxLengthValidator.validate,
2007
+ ]);
2008
+ }
2009
+ createControlConfig(field, formState) {
2010
+ const config = this.createDefaultControlConfig(CardNumberConfig, field);
2011
+ config.placeholder = config.title;
2012
+ config.availableCardTypes =
2013
+ formState?.availableCardTypes ?? [];
2014
+ config.activeCardType = formState?.activeCardType;
2015
+ config.customError = formState?.customError;
2016
+ config.disabled = formState?.disabled ?? false;
2017
+ return config;
2018
+ }
2019
+ getAutocomplete() {
2020
+ return 'cc-number';
2021
+ }
2022
+ getDataType() {
2023
+ return 'text';
2024
+ }
2025
+ }
2026
+ CardNumberConverter.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CardNumberConverter, deps: [{ token: SyncService }, { token: CreditCardMinLengthValidator }, { token: CreditCardMinLengthValidator }], target: i0.ɵɵFactoryTarget.Injectable });
2027
+ CardNumberConverter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CardNumberConverter });
2028
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CardNumberConverter, decorators: [{
2029
+ type: Injectable
2030
+ }], ctorParameters: function () { return [{ type: SyncService }, { type: CreditCardMinLengthValidator }, { type: CreditCardMinLengthValidator }]; } });
2031
+
2032
+ class CardExpirationConverter extends Converter {
2033
+ constructor(syncService) {
2034
+ super(syncService);
2035
+ }
2036
+ getValidators() {
2037
+ return [];
2038
+ }
2039
+ createControlConfig(field, formState) {
2040
+ const config = this.createDefaultControlConfig(TextControlConfig, field);
2041
+ config.maskConfig = {
2042
+ mask: '99',
2043
+ guide: false,
2044
+ };
2045
+ config.inputMode = 'numeric';
2046
+ config.title = 'date';
2047
+ config.disabled = formState?.disabled ?? false;
2048
+ return config;
2049
+ }
2050
+ getAutocomplete() {
2051
+ return 'cc-exp';
2052
+ }
2053
+ getDataType() {
2054
+ return 'text';
2055
+ }
2056
+ }
2057
+ CardExpirationConverter.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CardExpirationConverter, deps: [{ token: SyncService }], target: i0.ɵɵFactoryTarget.Injectable });
2058
+ CardExpirationConverter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CardExpirationConverter });
2059
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CardExpirationConverter, decorators: [{
2060
+ type: Injectable
2061
+ }], ctorParameters: function () { return [{ type: SyncService }]; } });
2062
+
2063
+ class CvvConverter extends Converter {
2064
+ constructor(syncService) {
2065
+ super(syncService);
2066
+ // eslint-disable-next-line @typescript-eslint/no-magic-numbers
2067
+ this.maxFieldLength = 4;
2068
+ }
2069
+ getValidators() {
2070
+ return [];
2071
+ }
2072
+ createControlConfig(field, formState) {
2073
+ const config = this.createDefaultControlConfig(TextControlConfig, field);
2074
+ config.maskConfig = {
2075
+ mask: () => new Array(this.maxFieldLength).fill('9').join(''),
2076
+ unmaskModelValue: false,
2077
+ guide: false,
2078
+ };
2079
+ config.tooltip = {
2080
+ text: 'The code is on the back of your card',
2081
+ image: 'cvv',
2082
+ parentField: FieldNames.cvv,
2083
+ position: 'input',
2084
+ analyticsAction: 'show-cvv-tooltip',
2085
+ };
2086
+ config.inputMode = 'numeric';
2087
+ config.shouldHideUserInput = this.shouldHideUserInput();
2088
+ config.disabled = formState?.disabled ?? false;
2089
+ return config;
2090
+ }
2091
+ getAutocomplete() {
2092
+ return 'cc-csc';
2093
+ }
2094
+ getDataType() {
2095
+ return 'password';
2096
+ }
2097
+ shouldHideUserInput() {
2098
+ return true;
2099
+ }
2100
+ }
2101
+ CvvConverter.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CvvConverter, deps: [{ token: SyncService }], target: i0.ɵɵFactoryTarget.Injectable });
2102
+ CvvConverter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CvvConverter });
2103
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CvvConverter, decorators: [{
2104
+ type: Injectable
2105
+ }], ctorParameters: function () { return [{ type: SyncService }]; } });
2106
+
2107
+ const birthdateValidator = ({ value }) => {
2108
+ if (isEmptyInputValue(value) || typeof value !== 'string') {
2109
+ return null;
2110
+ }
2111
+ const error = {
2112
+ invalidBirthDate: {
2113
+ message: `Enter a valid birth date`,
2114
+ },
2115
+ };
2116
+ const dateArr = value.split('/');
2117
+ const datePartsCount = 3;
2118
+ const dayIndex = 0;
2119
+ const monthIndex = 1;
2120
+ const yearIndex = 2;
2121
+ const maxMonths = 12;
2122
+ const maxDays = 31;
2123
+ const minAge = 16;
2124
+ const maxAge = 120;
2125
+ if (dateArr.length < datePartsCount) {
2126
+ return null;
2127
+ }
2128
+ if (+dateArr[monthIndex] > maxMonths || +dateArr[dayIndex] > maxDays) {
2129
+ return error;
2130
+ }
2131
+ const currentDate = new Date(+dateArr[yearIndex], +dateArr[monthIndex], +dateArr[dayIndex]);
2132
+ const nowDate = new Date();
2133
+ if (isNaN(currentDate.getFullYear()) ||
2134
+ nowDate.getFullYear() - currentDate.getFullYear() <= minAge ||
2135
+ nowDate.getFullYear() - currentDate.getFullYear() > maxAge) {
2136
+ return error;
2137
+ }
2138
+ else {
2139
+ return null;
2140
+ }
2141
+ };
2142
+
2143
+ class BirthDateConverter extends Converter {
2144
+ constructor(syncService) {
2145
+ super(syncService);
2146
+ }
2147
+ getValidators(field) {
2148
+ return super
2149
+ .getValidators(field)
2150
+ .concat([
2151
+ convert(Validators.pattern(/^[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{4}$/), `Enter a valid birth date`),
2152
+ birthdateValidator,
2153
+ ]);
2154
+ }
2155
+ createControlConfig(field) {
2156
+ const config = this.createDefaultControlConfig(TextControlConfig, field);
2157
+ config.maskConfig = {
2158
+ mask: '99/99/9999',
2159
+ unmaskModelValue: false,
2160
+ guide: false,
2161
+ };
2162
+ config.placeholder = `DD/MM/YYYY`;
2163
+ config.inputMode = 'numeric';
2164
+ return config;
2165
+ }
2166
+ }
2167
+ BirthDateConverter.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: BirthDateConverter, deps: [{ token: SyncService }], target: i0.ɵɵFactoryTarget.Injectable });
2168
+ BirthDateConverter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: BirthDateConverter });
2169
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: BirthDateConverter, decorators: [{
2170
+ type: Injectable
2171
+ }], ctorParameters: function () { return [{ type: SyncService }]; } });
2172
+
2173
+ class CardholderNameConverter extends Converter {
2174
+ constructor(syncService) {
2175
+ super(syncService);
2176
+ }
2177
+ createControlConfig(field) {
2178
+ return this.createDefaultControlConfig(TextControlConfig, field);
2179
+ }
2180
+ getAutocomplete() {
2181
+ return 'cc-name';
2182
+ }
2183
+ getDataType() {
2184
+ return 'text';
2185
+ }
2186
+ }
2187
+ CardholderNameConverter.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CardholderNameConverter, deps: [{ token: SyncService }], target: i0.ɵɵFactoryTarget.Injectable });
2188
+ CardholderNameConverter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CardholderNameConverter });
2189
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CardholderNameConverter, decorators: [{
2190
+ type: Injectable
2191
+ }], ctorParameters: function () { return [{ type: SyncService }]; } });
2192
+
2193
+ const cpfNameRegex = /^[a-zA-ZÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ.'-]{2,50}(?: [a-zA-ZÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ.'-]{2,50}){1,8}$/i; // tslint:disable-line
2194
+
2195
+ class CpfNameConverter extends Converter {
2196
+ constructor(syncService) {
2197
+ super(syncService);
2198
+ }
2199
+ getValidators(field) {
2200
+ return super
2201
+ .getValidators(field)
2202
+ .concat([
2203
+ convert(Validators.pattern(cpfNameRegex), `Enter a valid name`),
2204
+ ]);
2205
+ }
2206
+ createControlConfig(field) {
2207
+ const config = this.createDefaultControlConfig(TextControlConfig, field);
2208
+ config.tooltip = {
2209
+ text: `Where to find your name`,
2210
+ image: 'cpf-name',
2211
+ };
2212
+ return config;
2213
+ }
2214
+ }
2215
+ CpfNameConverter.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CpfNameConverter, deps: [{ token: SyncService }], target: i0.ɵɵFactoryTarget.Injectable });
2216
+ CpfNameConverter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CpfNameConverter });
2217
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CpfNameConverter, decorators: [{
2218
+ type: Injectable
2219
+ }], ctorParameters: function () { return [{ type: SyncService }]; } });
2220
+
2221
+ class CpfNumberConverter extends Converter {
2222
+ constructor(syncService) {
2223
+ super(syncService);
2224
+ }
2225
+ createControlConfig(field) {
2226
+ const config = this.createDefaultControlConfig(TextControlConfig, field);
2227
+ config.maskConfig = {
2228
+ mask: '999.999.999-99',
2229
+ unmaskModelValue: true,
2230
+ guide: false,
2231
+ };
2232
+ config.inputMode = 'numeric';
2233
+ config.placeholder = '000.000.000-00';
2234
+ config.tooltip = {
2235
+ text: `Where to find your registration number`,
2236
+ image: 'cpf-number',
2237
+ };
2238
+ return config;
2239
+ }
2240
+ }
2241
+ CpfNumberConverter.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CpfNumberConverter, deps: [{ token: SyncService }], target: i0.ɵɵFactoryTarget.Injectable });
2242
+ CpfNumberConverter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CpfNumberConverter });
2243
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CpfNumberConverter, decorators: [{
2244
+ type: Injectable
2245
+ }], ctorParameters: function () { return [{ type: SyncService }]; } });
2246
+
2247
+ class StreetNumberConverter extends Converter {
2248
+ constructor(syncService) {
2249
+ super(syncService);
2250
+ }
2251
+ getValidators(field, formState) {
2252
+ const validators = super.getValidators(field);
2253
+ if (formState?.country === 'BL') {
2254
+ validators.push(convert(restrictedValueValidator('0'), `Enter a valid building number`));
2255
+ }
2256
+ return validators;
2257
+ }
2258
+ createControlConfig(field) {
2259
+ return this.createDefaultControlConfig(TextControlConfig, field);
2260
+ }
2261
+ }
2262
+ StreetNumberConverter.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: StreetNumberConverter, deps: [{ token: SyncService }], target: i0.ɵɵFactoryTarget.Injectable });
2263
+ StreetNumberConverter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: StreetNumberConverter });
2264
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: StreetNumberConverter, decorators: [{
2265
+ type: Injectable
2266
+ }], ctorParameters: function () { return [{ type: SyncService }]; } });
2267
+
2268
+ class TextConverter extends Converter {
2269
+ constructor(syncService) {
2270
+ super(syncService);
2271
+ }
2272
+ createControlConfig(field) {
2273
+ return this.createDefaultControlConfig(TextControlConfig, field);
2274
+ }
2275
+ }
2276
+ TextConverter.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: TextConverter, deps: [{ token: SyncService }], target: i0.ɵɵFactoryTarget.Injectable });
2277
+ TextConverter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: TextConverter });
2278
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: TextConverter, decorators: [{
1895
2279
  type: Injectable
1896
- }], ctorParameters: function () { return [{ type: CreditCardService }]; } });
2280
+ }], ctorParameters: function () { return [{ type: SyncService }]; } });
1897
2281
 
1898
- class CardNumberConverter extends Converter {
1899
- constructor(syncService, maxLengthValidator, minLengthValidator) {
2282
+ function phoneValidator() {
2283
+ return convert(Validators.pattern(/^\d*$/), 'Enter a valid phone');
2284
+ }
2285
+
2286
+ function minLengthValidator(minLength) {
2287
+ return convert(Validators.minLength(minLength), `Enter at least ${minLength} characters`);
2288
+ }
2289
+
2290
+ function maxLengthValidator(maxLength) {
2291
+ return convert(Validators.maxLength(maxLength), `Enter no more than ${maxLength} characters`);
2292
+ }
2293
+
2294
+ class PhoneControlConfig extends ControlConfig {
2295
+ constructor() {
2296
+ super(...arguments);
2297
+ this.controlType = 'phone';
2298
+ }
2299
+ }
2300
+
2301
+ class PhoneConverter extends Converter {
2302
+ constructor(syncService) {
1900
2303
  super(syncService);
1901
- this.maxLengthValidator = maxLengthValidator;
1902
- this.minLengthValidator = minLengthValidator;
1903
2304
  }
1904
2305
  getValidators(field) {
2306
+ const minLength = 10;
2307
+ const maxLength = 15;
1905
2308
  return super
1906
2309
  .getValidators(field)
1907
2310
  .concat([
1908
- luhnFormulaValidator,
1909
- this.minLengthValidator.validate,
1910
- this.maxLengthValidator.validate,
2311
+ convertedRequiredValidator(),
2312
+ phoneValidator(),
2313
+ minLengthValidator(minLength),
2314
+ maxLengthValidator(maxLength),
1911
2315
  ]);
1912
2316
  }
1913
- createControlConfig(field, formState) {
1914
- const config = this.createDefaultControlConfig(CardNumberConfig, field);
1915
- config.placeholder = config.title;
1916
- config.availableCardTypes =
1917
- formState?.availableCardTypes ?? [];
1918
- config.activeCardType = formState?.activeCardType;
1919
- config.customError = formState?.customError;
1920
- config.disabled = formState?.disabled ?? false;
2317
+ createControlConfig(field) {
2318
+ const config = this.createDefaultControlConfig(PhoneControlConfig, field);
2319
+ config.inputMode = 'numeric';
1921
2320
  return config;
1922
2321
  }
1923
- getAutocomplete() {
1924
- return 'cc-number';
1925
- }
1926
- getDataType() {
1927
- return 'text';
1928
- }
1929
2322
  }
1930
- CardNumberConverter.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CardNumberConverter, deps: [{ token: SyncService }, { token: CreditCardMinLengthValidator }, { token: CreditCardMinLengthValidator }], target: i0.ɵɵFactoryTarget.Injectable });
1931
- CardNumberConverter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CardNumberConverter });
1932
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CardNumberConverter, decorators: [{
2323
+ PhoneConverter.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PhoneConverter, deps: [{ token: SyncService }], target: i0.ɵɵFactoryTarget.Injectable });
2324
+ PhoneConverter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PhoneConverter });
2325
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PhoneConverter, decorators: [{
1933
2326
  type: Injectable
1934
- }], ctorParameters: function () { return [{ type: SyncService }, { type: CreditCardMinLengthValidator }, { type: CreditCardMinLengthValidator }]; } });
2327
+ }], ctorParameters: function () { return [{ type: SyncService }]; } });
1935
2328
 
1936
2329
  const convertersMapToken = new InjectionToken('ConvertersTokensMap');
1937
2330
  const convertersMap = {
1938
2331
  zip: ZipConverter,
1939
2332
  email: EmailConverter,
1940
2333
  card_number: CardNumberConverter,
2334
+ card_month: CardExpirationConverter,
2335
+ card_year: CardExpirationConverter,
2336
+ cvv: CvvConverter,
2337
+ extra_cvv: CvvConverter,
2338
+ cardholdername: CardholderNameConverter,
2339
+ cpf_number: CpfNumberConverter,
2340
+ cpf_name: CpfNameConverter,
2341
+ birth_date: BirthDateConverter,
2342
+ street_number: StreetNumberConverter,
2343
+ text: TextConverter,
2344
+ phone: PhoneConverter,
1941
2345
  };
1942
2346
 
1943
2347
  class ControlConfigService {
@@ -2099,6 +2503,13 @@ const statusSearchParamsMap = new Map([
2099
2503
  ],
2100
2504
  ]);
2101
2505
 
2506
+ class TerminalError extends AppError {
2507
+ constructor(message, code) {
2508
+ super(message);
2509
+ this.code = code;
2510
+ }
2511
+ }
2512
+
2102
2513
  class XpsApiPart {
2103
2514
  constructor() {
2104
2515
  this.response = new BehaviorSubject(null);
@@ -2354,23 +2765,20 @@ const checkStatusResponseFactoryProvider = {
2354
2765
  };
2355
2766
 
2356
2767
  class CheckStatusService extends XpsApiPart {
2357
- constructor(secureApiClient, settingsService, requestFactory, responseFactory) {
2768
+ constructor(xpsApiService, settingsService, requestFactory, responseFactory) {
2358
2769
  super();
2359
- this.secureApiClient = secureApiClient;
2770
+ this.xpsApiService = xpsApiService;
2360
2771
  this.settingsService = settingsService;
2361
2772
  this.requestFactory = requestFactory;
2362
2773
  this.responseFactory = responseFactory;
2363
- this.apiRoute = 'directpayment';
2364
2774
  }
2365
2775
  setRequestParams(invoice) {
2366
2776
  this.invoice = invoice;
2367
2777
  }
2368
2778
  request() {
2369
2779
  const requestParams = this.requestFactory(this.settingsService.token, this.invoice);
2370
- lastValueFrom(this.secureApiClient.post(this.apiRoute, new URLSearchParams({ ...requestParams }), {
2371
- headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
2372
- responseType: 'json',
2373
- }))
2780
+ this.xpsApiService
2781
+ .directPaymentRequest(requestParams)
2374
2782
  .then((response) => {
2375
2783
  const checkStatusResponse = this.responseFactory({
2376
2784
  status: response.status,
@@ -2384,14 +2792,14 @@ class CheckStatusService extends XpsApiPart {
2384
2792
  });
2385
2793
  }
2386
2794
  }
2387
- CheckStatusService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CheckStatusService, deps: [{ token: SecureApiClient }, { token: SettingsService }, { token: checkStatusRequestFactoryToken }, { token: checkStatusResponseFactoryToken }], target: i0.ɵɵFactoryTarget.Injectable });
2795
+ CheckStatusService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CheckStatusService, deps: [{ token: XpsApiService }, { token: SettingsService }, { token: checkStatusRequestFactoryToken }, { token: checkStatusResponseFactoryToken }], target: i0.ɵɵFactoryTarget.Injectable });
2388
2796
  CheckStatusService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CheckStatusService, providedIn: 'root' });
2389
2797
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CheckStatusService, decorators: [{
2390
2798
  type: Injectable,
2391
2799
  args: [{
2392
2800
  providedIn: 'root',
2393
2801
  }]
2394
- }], ctorParameters: function () { return [{ type: SecureApiClient }, { type: SettingsService }, { type: undefined, decorators: [{
2802
+ }], ctorParameters: function () { return [{ type: XpsApiService }, { type: SettingsService }, { type: undefined, decorators: [{
2395
2803
  type: Inject,
2396
2804
  args: [checkStatusRequestFactoryToken]
2397
2805
  }] }, { type: undefined, decorators: [{
@@ -2522,34 +2930,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
2522
2930
  }]
2523
2931
  }] });
2524
2932
 
2525
- var ErrorTags;
2526
- (function (ErrorTags) {
2527
- ErrorTags["APP"] = "appError";
2528
- ErrorTags["HTTP"] = "httpError";
2529
- ErrorTags["JS"] = "jsError";
2530
- ErrorTags["WS"] = "webSocket";
2531
- ErrorTags["ENCRYPT"] = "encrypt";
2532
- ErrorTags["APPLEPAY"] = "applepay";
2533
- ErrorTags["HEADLESS_UI"] = "headlessUi";
2534
- ErrorTags["GOOGLEPAY"] = "googlepay";
2535
- ErrorTags["PAYTM"] = "paytm";
2536
- })(ErrorTags || (ErrorTags = {}));
2537
-
2538
- class TaggedError extends Error {
2539
- constructor(message, tags) {
2540
- super(message);
2541
- this.tags = [];
2542
- this.parentTag = ErrorTags.HEADLESS_UI;
2543
- this.tags = this.childTag
2544
- ? [this.parentTag, this.childTag]
2545
- : [this.parentTag];
2546
- if (tags) {
2547
- const newTags = tags.filter((t, i, arr) => !this.tags.includes(t) && arr.indexOf(t) == i);
2548
- this.tags = [...this.tags, ...newTags];
2549
- }
2550
- }
2551
- }
2552
-
2553
2933
  class WsError extends TaggedError {
2554
2934
  constructor(message, channelName, tags) {
2555
2935
  tags = tags ? [...tags, ErrorTags.WS] : [ErrorTags.WS];
@@ -3409,11 +3789,430 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
3409
3789
  }]
3410
3790
  }] });
3411
3791
 
3792
+ var ThreeDsStatusWebSocketTypes;
3793
+ (function (ThreeDsStatusWebSocketTypes) {
3794
+ ThreeDsStatusWebSocketTypes["status3DS_changed"] = "status3DS_changed";
3795
+ })(ThreeDsStatusWebSocketTypes || (ThreeDsStatusWebSocketTypes = {}));
3796
+
3797
+ var ThreeDsStatusTypes;
3798
+ (function (ThreeDsStatusTypes) {
3799
+ ThreeDsStatusTypes["completed"] = "completed";
3800
+ ThreeDsStatusTypes["challenge"] = "challenge";
3801
+ ThreeDsStatusTypes["collectDfp"] = "collect_dfp";
3802
+ })(ThreeDsStatusTypes || (ThreeDsStatusTypes = {}));
3803
+
3804
+ class XpsResponseError extends AppError {
3805
+ constructor(message) {
3806
+ super('XPS response failed' + (message ? `: "${message}".` : '.'));
3807
+ }
3808
+ }
3809
+
3810
+ class StatusThreeDsRequest {
3811
+ constructor(token, threeDsId) {
3812
+ this.access_token = token;
3813
+ this.threeDSTrXid = threeDsId;
3814
+ }
3815
+ }
3816
+
3817
+ const statusThreeDsRequestFactoryToken = new InjectionToken('StatusThreeDsRequest');
3818
+ const statusThreeDsRequestFactoryProvider = {
3819
+ provide: statusThreeDsRequestFactoryToken,
3820
+ useValue: (...args) => new StatusThreeDsRequest(...args),
3821
+ };
3822
+
3823
+ class StatusThreeDsResponse {
3824
+ constructor(params) {
3825
+ this.status = params.status;
3826
+ this.checkoutForm = params.checkoutForm;
3827
+ }
3828
+ }
3829
+
3830
+ const statusThreeDsResponseFactoryToken = new InjectionToken('StatusThreeDsResponse');
3831
+ const statusThreeDsResponseFactoryProvider = {
3832
+ provide: statusThreeDsResponseFactoryToken,
3833
+ useValue: (...args) => new StatusThreeDsResponse(...args),
3834
+ };
3835
+
3836
+ class StatusThreeDsService {
3837
+ get response$() {
3838
+ return this.response.asObservable();
3839
+ }
3840
+ constructor(secureApi, settingsService, requestFactory, responseFactory) {
3841
+ this.secureApi = secureApi;
3842
+ this.settingsService = settingsService;
3843
+ this.requestFactory = requestFactory;
3844
+ this.responseFactory = responseFactory;
3845
+ this.apiRoute = 'secure3d/check';
3846
+ this.response = new Subject();
3847
+ }
3848
+ request(data) {
3849
+ const token = this.settingsService.token;
3850
+ if (!token) {
3851
+ throw new TokenError();
3852
+ }
3853
+ const requestParams = this.requestFactory(token, data.threeDSTrXid);
3854
+ void lastValueFrom(this.secureApi
3855
+ .post(this.apiRoute, new URLSearchParams({ ...requestParams }), {
3856
+ headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
3857
+ responseType: 'json',
3858
+ })
3859
+ .pipe(map$1((response) => {
3860
+ const statusResponse = this.responseFactory({
3861
+ status: response.secure3d.status,
3862
+ checkoutForm: response.secure3d.checkout_form,
3863
+ });
3864
+ this.response.next(statusResponse);
3865
+ }))).catch((error) => {
3866
+ throw new XpsResponseError(error.message);
3867
+ });
3868
+ }
3869
+ }
3870
+ StatusThreeDsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: StatusThreeDsService, deps: [{ token: SecureApiClient }, { token: SettingsService }, { token: statusThreeDsRequestFactoryToken }, { token: statusThreeDsResponseFactoryToken }], target: i0.ɵɵFactoryTarget.Injectable });
3871
+ StatusThreeDsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: StatusThreeDsService, providedIn: 'root' });
3872
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: StatusThreeDsService, decorators: [{
3873
+ type: Injectable,
3874
+ args: [{
3875
+ providedIn: 'root',
3876
+ }]
3877
+ }], ctorParameters: function () { return [{ type: SecureApiClient }, { type: SettingsService }, { type: undefined, decorators: [{
3878
+ type: Inject,
3879
+ args: [statusThreeDsRequestFactoryToken]
3880
+ }] }, { type: undefined, decorators: [{
3881
+ type: Inject,
3882
+ args: [statusThreeDsResponseFactoryToken]
3883
+ }] }]; } });
3884
+
3885
+ class NotifyDfpStatusRequest {
3886
+ constructor(params) {
3887
+ this.access_token = params.token;
3888
+ this.threeDSTrXid = params.threeDsTrXid;
3889
+ this.secure3dCompind = params.isCompind ? 'Y' : 'N';
3890
+ }
3891
+ }
3892
+
3893
+ const notifyDfpStatusRequestFactoryToken = new InjectionToken('NotifyDfpStatusRequest');
3894
+ const notifyDfpStatusRequestFactoryProvider = {
3895
+ provide: notifyDfpStatusRequestFactoryToken,
3896
+ useValue: (...args) => new NotifyDfpStatusRequest(...args),
3897
+ };
3898
+
3899
+ class NotifyDfpStatusService {
3900
+ constructor(secureApi, settingsService, requestFactory) {
3901
+ this.secureApi = secureApi;
3902
+ this.settingsService = settingsService;
3903
+ this.requestFactory = requestFactory;
3904
+ this.apiRouteComplete = 'secure3d/notify';
3905
+ }
3906
+ /*
3907
+ * isCompind is a flag of dfp expired state
3908
+ */
3909
+ request(threeDsId, isCompind) {
3910
+ const token = this.settingsService.token;
3911
+ if (!token) {
3912
+ throw new TokenError();
3913
+ }
3914
+ const requestParams = this.requestFactory({
3915
+ token: token,
3916
+ threeDsTrXid: threeDsId,
3917
+ isCompind,
3918
+ });
3919
+ lastValueFrom(this.secureApi.post(this.apiRouteComplete, new URLSearchParams({ ...requestParams }), {
3920
+ headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
3921
+ responseType: 'json',
3922
+ })).catch((error) => {
3923
+ throw new XpsResponseError(error.message);
3924
+ });
3925
+ }
3926
+ }
3927
+ NotifyDfpStatusService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: NotifyDfpStatusService, deps: [{ token: SecureApiClient }, { token: SettingsService }, { token: notifyDfpStatusRequestFactoryToken }], target: i0.ɵɵFactoryTarget.Injectable });
3928
+ NotifyDfpStatusService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: NotifyDfpStatusService, providedIn: 'root' });
3929
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: NotifyDfpStatusService, decorators: [{
3930
+ type: Injectable,
3931
+ args: [{
3932
+ providedIn: 'root',
3933
+ }]
3934
+ }], ctorParameters: function () { return [{ type: SecureApiClient }, { type: SettingsService }, { type: undefined, decorators: [{
3935
+ type: Inject,
3936
+ args: [notifyDfpStatusRequestFactoryToken]
3937
+ }] }]; } });
3938
+
3939
+ class DfpCollectService {
3940
+ constructor(window, notifyDfpStatusService) {
3941
+ this.window = window;
3942
+ this.notifyDfpStatusService = notifyDfpStatusService;
3943
+ this.iframeName = 'iframeDFP';
3944
+ this.formName = 'formDFP';
3945
+ }
3946
+ collectDfpStatus(threeDsForm) {
3947
+ if (threeDsForm.waitCallback) {
3948
+ this.openIframeWithPostRequest(threeDsForm, false);
3949
+ }
3950
+ else {
3951
+ this.openIframeWithPostRequest(threeDsForm, true);
3952
+ }
3953
+ }
3954
+ /*
3955
+ * This method create invisible iframe with required params and after that it submit form in iframe
3956
+ * */
3957
+ openIframeWithPostRequest(threeDsForm, isNeedNotifyAfterLoad) {
3958
+ const iFrameElement = this.window.document.getElementById(this.iframeName);
3959
+ if (!iFrameElement) {
3960
+ this.createIframe(isNeedNotifyAfterLoad, threeDsForm.threeDSTrXid);
3961
+ this.postFormToIframe(threeDsForm.threeDSMethod, threeDsForm.threeDSMethodData);
3962
+ }
3963
+ }
3964
+ /*
3965
+ * isNeedNotifyAfterLoad is need to send notification of dft to server
3966
+ * */
3967
+ createIframe(isNeedNotifyAfterLoad, threeDsTrXid) {
3968
+ const attributes = {
3969
+ name: this.iframeName,
3970
+ id: this.iframeName,
3971
+ src: 'javascript:false',
3972
+ style: 'display:none',
3973
+ };
3974
+ const iFrame = this.window.document.createElement('iframe');
3975
+ this.setAttributes(iFrame, attributes);
3976
+ this.window.document.body.appendChild(iFrame);
3977
+ if (isNeedNotifyAfterLoad) {
3978
+ this.window.document.getElementById(this.iframeName).onload = () => {
3979
+ this.notifyDfpStatusService.request(threeDsTrXid, true);
3980
+ };
3981
+ }
3982
+ }
3983
+ /*
3984
+ * This method will submit form in our iframe. Form will be created, if it's don't exist
3985
+ * */
3986
+ postFormToIframe(url, threeDsMethod) {
3987
+ let form = this.window.document.getElementById(this.formName);
3988
+ if (!form) {
3989
+ form = this.createForm();
3990
+ this.window.document.body.appendChild(form);
3991
+ }
3992
+ form.setAttribute('action', url);
3993
+ form.setAttribute('target', this.iframeName);
3994
+ form.appendChild(this.createInput('threeDSMethodData', threeDsMethod));
3995
+ form.submit();
3996
+ }
3997
+ /*
3998
+ * This method will create invisible form with required params
3999
+ */
4000
+ createForm() {
4001
+ const form = this.window.document.createElement('form');
4002
+ const initAttributes = {
4003
+ name: this.formName,
4004
+ id: this.formName,
4005
+ style: 'display:none',
4006
+ method: 'POST',
4007
+ enctype: 'application/x-www-form-urlencoded',
4008
+ };
4009
+ this.setAttributes(form, initAttributes);
4010
+ return form;
4011
+ }
4012
+ createInput(name, value) {
4013
+ const input = this.window.document.createElement('input');
4014
+ input.type = 'hidden';
4015
+ input.name = name;
4016
+ input.value = value;
4017
+ return input;
4018
+ }
4019
+ /*
4020
+ * This method will set attributes to form/iframe
4021
+ * */
4022
+ setAttributes(element, attributes) {
4023
+ Object.keys(attributes).forEach((name) => {
4024
+ element.setAttribute(name, attributes[name]);
4025
+ });
4026
+ }
4027
+ }
4028
+ DfpCollectService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: DfpCollectService, deps: [{ token: windowToken }, { token: NotifyDfpStatusService }], target: i0.ɵɵFactoryTarget.Injectable });
4029
+ DfpCollectService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: DfpCollectService, providedIn: 'root' });
4030
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: DfpCollectService, decorators: [{
4031
+ type: Injectable,
4032
+ args: [{
4033
+ providedIn: 'root',
4034
+ }]
4035
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
4036
+ type: Inject,
4037
+ args: [windowToken]
4038
+ }] }, { type: NotifyDfpStatusService }]; } });
4039
+
4040
+ class ReinsuranceCheckService {
4041
+ constructor(window) {
4042
+ this.window = window;
4043
+ this.timers = {};
4044
+ }
4045
+ addTimer(timer) {
4046
+ if (!timer) {
4047
+ return;
4048
+ }
4049
+ this.removeTimer(timer.id);
4050
+ this.timers[timer.id] = timer;
4051
+ const timerInStorage = this.timers[timer.id];
4052
+ this.window.setTimeout(() => {
4053
+ timerInStorage.callback();
4054
+ this.timers[timer.id] = null;
4055
+ }, timerInStorage.timeoutMs);
4056
+ }
4057
+ removeTimer(id) {
4058
+ const timerInStorage = this.timers[id];
4059
+ if (!timerInStorage) {
4060
+ return;
4061
+ }
4062
+ this.window.clearTimeout(timerInStorage.timeoutRef);
4063
+ this.timers[id] = null;
4064
+ }
4065
+ }
4066
+ ReinsuranceCheckService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ReinsuranceCheckService, deps: [{ token: windowToken }], target: i0.ɵɵFactoryTarget.Injectable });
4067
+ ReinsuranceCheckService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ReinsuranceCheckService, providedIn: 'root' });
4068
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ReinsuranceCheckService, decorators: [{
4069
+ type: Injectable,
4070
+ args: [{
4071
+ providedIn: 'root',
4072
+ }]
4073
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
4074
+ type: Inject,
4075
+ args: [windowToken]
4076
+ }] }]; } });
4077
+
4078
+ class ThreeDs20Service {
4079
+ get statusUpdates$() {
4080
+ return this.statusUpdates.asObservable();
4081
+ }
4082
+ constructor(statusThreeDsService, notifyDfpStatusService, webSocketFactory, dfpCollectService, reinsuranceCheckService) {
4083
+ this.statusThreeDsService = statusThreeDsService;
4084
+ this.notifyDfpStatusService = notifyDfpStatusService;
4085
+ this.webSocketFactory = webSocketFactory;
4086
+ this.dfpCollectService = dfpCollectService;
4087
+ this.reinsuranceCheckService = reinsuranceCheckService;
4088
+ this.webSocketClient = null;
4089
+ this.statusUpdates = new Subject();
4090
+ this.statusRequestSubscription = null;
4091
+ this.notifyDfpTimerId = 'notify-dfp';
4092
+ this.notifyDfpTimeoutMs = 10000;
4093
+ this.statusThreeDsTimerId = 'status-three-ds';
4094
+ this.statusThreeDsTimeoutMs = 180000;
4095
+ }
4096
+ async checkThreeDs20(threeDsForm) {
4097
+ if (!threeDsForm) {
4098
+ return;
4099
+ }
4100
+ this.reinsuranceCheckService.addTimer({
4101
+ id: this.notifyDfpTimerId,
4102
+ timeoutMs: this.notifyDfpTimeoutMs,
4103
+ callback: () => {
4104
+ this.notifyDfpStatusService.request(threeDsForm.threeDSTrXid, false);
4105
+ },
4106
+ });
4107
+ this.webSocketClient = this.webSocketFactory.createWebSocketClient(threeDsForm.webSocketChannelUrl, threeDsForm.webSocketClientType);
4108
+ await this.webSocketClient.open(threeDsForm.webSocketChannelUrl, threeDsForm.webSocketClientType);
4109
+ this.webSocketSubscription?.unsubscribe();
4110
+ this.webSocketSubscription = this.webSocketClient.messages$.subscribe((message) => {
4111
+ if (message !== ThreeDsStatusWebSocketTypes.status3DS_changed) {
4112
+ return;
4113
+ }
4114
+ this.statusThreeDsService.request(threeDsForm);
4115
+ });
4116
+ this.webSocketReconnectionSubscription?.unsubscribe();
4117
+ this.webSocketReconnectionSubscription =
4118
+ this.webSocketClient.subscribeOnSuccessfulReconnection(() => {
4119
+ this.statusThreeDsService.request(threeDsForm);
4120
+ });
4121
+ this.handleThreeDsUpdates(threeDsForm);
4122
+ this.statusThreeDsService.request(threeDsForm);
4123
+ this.reinsuranceCheckService.addTimer({
4124
+ id: this.statusThreeDsTimerId,
4125
+ timeoutMs: this.statusThreeDsTimeoutMs,
4126
+ callback: () => {
4127
+ this.statusThreeDsService.request(threeDsForm);
4128
+ },
4129
+ });
4130
+ }
4131
+ handleThreeDsUpdates(threeDsForm) {
4132
+ this.statusRequestSubscription?.unsubscribe();
4133
+ this.statusRequestSubscription =
4134
+ this.statusThreeDsService.response$.subscribe((threeDsStatus) => {
4135
+ if (!threeDsStatus) {
4136
+ return;
4137
+ }
4138
+ if (threeDsStatus.status === ThreeDsStatusTypes.completed) {
4139
+ this.stopReinsuranceMethods();
4140
+ this.statusUpdates.next({
4141
+ type: 'complete',
4142
+ data: {
4143
+ statusUrl: threeDsForm.statusUrl,
4144
+ },
4145
+ });
4146
+ return;
4147
+ }
4148
+ if (threeDsStatus.status === ThreeDsStatusTypes.challenge &&
4149
+ threeDsStatus.checkoutForm) {
4150
+ this.stopReinsuranceMethods();
4151
+ this.statusUpdates.next({
4152
+ type: 'challenge',
4153
+ data: threeDsStatus.checkoutForm,
4154
+ });
4155
+ }
4156
+ if (threeDsStatus.status === ThreeDsStatusTypes.collectDfp) {
4157
+ this.dfpCollectService.collectDfpStatus(threeDsForm);
4158
+ }
4159
+ });
4160
+ }
4161
+ stopReinsuranceMethods() {
4162
+ this.reinsuranceCheckService.removeTimer(this.notifyDfpTimerId);
4163
+ this.reinsuranceCheckService.removeTimer(this.statusThreeDsTimerId);
4164
+ this.webSocketClient?.close();
4165
+ this.statusRequestSubscription?.unsubscribe();
4166
+ }
4167
+ }
4168
+ ThreeDs20Service.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ThreeDs20Service, deps: [{ token: StatusThreeDsService }, { token: NotifyDfpStatusService }, { token: WebSocketFactory }, { token: DfpCollectService }, { token: ReinsuranceCheckService }], target: i0.ɵɵFactoryTarget.Injectable });
4169
+ ThreeDs20Service.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ThreeDs20Service, providedIn: 'root' });
4170
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ThreeDs20Service, decorators: [{
4171
+ type: Injectable,
4172
+ args: [{
4173
+ providedIn: 'root',
4174
+ }]
4175
+ }], ctorParameters: function () { return [{ type: StatusThreeDsService }, { type: NotifyDfpStatusService }, { type: WebSocketFactory }, { type: DfpCollectService }, { type: ReinsuranceCheckService }]; } });
4176
+
4177
+ class ThreeDsService {
4178
+ constructor(threeDs20Service, nextActionService) {
4179
+ this.threeDs20Service = threeDs20Service;
4180
+ this.nextActionService = nextActionService;
4181
+ this.statusSubscription = null;
4182
+ }
4183
+ checkThreeDs(params) {
4184
+ /*
4185
+ At this moment we support only 3ds 2.0 version.
4186
+ 3ds 1.0 currently working by our redirect logic (Redirect NextAction).
4187
+ If in future we will get new version of 3ds, we should add 3ds determination logic to this service
4188
+ */
4189
+ void this.threeDs20Service.checkThreeDs20(params.parameters.threeDSForm);
4190
+ this.statusSubscription?.unsubscribe();
4191
+ this.statusSubscription = this.threeDs20Service.statusUpdates$.subscribe((statusUpdate) => {
4192
+ if (statusUpdate.type === 'complete') {
4193
+ return this.nextActionService.emitFlowUpdates(new CheckStatusAction(params));
4194
+ }
4195
+ this.nextActionService.emitFlowUpdates(new ThreeDsAction(statusUpdate));
4196
+ });
4197
+ }
4198
+ stopChecking() {
4199
+ this.statusSubscription?.unsubscribe();
4200
+ }
4201
+ }
4202
+ ThreeDsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ThreeDsService, deps: [{ token: ThreeDs20Service }, { token: NextActionService }], target: i0.ɵɵFactoryTarget.Injectable });
4203
+ ThreeDsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ThreeDsService, providedIn: 'root' });
4204
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ThreeDsService, decorators: [{
4205
+ type: Injectable,
4206
+ args: [{
4207
+ providedIn: 'root',
4208
+ }]
4209
+ }], ctorParameters: function () { return [{ type: ThreeDs20Service }, { type: NextActionService }]; } });
4210
+
3412
4211
  class PaymentService {
3413
4212
  get formFieldsStatus$() {
3414
4213
  return this.formFieldsStatusSubject.asObservable().pipe(filter$1(Boolean));
3415
4214
  }
3416
- constructor(initializeService, submitService, syncService, formService, statusService, financeDetailsService, creditCardStateService, nextActionService, controlConfigService) {
4215
+ constructor(initializeService, submitService, syncService, formService, statusService, financeDetailsService, creditCardStateService, nextActionService, controlConfigService, threeDsService) {
3417
4216
  this.initializeService = initializeService;
3418
4217
  this.submitService = submitService;
3419
4218
  this.syncService = syncService;
@@ -3423,6 +4222,7 @@ class PaymentService {
3423
4222
  this.creditCardStateService = creditCardStateService;
3424
4223
  this.nextActionService = nextActionService;
3425
4224
  this.controlConfigService = controlConfigService;
4225
+ this.threeDsService = threeDsService;
3426
4226
  this.form = null;
3427
4227
  this.data = null;
3428
4228
  this.financeDetails = null;
@@ -3458,6 +4258,13 @@ class PaymentService {
3458
4258
  const submitResponse = await this.submitService.request(this.fields, this.form);
3459
4259
  this.data = submitResponse;
3460
4260
  this.emitFinanceDetails(submitResponse.summary);
4261
+ // Handle 3ds flow
4262
+ if (submitResponse.currentCommand === XpsCommand.create) {
4263
+ this.runThreeDs();
4264
+ return;
4265
+ }
4266
+ this.fields = this.getFields();
4267
+ this.form = this.formService.createForm(this.fields);
3461
4268
  return this.nextActionService.getNextAction(submitResponse);
3462
4269
  }
3463
4270
  getFields() {
@@ -3474,7 +4281,10 @@ class PaymentService {
3474
4281
  return this.syncService.validate(field);
3475
4282
  }
3476
4283
  runThreeDs() {
3477
- throw new Error('Method not implemented.');
4284
+ if (!isSubmitResponse(this.data)) {
4285
+ throw new Error('Should submit form first');
4286
+ }
4287
+ this.threeDsService.checkThreeDs(this.data);
3478
4288
  }
3479
4289
  getFinanceDetails() {
3480
4290
  return this.financeDetails;
@@ -3525,6 +4335,7 @@ class PaymentService {
3525
4335
  this.fields = [];
3526
4336
  this.formDestroy$.next();
3527
4337
  this.destroy$.next();
4338
+ this.threeDsService.stopChecking();
3528
4339
  }
3529
4340
  emitFinanceDetails(summary) {
3530
4341
  this.financeDetailsService.emit(summary);
@@ -3572,14 +4383,14 @@ class PaymentService {
3572
4383
  .subscribe(() => this.emitFormFieldsStatus(form));
3573
4384
  }
3574
4385
  }
3575
- 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: StatusService }, { token: FinanceDetailsService }, { token: CreditCardStateService }, { token: NextActionService }, { token: ControlConfigService }], target: i0.ɵɵFactoryTarget.Injectable });
4386
+ 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: StatusService }, { token: FinanceDetailsService }, { token: CreditCardStateService }, { token: NextActionService }, { token: ControlConfigService }, { token: ThreeDsService }], target: i0.ɵɵFactoryTarget.Injectable });
3576
4387
  PaymentService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PaymentService, providedIn: 'root' });
3577
4388
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PaymentService, decorators: [{
3578
4389
  type: Injectable,
3579
4390
  args: [{
3580
4391
  providedIn: 'root',
3581
4392
  }]
3582
- }], ctorParameters: function () { return [{ type: InitializeService }, { type: SubmitService }, { type: SyncService }, { type: FormService }, { type: StatusService }, { type: FinanceDetailsService }, { type: CreditCardStateService }, { type: NextActionService }, { type: ControlConfigService }]; } });
4393
+ }], ctorParameters: function () { return [{ type: InitializeService }, { type: SubmitService }, { type: SyncService }, { type: FormService }, { type: StatusService }, { type: FinanceDetailsService }, { type: CreditCardStateService }, { type: NextActionService }, { type: ControlConfigService }, { type: ThreeDsService }]; } });
3583
4394
 
3584
4395
  class RefundPolicyService {
3585
4396
  constructor(settingsService) {
@@ -3708,7 +4519,7 @@ class CoreLibraryService {
3708
4519
  }
3709
4520
  async init(configuration) {
3710
4521
  await this.settingsService.init(configuration);
3711
- await this.deviceFingerPrintService.init();
4522
+ this.deviceFingerPrintService.init();
3712
4523
  }
3713
4524
  async getStatus(url) {
3714
4525
  return this.statusService.getStatusWithUrlSearchParams(url);
@@ -3842,6 +4653,15 @@ FormModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15
3842
4653
  ZipConverter,
3843
4654
  EmailConverter,
3844
4655
  CardNumberConverter,
4656
+ CardExpirationConverter,
4657
+ CvvConverter,
4658
+ CardholderNameConverter,
4659
+ CpfNumberConverter,
4660
+ CpfNameConverter,
4661
+ BirthDateConverter,
4662
+ StreetNumberConverter,
4663
+ TextConverter,
4664
+ PhoneConverter,
3845
4665
  { provide: convertersMapToken, useValue: convertersMap },
3846
4666
  ], imports: [ReactiveFormsModule, ValidatorsModule] });
3847
4667
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: FormModule, decorators: [{
@@ -3854,6 +4674,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
3854
4674
  ZipConverter,
3855
4675
  EmailConverter,
3856
4676
  CardNumberConverter,
4677
+ CardExpirationConverter,
4678
+ CvvConverter,
4679
+ CardholderNameConverter,
4680
+ CpfNumberConverter,
4681
+ CpfNameConverter,
4682
+ BirthDateConverter,
4683
+ StreetNumberConverter,
4684
+ TextConverter,
4685
+ PhoneConverter,
3857
4686
  { provide: convertersMapToken, useValue: convertersMap },
3858
4687
  ],
3859
4688
  }]
@@ -3883,6 +4712,9 @@ CoreLibraryModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", versi
3883
4712
  checkStatusRequestFactoryProvider,
3884
4713
  checkStatusResponseFactoryProvider,
3885
4714
  financeDetailsResponseFactoryProvider,
4715
+ statusThreeDsRequestFactoryProvider,
4716
+ statusThreeDsResponseFactoryProvider,
4717
+ notifyDfpStatusRequestFactoryProvider,
3886
4718
  {
3887
4719
  provide: nextActionsToken,
3888
4720
  useValue: nextActions,
@@ -3914,6 +4746,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
3914
4746
  checkStatusRequestFactoryProvider,
3915
4747
  checkStatusResponseFactoryProvider,
3916
4748
  financeDetailsResponseFactoryProvider,
4749
+ statusThreeDsRequestFactoryProvider,
4750
+ statusThreeDsResponseFactoryProvider,
4751
+ notifyDfpStatusRequestFactoryProvider,
3917
4752
  {
3918
4753
  provide: nextActionsToken,
3919
4754
  useValue: nextActions,