@xsolla/payment-client-core 0.0.14 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/esm2020/lib/core/payment/actions/next-action.interface.mjs +1 -1
  2. package/esm2020/lib/core/payment/actions/next-action.service.mjs +6 -2
  3. package/esm2020/lib/core/payment/actions/next-actions.mjs +8 -2
  4. package/esm2020/lib/core/payment/actions/show-errors/show-errors.action.class.mjs +9 -0
  5. package/esm2020/lib/core/payment/actions/show-errors/show-errors.action.token.mjs +13 -0
  6. package/esm2020/lib/core/payment/actions/show-errors/show-errors.action.type.mjs +2 -0
  7. package/esm2020/lib/core/payment/actions/show-field-state/show-field-state.action.class.mjs +11 -0
  8. package/esm2020/lib/core/payment/actions/show-field-state/show-field-state.action.token.mjs +13 -0
  9. package/esm2020/lib/core/payment/actions/show-field-state/show-field-state.action.type.mjs +2 -0
  10. package/esm2020/lib/core/payment/config/config.service.mjs +4 -1
  11. package/esm2020/lib/core/payment/initialize/initialize.service.mjs +13 -6
  12. package/esm2020/lib/core/payment/payment.service.mjs +25 -1
  13. package/esm2020/lib/core/payment/show-field-state.interface.mjs +2 -0
  14. package/esm2020/lib/core/payment/sync/sync.service.mjs +11 -5
  15. package/esm2020/lib/core/url/url.service.mjs +7 -1
  16. package/esm2020/lib/core-library.module.mjs +4 -2
  17. package/fesm2015/xsolla-payment-client-core.mjs +276 -180
  18. package/fesm2015/xsolla-payment-client-core.mjs.map +1 -1
  19. package/fesm2020/xsolla-payment-client-core.mjs +269 -177
  20. package/fesm2020/xsolla-payment-client-core.mjs.map +1 -1
  21. package/lib/core/payment/actions/next-action.interface.d.ts +3 -1
  22. package/lib/core/payment/actions/next-action.service.d.ts +1 -1
  23. package/lib/core/payment/actions/next-actions.d.ts +1 -0
  24. package/lib/core/payment/actions/show-errors/show-errors.action.class.d.ts +8 -0
  25. package/lib/core/payment/actions/show-errors/show-errors.action.token.d.ts +4 -0
  26. package/lib/core/payment/actions/show-errors/show-errors.action.type.d.ts +7 -0
  27. package/lib/core/payment/actions/show-field-state/show-field-state.action.class.d.ts +8 -0
  28. package/lib/core/payment/actions/show-field-state/show-field-state.action.token.d.ts +4 -0
  29. package/lib/core/payment/actions/show-field-state/show-field-state.action.type.d.ts +10 -0
  30. package/lib/core/payment/initialize/initialize.service.d.ts +3 -1
  31. package/lib/core/payment/payment.service.d.ts +4 -1
  32. package/lib/core/payment/show-field-state.interface.d.ts +7 -0
  33. package/lib/core/payment/sync/sync.service.d.ts +3 -1
  34. package/package.json +1 -1
  35. package/xsolla-payment-client-core-0.1.1.tgz +0 -0
  36. package/xsolla-payment-client-core-0.0.14.tgz +0 -0
@@ -1,6 +1,6 @@
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, BehaviorSubject, filter as filter$1, takeUntil, skip, throwError } from 'rxjs';
3
+ import { firstValueFrom, lastValueFrom, map, Subject, tap, 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
6
  import { UntypedFormGroup, Validators, UntypedFormControl, ReactiveFormsModule } from '@angular/forms';
@@ -407,6 +407,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
407
407
 
408
408
  class UrlService {
409
409
  addSearchParams(url, params = {}) {
410
+ if (!url) {
411
+ return '';
412
+ }
410
413
  const urlObject = new URL(url);
411
414
  for (const [key, value] of Object.entries(params)) {
412
415
  urlObject.searchParams.set(key, value);
@@ -414,6 +417,9 @@ class UrlService {
414
417
  return urlObject.toString();
415
418
  }
416
419
  getSearchParams(url) {
420
+ if (!url) {
421
+ return {};
422
+ }
417
423
  const urlObject = new URL(url);
418
424
  const searchParams = {};
419
425
  for (const [key, value] of urlObject.searchParams) {
@@ -437,6 +443,9 @@ class PaymentConfigService {
437
443
  this.settingsService = settingsService;
438
444
  }
439
445
  enrich(config) {
446
+ if (!config.returnUrl) {
447
+ throw new Error('URL is not provided in payment config');
448
+ }
440
449
  return {
441
450
  ...config,
442
451
  returnUrl: this.enrichReturnUrl(config.returnUrl),
@@ -564,6 +573,17 @@ const isSubmitResponse = (value) => {
564
573
  return value instanceof SubmitResponse;
565
574
  };
566
575
 
576
+ class ShowFieldStateAction {
577
+ constructor(control) {
578
+ this.type = 'show_field_state';
579
+ this.data = {
580
+ fieldName: control.fieldName,
581
+ fieldState: control.fieldState,
582
+ error: control.error,
583
+ };
584
+ }
585
+ }
586
+
567
587
  class InitializeResponse {
568
588
  constructor(response) {
569
589
  this.paymentForm = null;
@@ -613,12 +633,220 @@ const initializeResponseFactoryProvider = {
613
633
  useValue: (...args) => new InitializeResponse(...args),
614
634
  };
615
635
 
636
+ class ShowErrorsAction {
637
+ constructor(errors) {
638
+ this.type = 'show_errors';
639
+ this.data = {
640
+ errors,
641
+ };
642
+ }
643
+ }
644
+
645
+ class ShowFieldsAction {
646
+ constructor(submitResponse) {
647
+ this.type = 'show_fields';
648
+ this.data = {
649
+ fields: [],
650
+ errors: [],
651
+ messages: [],
652
+ order: {},
653
+ };
654
+ this.data.fields = submitResponse.fields.filter((field) => field?.isVisible === "1" /* XpsBoolean.true */);
655
+ this.data.errors = submitResponse.errors;
656
+ this.data.messages = submitResponse.messages;
657
+ this.data.order = submitResponse.summary;
658
+ }
659
+ }
660
+
661
+ const showFieldsActionFactoryToken = new InjectionToken('ShowFieldsAction');
662
+ const showFieldsActionFactoryProvider = {
663
+ provide: showFieldsActionFactoryToken,
664
+ useValue: {
665
+ factory: (...args) => new ShowFieldsAction(...args),
666
+ isSuitable: (response) => {
667
+ return response.currentCommand === XpsCommand.check;
668
+ },
669
+ },
670
+ };
671
+
672
+ class CheckStatusAction {
673
+ constructor(submitResponse) {
674
+ this.type = 'check_status';
675
+ const status = submitResponse.parameters.status;
676
+ this.data = {
677
+ invoice: status?.invoice,
678
+ signature: submitResponse.parameters.form.signature?.value,
679
+ locale: submitResponse.parameters.form.locale?.value,
680
+ testPs: submitResponse.parameters.form.testPs?.value,
681
+ testXsolla: submitResponse.parameters.form.testXsolla?.value,
682
+ testProject: submitResponse.parameters.form.testProject?.value,
683
+ userReturnStatus: submitResponse.parameters.form.userReturnStatus?.value,
684
+ };
685
+ }
686
+ }
687
+
688
+ const checkStatusActionFactoryToken = new InjectionToken('CheckStatusAction');
689
+ const checkStatusActionFactoryProvider = {
690
+ provide: checkStatusActionFactoryToken,
691
+ useValue: {
692
+ factory: (...args) => new CheckStatusAction(...args),
693
+ isSuitable: (response) => {
694
+ return response.currentCommand === XpsCommand.status;
695
+ },
696
+ },
697
+ };
698
+
699
+ class StatusUpdatedAction {
700
+ constructor(statusResponse) {
701
+ this.type = 'status_updated';
702
+ this.data = {
703
+ statusState: statusResponse.status.statusState,
704
+ invoice: statusResponse.status.invoice,
705
+ isSuccess: statusResponse.status.isSuccess,
706
+ isCanceled: statusResponse.status.isCanceled,
707
+ group: statusResponse.status.group,
708
+ };
709
+ }
710
+ }
711
+
712
+ const statusUpdatedActionFactoryToken = new InjectionToken('StatusUpdatedAction');
713
+ const statusUpdatedActionFactoryProvider = {
714
+ provide: statusUpdatedActionFactoryToken,
715
+ useValue: {
716
+ factory: (...args) => new StatusUpdatedAction(...args),
717
+ isSuitable: () => false,
718
+ },
719
+ };
720
+
721
+ class RedirectAction {
722
+ constructor(submitResponse) {
723
+ this.type = 'redirect';
724
+ this.data = {
725
+ fields: submitResponse.fields,
726
+ errors: submitResponse.errors,
727
+ messages: submitResponse.messages,
728
+ order: submitResponse.summary,
729
+ invoiceId: submitResponse.fixInvoice,
730
+ redirect: this.getRedirect(submitResponse),
731
+ };
732
+ }
733
+ getRedirect(submitResponse) {
734
+ return {
735
+ redirectUrl: submitResponse.parameters.checkout.action,
736
+ data: submitResponse.parameters.checkout.data,
737
+ };
738
+ }
739
+ }
740
+
741
+ const redirectActionFactoryToken = new InjectionToken('RedirectAction');
742
+ const redirectActionFactoryProvider = {
743
+ provide: redirectActionFactoryToken,
744
+ useValue: {
745
+ factory: (...args) => new RedirectAction(...args),
746
+ isSuitable: (response) => {
747
+ return (response.currentCommand === XpsCommand.account ||
748
+ (response.currentCommand === XpsCommand.checkout &&
749
+ Boolean(response.parameters.checkout)));
750
+ },
751
+ },
752
+ };
753
+
754
+ const showErrorsActionFactoryToken = new InjectionToken('ShowErrorsAction');
755
+ const showErrorsActionFactoryProvider = {
756
+ provide: showErrorsActionFactoryToken,
757
+ useValue: {
758
+ factory: (...args) => new ShowErrorsAction(...args),
759
+ isSuitable: (response) => {
760
+ return Boolean(response.errors?.length);
761
+ },
762
+ },
763
+ };
764
+
765
+ const showFieldStateActionFactoryToken = new InjectionToken('ShowFieldStateAction');
766
+ const showFieldStateActionFactoryProvider = {
767
+ provide: showFieldStateActionFactoryToken,
768
+ useValue: {
769
+ factory: (...args) => new ShowFieldStateAction(...args),
770
+ isSuitable: () => {
771
+ return true;
772
+ },
773
+ },
774
+ };
775
+
776
+ const nextActionsToken = new InjectionToken('Action');
777
+ const nextActions = [
778
+ showFieldsActionFactoryProvider,
779
+ checkStatusActionFactoryProvider,
780
+ redirectActionFactoryProvider,
781
+ ];
782
+ const flowUpdateNextActions = [
783
+ statusUpdatedActionFactoryProvider,
784
+ showErrorsActionFactoryProvider,
785
+ showFieldStateActionFactoryProvider,
786
+ ];
787
+
788
+ class NextActionService {
789
+ get flowUpdates$() {
790
+ return this.flowUpdatesSubject.asObservable();
791
+ }
792
+ constructor(nextActionTokens, injector) {
793
+ this.nextActionTokens = nextActionTokens;
794
+ this.injector = injector;
795
+ this.flowUpdatesSubject = new Subject();
796
+ this.nextActionsList = [];
797
+ this.fillNextActionsList();
798
+ }
799
+ getNextAction(submitResponse) {
800
+ if (submitResponse.errors?.length) {
801
+ this.emitFlowUpdates(new ShowErrorsAction(submitResponse.errors));
802
+ }
803
+ if (!submitResponse.currentCommand) {
804
+ return null;
805
+ }
806
+ const nextActionFactory = this.findNextAction(submitResponse);
807
+ if (nextActionFactory) {
808
+ return nextActionFactory(submitResponse);
809
+ }
810
+ throw new Error('Next action is undefined.');
811
+ }
812
+ emitFlowUpdates(action) {
813
+ this.flowUpdatesSubject.next(action);
814
+ }
815
+ fillNextActionsList() {
816
+ this.nextActionTokens.forEach((nextAction) => {
817
+ const item = this.injector.get(nextAction.provide);
818
+ this.nextActionsList.push(item);
819
+ });
820
+ }
821
+ findNextAction(submitResponse) {
822
+ const actionType = this.nextActionsList.find((nextAction) => {
823
+ return nextAction.isSuitable(submitResponse);
824
+ });
825
+ if (!actionType) {
826
+ return;
827
+ }
828
+ return actionType.factory;
829
+ }
830
+ }
831
+ NextActionService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: NextActionService, deps: [{ token: nextActionsToken }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
832
+ NextActionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: NextActionService, providedIn: 'root' });
833
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: NextActionService, decorators: [{
834
+ type: Injectable,
835
+ args: [{
836
+ providedIn: 'root',
837
+ }]
838
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
839
+ type: Inject,
840
+ args: [nextActionsToken]
841
+ }] }, { type: i0.Injector }]; } });
842
+
616
843
  class InitializeService {
617
- constructor(responseFactory, secureApi, settingsService, countryService) {
844
+ constructor(responseFactory, secureApi, settingsService, countryService, nextActionService) {
618
845
  this.responseFactory = responseFactory;
619
846
  this.secureApi = secureApi;
620
847
  this.settingsService = settingsService;
621
848
  this.countryService = countryService;
849
+ this.nextActionService = nextActionService;
622
850
  this.apiRoute = 'directpayment';
623
851
  // TODO PAYMENTS-15743: replace with new refer id for headless core
624
852
  this.ps4ReferId = '22';
@@ -636,12 +864,16 @@ class InitializeService {
636
864
  headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
637
865
  responseType: 'json',
638
866
  })
639
- .pipe(map((response) => this.responseFactory(response)))).catch((error) => {
867
+ .pipe(map((response) => this.responseFactory(response)), tap((response) => {
868
+ if (response.paymentForm?.errors?.length) {
869
+ this.nextActionService.emitFlowUpdates(new ShowErrorsAction(response.paymentForm.errors));
870
+ }
871
+ }))).catch((error) => {
640
872
  throw new ResponseError(error.message);
641
873
  });
642
874
  }
643
875
  }
644
- InitializeService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, deps: [{ token: initializeResponseFactoryToken }, { token: SecureApiClient }, { token: SettingsService }, { token: CountryService }], target: i0.ɵɵFactoryTarget.Injectable });
876
+ 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 });
645
877
  InitializeService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, providedIn: 'root' });
646
878
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, decorators: [{
647
879
  type: Injectable,
@@ -651,7 +883,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
651
883
  }], ctorParameters: function () { return [{ type: undefined, decorators: [{
652
884
  type: Inject,
653
885
  args: [initializeResponseFactoryToken]
654
- }] }, { type: SecureApiClient }, { type: SettingsService }, { type: CountryService }]; } });
886
+ }] }, { type: SecureApiClient }, { type: SettingsService }, { type: CountryService }, { type: NextActionService }]; } });
655
887
 
656
888
  class XpsApiPartRequest {
657
889
  addXpsParameters(parameters) {
@@ -997,11 +1229,12 @@ const syncResponseFactoryProvider = {
997
1229
  };
998
1230
 
999
1231
  class SyncService extends EmitDataService {
1000
- constructor(requestFactory, responseFactory, secureApi, settingsService) {
1232
+ constructor(requestFactory, responseFactory, secureApi, nextActionService, settingsService) {
1001
1233
  super();
1002
1234
  this.requestFactory = requestFactory;
1003
1235
  this.responseFactory = responseFactory;
1004
1236
  this.secureApi = secureApi;
1237
+ this.nextActionService = nextActionService;
1005
1238
  this.settingsService = settingsService;
1006
1239
  this.apiRoute = 'directpayment';
1007
1240
  this.prevFieldSyncStates = {};
@@ -1061,6 +1294,9 @@ class SyncService extends EmitDataService {
1061
1294
  headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
1062
1295
  responseType: 'json',
1063
1296
  })).then((response) => {
1297
+ if (response.errors?.length) {
1298
+ this.nextActionService.emitFlowUpdates(new ShowErrorsAction(response.errors));
1299
+ }
1064
1300
  this.emit(response);
1065
1301
  return this.responseFactory(field, response);
1066
1302
  });
@@ -1077,7 +1313,7 @@ class SyncService extends EmitDataService {
1077
1313
  this.prevFieldSyncStates[field.name] = { value, result };
1078
1314
  }
1079
1315
  }
1080
- SyncService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SyncService, deps: [{ token: syncRequestFactoryToken }, { token: syncResponseFactoryToken }, { token: SecureApiClient }, { token: SettingsService }], target: i0.ɵɵFactoryTarget.Injectable });
1316
+ 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 });
1081
1317
  SyncService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SyncService, providedIn: 'root' });
1082
1318
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SyncService, decorators: [{
1083
1319
  type: Injectable,
@@ -1090,7 +1326,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
1090
1326
  }] }, { type: undefined, decorators: [{
1091
1327
  type: Inject,
1092
1328
  args: [syncResponseFactoryToken]
1093
- }] }, { type: SecureApiClient }, { type: SettingsService }]; } });
1329
+ }] }, { type: SecureApiClient }, { type: NextActionService }, { type: SettingsService }]; } });
1094
1330
 
1095
1331
  class ControlConfig {
1096
1332
  constructor() {
@@ -1373,19 +1609,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
1373
1609
  type: Injectable
1374
1610
  }], ctorParameters: function () { return [{ type: ControlConfigService }]; } });
1375
1611
 
1376
- class StatusUpdatedAction {
1377
- constructor(statusResponse) {
1378
- this.type = 'status_updated';
1379
- this.data = {
1380
- statusState: statusResponse.status.statusState,
1381
- invoice: statusResponse.status.invoice,
1382
- isSuccess: statusResponse.status.isSuccess,
1383
- isCanceled: statusResponse.status.isCanceled,
1384
- group: statusResponse.status.group,
1385
- };
1386
- }
1387
- }
1388
-
1389
1612
  var StatusSearchParam;
1390
1613
  (function (StatusSearchParam) {
1391
1614
  StatusSearchParam["token"] = "token";
@@ -2439,162 +2662,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
2439
2662
  }]
2440
2663
  }], ctorParameters: function () { return [{ type: StatusRequestService }, { type: CheckStatusService }, { type: WebsocketStatusService }]; } });
2441
2664
 
2442
- class ShowFieldsAction {
2443
- constructor(submitResponse) {
2444
- this.type = 'show_fields';
2445
- this.data = {
2446
- fields: [],
2447
- errors: [],
2448
- messages: [],
2449
- order: {},
2450
- };
2451
- this.data.fields = submitResponse.fields.filter((field) => field?.isVisible === "1" /* XpsBoolean.true */);
2452
- this.data.errors = submitResponse.errors;
2453
- this.data.messages = submitResponse.messages;
2454
- this.data.order = submitResponse.summary;
2455
- }
2456
- }
2457
-
2458
- const showFieldsActionFactoryToken = new InjectionToken('ShowFieldsAction');
2459
- const showFieldsActionFactoryProvider = {
2460
- provide: showFieldsActionFactoryToken,
2461
- useValue: {
2462
- factory: (...args) => new ShowFieldsAction(...args),
2463
- isSuitable: (response) => {
2464
- return response.currentCommand === XpsCommand.check;
2465
- },
2466
- },
2467
- };
2468
-
2469
- class CheckStatusAction {
2470
- constructor(submitResponse) {
2471
- this.type = 'check_status';
2472
- const status = submitResponse.parameters.status;
2473
- this.data = {
2474
- invoice: status?.invoice,
2475
- signature: submitResponse.parameters.form.signature?.value,
2476
- locale: submitResponse.parameters.form.locale?.value,
2477
- testPs: submitResponse.parameters.form.testPs?.value,
2478
- testXsolla: submitResponse.parameters.form.testXsolla?.value,
2479
- testProject: submitResponse.parameters.form.testProject?.value,
2480
- userReturnStatus: submitResponse.parameters.form.userReturnStatus?.value,
2481
- };
2482
- }
2483
- }
2484
-
2485
- const checkStatusActionFactoryToken = new InjectionToken('CheckStatusAction');
2486
- const checkStatusActionFactoryProvider = {
2487
- provide: checkStatusActionFactoryToken,
2488
- useValue: {
2489
- factory: (...args) => new CheckStatusAction(...args),
2490
- isSuitable: (response) => {
2491
- return response.currentCommand === XpsCommand.status;
2492
- },
2493
- },
2494
- };
2495
-
2496
- const statusUpdatedActionFactoryToken = new InjectionToken('StatusUpdatedAction');
2497
- const statusUpdatedActionFactoryProvider = {
2498
- provide: statusUpdatedActionFactoryToken,
2499
- useValue: {
2500
- factory: (...args) => new StatusUpdatedAction(...args),
2501
- isSuitable: () => false,
2502
- },
2503
- };
2504
-
2505
- class RedirectAction {
2506
- constructor(submitResponse) {
2507
- this.type = 'redirect';
2508
- this.data = {
2509
- fields: submitResponse.fields,
2510
- errors: submitResponse.errors,
2511
- messages: submitResponse.messages,
2512
- order: submitResponse.summary,
2513
- invoiceId: submitResponse.fixInvoice,
2514
- redirect: this.getRedirect(submitResponse),
2515
- };
2516
- }
2517
- getRedirect(submitResponse) {
2518
- return {
2519
- redirectUrl: submitResponse.parameters.checkout.action,
2520
- data: submitResponse.parameters.checkout.data,
2521
- };
2522
- }
2523
- }
2524
-
2525
- const redirectActionFactoryToken = new InjectionToken('RedirectAction');
2526
- const redirectActionFactoryProvider = {
2527
- provide: redirectActionFactoryToken,
2528
- useValue: {
2529
- factory: (...args) => new RedirectAction(...args),
2530
- isSuitable: (response) => {
2531
- return (response.currentCommand === XpsCommand.account ||
2532
- (response.currentCommand === XpsCommand.checkout &&
2533
- Boolean(response.parameters.checkout)));
2534
- },
2535
- },
2536
- };
2537
-
2538
- const nextActionsToken = new InjectionToken('Action');
2539
- const nextActions = [
2540
- showFieldsActionFactoryProvider,
2541
- checkStatusActionFactoryProvider,
2542
- statusUpdatedActionFactoryProvider,
2543
- redirectActionFactoryProvider,
2544
- ];
2545
-
2546
- class NextActionService {
2547
- get flowUpdates$() {
2548
- return this.flowUpdatesSubject.asObservable();
2549
- }
2550
- constructor(nextActionTokens, injector) {
2551
- this.nextActionTokens = nextActionTokens;
2552
- this.injector = injector;
2553
- this.flowUpdatesSubject = new Subject();
2554
- this.nextActionsList = [];
2555
- this.fillNextActionsList();
2556
- }
2557
- getNextAction(submitResponse) {
2558
- if (!submitResponse.currentCommand) {
2559
- return null;
2560
- }
2561
- const nextActionFactory = this.findNextAction(submitResponse);
2562
- if (nextActionFactory) {
2563
- return nextActionFactory(submitResponse);
2564
- }
2565
- throw new Error('Next action is undefined.');
2566
- }
2567
- emitFlowUpdates(action) {
2568
- this.flowUpdatesSubject.next(action);
2569
- }
2570
- fillNextActionsList() {
2571
- this.nextActionTokens.forEach((nextAction) => {
2572
- const item = this.injector.get(nextAction.provide);
2573
- this.nextActionsList.push(item);
2574
- });
2575
- }
2576
- findNextAction(submitResponse) {
2577
- const actionType = this.nextActionsList.find((nextAction) => {
2578
- return nextAction.isSuitable(submitResponse);
2579
- });
2580
- if (!actionType) {
2581
- return;
2582
- }
2583
- return actionType.factory;
2584
- }
2585
- }
2586
- NextActionService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: NextActionService, deps: [{ token: nextActionsToken }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
2587
- NextActionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: NextActionService, providedIn: 'root' });
2588
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: NextActionService, decorators: [{
2589
- type: Injectable,
2590
- args: [{
2591
- providedIn: 'root',
2592
- }]
2593
- }], ctorParameters: function () { return [{ type: undefined, decorators: [{
2594
- type: Inject,
2595
- args: [nextActionsToken]
2596
- }] }, { type: i0.Injector }]; } });
2597
-
2598
2665
  class StatusService {
2599
2666
  constructor(urlService, statusRequestService, listenStatusService, nextActionService) {
2600
2667
  this.urlService = urlService;
@@ -2948,14 +3015,17 @@ class PaymentService {
2948
3015
  this.financeDetails = null;
2949
3016
  this.fields = [];
2950
3017
  this.destroy$ = new Subject();
3018
+ this.formDestroy$ = new Subject();
2951
3019
  }
2952
3020
  async initialize(config) {
2953
3021
  this.destroy$ = new Subject();
3022
+ this.formDestroy$ = new Subject();
2954
3023
  this.listenFinanceDetails();
2955
3024
  this.config = config;
2956
3025
  this.data = await this.initializeService.request(config);
2957
3026
  this.fields = this.getFields();
2958
3027
  this.form = this.formService.createForm(this.fields);
3028
+ this.listenSyncValidationErrors(this.form);
2959
3029
  this.emitFinanceDetails(this.data.paymentForm?.summary);
2960
3030
  this.setupSyncService(this.form, this.fields);
2961
3031
  return this.fields.filter((field) => field?.isVisible === "1" /* XpsBoolean.true */);
@@ -3013,6 +3083,7 @@ class PaymentService {
3013
3083
  this.financeDetails = null;
3014
3084
  this.form = null;
3015
3085
  this.fields = [];
3086
+ this.formDestroy$.next();
3016
3087
  this.destroy$.next();
3017
3088
  }
3018
3089
  emitFinanceDetails(summary) {
@@ -3029,6 +3100,25 @@ class PaymentService {
3029
3100
  .pipe(takeUntil(this.destroy$))
3030
3101
  .subscribe((financeDetails) => (this.financeDetails = financeDetails));
3031
3102
  }
3103
+ listenSyncValidationErrors(form) {
3104
+ Object.keys(form.controls).forEach((key) => {
3105
+ const control = form.get(key);
3106
+ if (control) {
3107
+ control.statusChanges
3108
+ .pipe(takeUntil(this.formDestroy$))
3109
+ .subscribe((status) => {
3110
+ const controlError = control.errors?.['rewritableError'] ??
3111
+ null;
3112
+ const controlObject = {
3113
+ fieldName: key,
3114
+ fieldState: status,
3115
+ error: controlError,
3116
+ };
3117
+ this.nextActionService.emitFlowUpdates(new ShowFieldStateAction(controlObject));
3118
+ });
3119
+ }
3120
+ });
3121
+ }
3032
3122
  }
3033
3123
  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: NextActionService }, { token: ControlConfigService }], target: i0.ɵɵFactoryTarget.Injectable });
3034
3124
  PaymentService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PaymentService, providedIn: 'root' });
@@ -3316,6 +3406,7 @@ CoreLibraryModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", versi
3316
3406
  useValue: nextActions,
3317
3407
  },
3318
3408
  ...nextActions,
3409
+ ...flowUpdateNextActions,
3319
3410
  ], imports: [HttpClientModule, FormModule] });
3320
3411
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryModule, decorators: [{
3321
3412
  type: NgModule,
@@ -3346,6 +3437,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
3346
3437
  useValue: nextActions,
3347
3438
  },
3348
3439
  ...nextActions,
3440
+ ...flowUpdateNextActions,
3349
3441
  ],
3350
3442
  }]
3351
3443
  }] });