@xsolla/payment-client-core 0.0.13 → 0.1.0

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 (50) 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 +6 -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/config/config.service.mjs +33 -0
  8. package/esm2020/lib/core/payment/extended-xps-error.mjs +2 -0
  9. package/esm2020/lib/core/payment/initialize/initialize.service.mjs +13 -6
  10. package/esm2020/lib/core/payment/payment.service.mjs +30 -5
  11. package/esm2020/lib/core/payment/status/status-request/request/status-request.class.mjs +2 -2
  12. package/esm2020/lib/core/payment/status/status-request/required-status-search-params.const.mjs +9 -0
  13. package/esm2020/lib/core/payment/status/status-request/status-request-params.interface.mjs +1 -1
  14. package/esm2020/lib/core/payment/status/status-request/status-search-param.enum.mjs +13 -0
  15. package/esm2020/lib/core/payment/status/status-request/status-search-params.map.mjs +72 -0
  16. package/esm2020/lib/core/payment/status/status.service.mjs +30 -7
  17. package/esm2020/lib/core/payment/sync/sync.service.mjs +11 -5
  18. package/esm2020/lib/core/url/search-params.interface.mjs +2 -0
  19. package/esm2020/lib/core/url/url.service.mjs +34 -0
  20. package/esm2020/lib/core-library.module.mjs +4 -2
  21. package/esm2020/lib/core-library.service.mjs +18 -10
  22. package/fesm2015/xsolla-payment-client-core.mjs +438 -188
  23. package/fesm2015/xsolla-payment-client-core.mjs.map +1 -1
  24. package/fesm2020/xsolla-payment-client-core.mjs +428 -188
  25. package/fesm2020/xsolla-payment-client-core.mjs.map +1 -1
  26. package/lib/core/payment/actions/next-action.interface.d.ts +2 -1
  27. package/lib/core/payment/actions/next-action.service.d.ts +1 -1
  28. package/lib/core/payment/actions/next-actions.d.ts +1 -0
  29. package/lib/core/payment/actions/show-errors/show-errors.action.class.d.ts +8 -0
  30. package/lib/core/payment/actions/show-errors/show-errors.action.token.d.ts +4 -0
  31. package/lib/core/payment/actions/show-errors/show-errors.action.type.d.ts +7 -0
  32. package/lib/core/payment/config/config.service.d.ts +13 -0
  33. package/lib/core/payment/extended-xps-error.d.ts +4 -0
  34. package/lib/core/payment/initialize/initialize.service.d.ts +3 -1
  35. package/lib/core/payment/payment.service.d.ts +3 -1
  36. package/lib/core/payment/status/status-request/request/status-request.class.d.ts +1 -3
  37. package/lib/core/payment/status/status-request/required-status-search-params.const.d.ts +2 -0
  38. package/lib/core/payment/status/status-request/status-request-params.interface.d.ts +1 -0
  39. package/lib/core/payment/status/status-request/status-search-param.enum.d.ts +11 -0
  40. package/lib/core/payment/status/status-request/status-search-params.map.d.ts +9 -0
  41. package/lib/core/payment/status/status.service.d.ts +5 -1
  42. package/lib/core/payment/sync/sync.service.d.ts +3 -1
  43. package/lib/core/url/search-params.interface.d.ts +3 -0
  44. package/lib/core/url/url.service.d.ts +8 -0
  45. package/lib/core-library.service.d.ts +7 -1
  46. package/package.json +1 -1
  47. package/xsolla-payment-client-core-0.1.0.tgz +0 -0
  48. package/esm2020/lib/core/payment/status/status-params.interface.mjs +0 -2
  49. package/lib/core/payment/status/status-params.interface.d.ts +0 -9
  50. package/xsolla-payment-client-core-0.0.13.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';
@@ -405,6 +405,67 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
405
405
  args: [userBalanceResponseFactoryToken]
406
406
  }] }, { type: SettingsService }, { type: SecureApiClient }]; } });
407
407
 
408
+ class UrlService {
409
+ addSearchParams(url, params = {}) {
410
+ if (!url) {
411
+ return '';
412
+ }
413
+ const urlObject = new URL(url);
414
+ for (const [key, value] of Object.entries(params)) {
415
+ urlObject.searchParams.set(key, value);
416
+ }
417
+ return urlObject.toString();
418
+ }
419
+ getSearchParams(url) {
420
+ if (!url) {
421
+ return {};
422
+ }
423
+ const urlObject = new URL(url);
424
+ const searchParams = {};
425
+ for (const [key, value] of urlObject.searchParams) {
426
+ searchParams[key] = value;
427
+ }
428
+ return searchParams;
429
+ }
430
+ }
431
+ UrlService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: UrlService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
432
+ UrlService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: UrlService, providedIn: 'root' });
433
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: UrlService, decorators: [{
434
+ type: Injectable,
435
+ args: [{
436
+ providedIn: 'root',
437
+ }]
438
+ }] });
439
+
440
+ class PaymentConfigService {
441
+ constructor(urlService, settingsService) {
442
+ this.urlService = urlService;
443
+ this.settingsService = settingsService;
444
+ }
445
+ enrich(config) {
446
+ if (!config.returnUrl) {
447
+ throw new Error('URL is not provided in payment config');
448
+ }
449
+ return {
450
+ ...config,
451
+ returnUrl: this.enrichReturnUrl(config.returnUrl),
452
+ };
453
+ }
454
+ enrichReturnUrl(returnUrl) {
455
+ return this.urlService.addSearchParams(returnUrl, {
456
+ token: this.settingsService.token,
457
+ });
458
+ }
459
+ }
460
+ PaymentConfigService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PaymentConfigService, deps: [{ token: UrlService }, { token: SettingsService }], target: i0.ɵɵFactoryTarget.Injectable });
461
+ PaymentConfigService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PaymentConfigService, providedIn: 'root' });
462
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PaymentConfigService, decorators: [{
463
+ type: Injectable,
464
+ args: [{
465
+ providedIn: 'root',
466
+ }]
467
+ }], ctorParameters: function () { return [{ type: UrlService }, { type: SettingsService }]; } });
468
+
408
469
  var XpsCommand;
409
470
  (function (XpsCommand) {
410
471
  XpsCommand["form"] = "form";
@@ -512,6 +573,15 @@ const isSubmitResponse = (value) => {
512
573
  return value instanceof SubmitResponse;
513
574
  };
514
575
 
576
+ class ShowErrorsAction {
577
+ constructor(errors) {
578
+ this.type = 'show_errors';
579
+ this.data = {
580
+ errors,
581
+ };
582
+ }
583
+ }
584
+
515
585
  class InitializeResponse {
516
586
  constructor(response) {
517
587
  this.paymentForm = null;
@@ -561,12 +631,199 @@ const initializeResponseFactoryProvider = {
561
631
  useValue: (...args) => new InitializeResponse(...args),
562
632
  };
563
633
 
634
+ class ShowFieldsAction {
635
+ constructor(submitResponse) {
636
+ this.type = 'show_fields';
637
+ this.data = {
638
+ fields: [],
639
+ errors: [],
640
+ messages: [],
641
+ order: {},
642
+ };
643
+ this.data.fields = submitResponse.fields.filter((field) => field?.isVisible === "1" /* XpsBoolean.true */);
644
+ this.data.errors = submitResponse.errors;
645
+ this.data.messages = submitResponse.messages;
646
+ this.data.order = submitResponse.summary;
647
+ }
648
+ }
649
+
650
+ const showFieldsActionFactoryToken = new InjectionToken('ShowFieldsAction');
651
+ const showFieldsActionFactoryProvider = {
652
+ provide: showFieldsActionFactoryToken,
653
+ useValue: {
654
+ factory: (...args) => new ShowFieldsAction(...args),
655
+ isSuitable: (response) => {
656
+ return response.currentCommand === XpsCommand.check;
657
+ },
658
+ },
659
+ };
660
+
661
+ class CheckStatusAction {
662
+ constructor(submitResponse) {
663
+ this.type = 'check_status';
664
+ const status = submitResponse.parameters.status;
665
+ this.data = {
666
+ invoice: status?.invoice,
667
+ signature: submitResponse.parameters.form.signature?.value,
668
+ locale: submitResponse.parameters.form.locale?.value,
669
+ testPs: submitResponse.parameters.form.testPs?.value,
670
+ testXsolla: submitResponse.parameters.form.testXsolla?.value,
671
+ testProject: submitResponse.parameters.form.testProject?.value,
672
+ userReturnStatus: submitResponse.parameters.form.userReturnStatus?.value,
673
+ };
674
+ }
675
+ }
676
+
677
+ const checkStatusActionFactoryToken = new InjectionToken('CheckStatusAction');
678
+ const checkStatusActionFactoryProvider = {
679
+ provide: checkStatusActionFactoryToken,
680
+ useValue: {
681
+ factory: (...args) => new CheckStatusAction(...args),
682
+ isSuitable: (response) => {
683
+ return response.currentCommand === XpsCommand.status;
684
+ },
685
+ },
686
+ };
687
+
688
+ class StatusUpdatedAction {
689
+ constructor(statusResponse) {
690
+ this.type = 'status_updated';
691
+ this.data = {
692
+ statusState: statusResponse.status.statusState,
693
+ invoice: statusResponse.status.invoice,
694
+ isSuccess: statusResponse.status.isSuccess,
695
+ isCanceled: statusResponse.status.isCanceled,
696
+ group: statusResponse.status.group,
697
+ };
698
+ }
699
+ }
700
+
701
+ const statusUpdatedActionFactoryToken = new InjectionToken('StatusUpdatedAction');
702
+ const statusUpdatedActionFactoryProvider = {
703
+ provide: statusUpdatedActionFactoryToken,
704
+ useValue: {
705
+ factory: (...args) => new StatusUpdatedAction(...args),
706
+ isSuitable: () => false,
707
+ },
708
+ };
709
+
710
+ class RedirectAction {
711
+ constructor(submitResponse) {
712
+ this.type = 'redirect';
713
+ this.data = {
714
+ fields: submitResponse.fields,
715
+ errors: submitResponse.errors,
716
+ messages: submitResponse.messages,
717
+ order: submitResponse.summary,
718
+ invoiceId: submitResponse.fixInvoice,
719
+ redirect: this.getRedirect(submitResponse),
720
+ };
721
+ }
722
+ getRedirect(submitResponse) {
723
+ return {
724
+ redirectUrl: submitResponse.parameters.checkout.action,
725
+ data: submitResponse.parameters.checkout.data,
726
+ };
727
+ }
728
+ }
729
+
730
+ const redirectActionFactoryToken = new InjectionToken('RedirectAction');
731
+ const redirectActionFactoryProvider = {
732
+ provide: redirectActionFactoryToken,
733
+ useValue: {
734
+ factory: (...args) => new RedirectAction(...args),
735
+ isSuitable: (response) => {
736
+ return (response.currentCommand === XpsCommand.account ||
737
+ (response.currentCommand === XpsCommand.checkout &&
738
+ Boolean(response.parameters.checkout)));
739
+ },
740
+ },
741
+ };
742
+
743
+ const showErrorsActionFactoryToken = new InjectionToken('ShowErrorsAction');
744
+ const showErrorsActionFactoryProvider = {
745
+ provide: showErrorsActionFactoryToken,
746
+ useValue: {
747
+ factory: (...args) => new ShowErrorsAction(...args),
748
+ isSuitable: (response) => {
749
+ return Boolean(response.errors?.length);
750
+ },
751
+ },
752
+ };
753
+
754
+ const nextActionsToken = new InjectionToken('Action');
755
+ const nextActions = [
756
+ showFieldsActionFactoryProvider,
757
+ checkStatusActionFactoryProvider,
758
+ redirectActionFactoryProvider,
759
+ ];
760
+ const flowUpdateNextActions = [
761
+ statusUpdatedActionFactoryProvider,
762
+ showErrorsActionFactoryProvider,
763
+ ];
764
+
765
+ class NextActionService {
766
+ get flowUpdates$() {
767
+ return this.flowUpdatesSubject.asObservable();
768
+ }
769
+ constructor(nextActionTokens, injector) {
770
+ this.nextActionTokens = nextActionTokens;
771
+ this.injector = injector;
772
+ this.flowUpdatesSubject = new Subject();
773
+ this.nextActionsList = [];
774
+ this.fillNextActionsList();
775
+ }
776
+ getNextAction(submitResponse) {
777
+ if (submitResponse.errors?.length) {
778
+ this.emitFlowUpdates(new ShowErrorsAction(submitResponse.errors));
779
+ }
780
+ if (!submitResponse.currentCommand) {
781
+ return null;
782
+ }
783
+ const nextActionFactory = this.findNextAction(submitResponse);
784
+ if (nextActionFactory) {
785
+ return nextActionFactory(submitResponse);
786
+ }
787
+ throw new Error('Next action is undefined.');
788
+ }
789
+ emitFlowUpdates(action) {
790
+ this.flowUpdatesSubject.next(action);
791
+ }
792
+ fillNextActionsList() {
793
+ this.nextActionTokens.forEach((nextAction) => {
794
+ const item = this.injector.get(nextAction.provide);
795
+ this.nextActionsList.push(item);
796
+ });
797
+ }
798
+ findNextAction(submitResponse) {
799
+ const actionType = this.nextActionsList.find((nextAction) => {
800
+ return nextAction.isSuitable(submitResponse);
801
+ });
802
+ if (!actionType) {
803
+ return;
804
+ }
805
+ return actionType.factory;
806
+ }
807
+ }
808
+ 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 });
809
+ NextActionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: NextActionService, providedIn: 'root' });
810
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: NextActionService, decorators: [{
811
+ type: Injectable,
812
+ args: [{
813
+ providedIn: 'root',
814
+ }]
815
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
816
+ type: Inject,
817
+ args: [nextActionsToken]
818
+ }] }, { type: i0.Injector }]; } });
819
+
564
820
  class InitializeService {
565
- constructor(responseFactory, secureApi, settingsService, countryService) {
821
+ constructor(responseFactory, secureApi, settingsService, countryService, nextActionService) {
566
822
  this.responseFactory = responseFactory;
567
823
  this.secureApi = secureApi;
568
824
  this.settingsService = settingsService;
569
825
  this.countryService = countryService;
826
+ this.nextActionService = nextActionService;
570
827
  this.apiRoute = 'directpayment';
571
828
  // TODO PAYMENTS-15743: replace with new refer id for headless core
572
829
  this.ps4ReferId = '22';
@@ -584,12 +841,16 @@ class InitializeService {
584
841
  headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
585
842
  responseType: 'json',
586
843
  })
587
- .pipe(map((response) => this.responseFactory(response)))).catch((error) => {
844
+ .pipe(map((response) => this.responseFactory(response)), tap((response) => {
845
+ if (response.paymentForm?.errors?.length) {
846
+ this.nextActionService.emitFlowUpdates(new ShowErrorsAction(response.paymentForm.errors));
847
+ }
848
+ }))).catch((error) => {
588
849
  throw new ResponseError(error.message);
589
850
  });
590
851
  }
591
852
  }
592
- 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 });
853
+ 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 });
593
854
  InitializeService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, providedIn: 'root' });
594
855
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, decorators: [{
595
856
  type: Injectable,
@@ -599,7 +860,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
599
860
  }], ctorParameters: function () { return [{ type: undefined, decorators: [{
600
861
  type: Inject,
601
862
  args: [initializeResponseFactoryToken]
602
- }] }, { type: SecureApiClient }, { type: SettingsService }, { type: CountryService }]; } });
863
+ }] }, { type: SecureApiClient }, { type: SettingsService }, { type: CountryService }, { type: NextActionService }]; } });
603
864
 
604
865
  class XpsApiPartRequest {
605
866
  addXpsParameters(parameters) {
@@ -945,11 +1206,12 @@ const syncResponseFactoryProvider = {
945
1206
  };
946
1207
 
947
1208
  class SyncService extends EmitDataService {
948
- constructor(requestFactory, responseFactory, secureApi, settingsService) {
1209
+ constructor(requestFactory, responseFactory, secureApi, nextActionService, settingsService) {
949
1210
  super();
950
1211
  this.requestFactory = requestFactory;
951
1212
  this.responseFactory = responseFactory;
952
1213
  this.secureApi = secureApi;
1214
+ this.nextActionService = nextActionService;
953
1215
  this.settingsService = settingsService;
954
1216
  this.apiRoute = 'directpayment';
955
1217
  this.prevFieldSyncStates = {};
@@ -1009,6 +1271,9 @@ class SyncService extends EmitDataService {
1009
1271
  headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
1010
1272
  responseType: 'json',
1011
1273
  })).then((response) => {
1274
+ if (response.errors?.length) {
1275
+ this.nextActionService.emitFlowUpdates(new ShowErrorsAction(response.errors));
1276
+ }
1012
1277
  this.emit(response);
1013
1278
  return this.responseFactory(field, response);
1014
1279
  });
@@ -1025,7 +1290,7 @@ class SyncService extends EmitDataService {
1025
1290
  this.prevFieldSyncStates[field.name] = { value, result };
1026
1291
  }
1027
1292
  }
1028
- 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 });
1293
+ 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 });
1029
1294
  SyncService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SyncService, providedIn: 'root' });
1030
1295
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SyncService, decorators: [{
1031
1296
  type: Injectable,
@@ -1038,7 +1303,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
1038
1303
  }] }, { type: undefined, decorators: [{
1039
1304
  type: Inject,
1040
1305
  args: [syncResponseFactoryToken]
1041
- }] }, { type: SecureApiClient }, { type: SettingsService }]; } });
1306
+ }] }, { type: SecureApiClient }, { type: NextActionService }, { type: SettingsService }]; } });
1042
1307
 
1043
1308
  class ControlConfig {
1044
1309
  constructor() {
@@ -1321,18 +1586,97 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
1321
1586
  type: Injectable
1322
1587
  }], ctorParameters: function () { return [{ type: ControlConfigService }]; } });
1323
1588
 
1324
- class StatusUpdatedAction {
1325
- constructor(statusResponse) {
1326
- this.type = 'status_updated';
1327
- this.data = {
1328
- statusState: statusResponse.status.statusState,
1329
- invoice: statusResponse.status.invoice,
1330
- isSuccess: statusResponse.status.isSuccess,
1331
- isCanceled: statusResponse.status.isCanceled,
1332
- group: statusResponse.status.group,
1333
- };
1334
- }
1335
- }
1589
+ var StatusSearchParam;
1590
+ (function (StatusSearchParam) {
1591
+ StatusSearchParam["token"] = "token";
1592
+ StatusSearchParam["pid"] = "fix_pid";
1593
+ StatusSearchParam["invoice"] = "fix_invoice";
1594
+ StatusSearchParam["signature"] = "signature";
1595
+ StatusSearchParam["locale"] = "locale";
1596
+ StatusSearchParam["testProject"] = "fix_testProject";
1597
+ StatusSearchParam["testPs"] = "fix_testPs";
1598
+ StatusSearchParam["testXsolla"] = "fix_testXsolla";
1599
+ StatusSearchParam["userReturnStatus"] = "fix_userReturnStatus";
1600
+ })(StatusSearchParam || (StatusSearchParam = {}));
1601
+
1602
+ const requiredStatusSearchParams = [
1603
+ StatusSearchParam.token,
1604
+ StatusSearchParam.locale,
1605
+ StatusSearchParam.signature,
1606
+ StatusSearchParam.pid,
1607
+ StatusSearchParam.invoice,
1608
+ ];
1609
+
1610
+ const stringConverter = (value) => value;
1611
+ const numberConverter = (value) => {
1612
+ const numberValue = Number(value);
1613
+ return isNaN(numberValue) ? 0 : numberValue;
1614
+ };
1615
+ const statusSearchParamsMap = new Map([
1616
+ [
1617
+ StatusSearchParam.token,
1618
+ {
1619
+ key: 'token',
1620
+ converter: stringConverter,
1621
+ },
1622
+ ],
1623
+ [
1624
+ StatusSearchParam.signature,
1625
+ {
1626
+ key: 'signature',
1627
+ converter: stringConverter,
1628
+ },
1629
+ ],
1630
+ [
1631
+ StatusSearchParam.locale,
1632
+ {
1633
+ key: 'locale',
1634
+ converter: stringConverter,
1635
+ },
1636
+ ],
1637
+ [
1638
+ StatusSearchParam.userReturnStatus,
1639
+ {
1640
+ key: 'userReturnStatus',
1641
+ converter: stringConverter,
1642
+ },
1643
+ ],
1644
+ [
1645
+ StatusSearchParam.pid,
1646
+ {
1647
+ key: 'pid',
1648
+ converter: numberConverter,
1649
+ },
1650
+ ],
1651
+ [
1652
+ StatusSearchParam.invoice,
1653
+ {
1654
+ key: 'invoice',
1655
+ converter: numberConverter,
1656
+ },
1657
+ ],
1658
+ [
1659
+ StatusSearchParam.testProject,
1660
+ {
1661
+ key: 'testProject',
1662
+ converter: numberConverter,
1663
+ },
1664
+ ],
1665
+ [
1666
+ StatusSearchParam.testPs,
1667
+ {
1668
+ key: 'testPs',
1669
+ converter: numberConverter,
1670
+ },
1671
+ ],
1672
+ [
1673
+ StatusSearchParam.testXsolla,
1674
+ {
1675
+ key: 'testXsolla',
1676
+ converter: numberConverter,
1677
+ },
1678
+ ],
1679
+ ]);
1336
1680
 
1337
1681
  class XpsApiPart {
1338
1682
  constructor() {
@@ -1356,7 +1700,7 @@ class StatusRequest extends XpsApiPartRequest {
1356
1700
  constructor(parameters) {
1357
1701
  super();
1358
1702
  this.xps_fix_command = 'status';
1359
- if (parameters.token === null) {
1703
+ if (!parameters.token) {
1360
1704
  throw new TokenError();
1361
1705
  }
1362
1706
  this.access_token = parameters.token;
@@ -2295,164 +2639,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
2295
2639
  }]
2296
2640
  }], ctorParameters: function () { return [{ type: StatusRequestService }, { type: CheckStatusService }, { type: WebsocketStatusService }]; } });
2297
2641
 
2298
- class ShowFieldsAction {
2299
- constructor(submitResponse) {
2300
- this.type = 'show_fields';
2301
- this.data = {
2302
- fields: [],
2303
- errors: [],
2304
- messages: [],
2305
- order: {},
2306
- };
2307
- this.data.fields = submitResponse.fields.filter((field) => field?.isVisible === "1" /* XpsBoolean.true */);
2308
- this.data.errors = submitResponse.errors;
2309
- this.data.messages = submitResponse.messages;
2310
- this.data.order = submitResponse.summary;
2311
- }
2312
- }
2313
-
2314
- const showFieldsActionFactoryToken = new InjectionToken('ShowFieldsAction');
2315
- const showFieldsActionFactoryProvider = {
2316
- provide: showFieldsActionFactoryToken,
2317
- useValue: {
2318
- factory: (...args) => new ShowFieldsAction(...args),
2319
- isSuitable: (response) => {
2320
- return response.currentCommand === XpsCommand.check;
2321
- },
2322
- },
2323
- };
2324
-
2325
- class CheckStatusAction {
2326
- constructor(submitResponse) {
2327
- this.type = 'check_status';
2328
- const status = submitResponse.parameters.status;
2329
- this.data = {
2330
- invoice: status?.invoice,
2331
- signature: submitResponse.parameters.form.signature?.value,
2332
- locale: submitResponse.parameters.form.locale?.value,
2333
- testPs: submitResponse.parameters.form.testPs?.value,
2334
- testXsolla: submitResponse.parameters.form.testXsolla?.value,
2335
- testProject: submitResponse.parameters.form.testProject?.value,
2336
- userReturnStatus: submitResponse.parameters.form.userReturnStatus?.value,
2337
- };
2338
- }
2339
- }
2340
-
2341
- const checkStatusActionFactoryToken = new InjectionToken('CheckStatusAction');
2342
- const checkStatusActionFactoryProvider = {
2343
- provide: checkStatusActionFactoryToken,
2344
- useValue: {
2345
- factory: (...args) => new CheckStatusAction(...args),
2346
- isSuitable: (response) => {
2347
- return response.currentCommand === XpsCommand.status;
2348
- },
2349
- },
2350
- };
2351
-
2352
- const statusUpdatedActionFactoryToken = new InjectionToken('StatusUpdatedAction');
2353
- const statusUpdatedActionFactoryProvider = {
2354
- provide: statusUpdatedActionFactoryToken,
2355
- useValue: {
2356
- factory: (...args) => new StatusUpdatedAction(...args),
2357
- isSuitable: () => false,
2358
- },
2359
- };
2360
-
2361
- class RedirectAction {
2362
- constructor(submitResponse) {
2363
- this.type = 'redirect';
2364
- this.data = {
2365
- fields: submitResponse.fields,
2366
- errors: submitResponse.errors,
2367
- messages: submitResponse.messages,
2368
- order: submitResponse.summary,
2369
- invoiceId: submitResponse.fixInvoice,
2370
- redirect: this.getRedirect(submitResponse),
2371
- };
2372
- }
2373
- getRedirect(submitResponse) {
2374
- return {
2375
- redirectUrl: submitResponse.parameters.checkout.action,
2376
- data: submitResponse.parameters.checkout.data,
2377
- };
2378
- }
2379
- }
2380
-
2381
- const redirectActionFactoryToken = new InjectionToken('RedirectAction');
2382
- const redirectActionFactoryProvider = {
2383
- provide: redirectActionFactoryToken,
2384
- useValue: {
2385
- factory: (...args) => new RedirectAction(...args),
2386
- isSuitable: (response) => {
2387
- return (response.currentCommand === XpsCommand.account ||
2388
- (response.currentCommand === XpsCommand.checkout &&
2389
- Boolean(response.parameters.checkout)));
2390
- },
2391
- },
2392
- };
2393
-
2394
- const nextActionsToken = new InjectionToken('Action');
2395
- const nextActions = [
2396
- showFieldsActionFactoryProvider,
2397
- checkStatusActionFactoryProvider,
2398
- statusUpdatedActionFactoryProvider,
2399
- redirectActionFactoryProvider,
2400
- ];
2401
-
2402
- class NextActionService {
2403
- get flowUpdates$() {
2404
- return this.flowUpdatesSubject.asObservable();
2405
- }
2406
- constructor(nextActionTokens, injector) {
2407
- this.nextActionTokens = nextActionTokens;
2408
- this.injector = injector;
2409
- this.flowUpdatesSubject = new Subject();
2410
- this.nextActionsList = [];
2411
- this.fillNextActionsList();
2412
- }
2413
- getNextAction(submitResponse) {
2414
- if (!submitResponse.currentCommand) {
2415
- return null;
2416
- }
2417
- const nextActionFactory = this.findNextAction(submitResponse);
2418
- if (nextActionFactory) {
2419
- return nextActionFactory(submitResponse);
2420
- }
2421
- throw new Error('Next action is undefined.');
2422
- }
2423
- emitFlowUpdates(action) {
2424
- this.flowUpdatesSubject.next(action);
2425
- }
2426
- fillNextActionsList() {
2427
- this.nextActionTokens.forEach((nextAction) => {
2428
- const item = this.injector.get(nextAction.provide);
2429
- this.nextActionsList.push(item);
2430
- });
2431
- }
2432
- findNextAction(submitResponse) {
2433
- const actionType = this.nextActionsList.find((nextAction) => {
2434
- return nextAction.isSuitable(submitResponse);
2435
- });
2436
- if (!actionType) {
2437
- return;
2438
- }
2439
- return actionType.factory;
2440
- }
2441
- }
2442
- 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 });
2443
- NextActionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: NextActionService, providedIn: 'root' });
2444
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: NextActionService, decorators: [{
2445
- type: Injectable,
2446
- args: [{
2447
- providedIn: 'root',
2448
- }]
2449
- }], ctorParameters: function () { return [{ type: undefined, decorators: [{
2450
- type: Inject,
2451
- args: [nextActionsToken]
2452
- }] }, { type: i0.Injector }]; } });
2453
-
2454
2642
  class StatusService {
2455
- constructor(statusRequestService, listenStatusService, nextActionService) {
2643
+ constructor(urlService, statusRequestService, listenStatusService, nextActionService) {
2644
+ this.urlService = urlService;
2456
2645
  this.statusRequestService = statusRequestService;
2457
2646
  this.listenStatusService = listenStatusService;
2458
2647
  this.nextActionService = nextActionService;
@@ -2464,6 +2653,25 @@ class StatusService {
2464
2653
  const statusResponse = await firstValueFrom(this.statusRequestService.response$);
2465
2654
  return statusResponse.status;
2466
2655
  }
2656
+ async getStatusWithUrlSearchParams(url) {
2657
+ const searchParams = this.getRequestParamsFromUrl(url);
2658
+ if (!searchParams) {
2659
+ throw new Error('No required search params to get status');
2660
+ }
2661
+ return this.getStatus(searchParams);
2662
+ }
2663
+ getRequestParamsFromUrl(url) {
2664
+ const searchParams = this.urlService.getSearchParams(url ?? '');
2665
+ const keys = new Set(Object.keys(searchParams));
2666
+ if (requiredStatusSearchParams.some((requiredKey) => !keys.has(requiredKey))) {
2667
+ return null;
2668
+ }
2669
+ const params = {};
2670
+ statusSearchParamsMap.forEach((settings, key) => {
2671
+ params[settings.key] = settings.converter(searchParams[key]);
2672
+ });
2673
+ return params;
2674
+ }
2467
2675
  startWaitingStatusUpdates(invoice) {
2468
2676
  this.listenStatusService.listen(invoice);
2469
2677
  this.listenStatusService.statusUpdated$
@@ -2473,14 +2681,14 @@ class StatusService {
2473
2681
  });
2474
2682
  }
2475
2683
  }
2476
- StatusService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: StatusService, deps: [{ token: StatusRequestService }, { token: ListenStatusService }, { token: NextActionService }], target: i0.ɵɵFactoryTarget.Injectable });
2684
+ StatusService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: StatusService, deps: [{ token: UrlService }, { token: StatusRequestService }, { token: ListenStatusService }, { token: NextActionService }], target: i0.ɵɵFactoryTarget.Injectable });
2477
2685
  StatusService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: StatusService, providedIn: 'root' });
2478
2686
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: StatusService, decorators: [{
2479
2687
  type: Injectable,
2480
2688
  args: [{
2481
2689
  providedIn: 'root',
2482
2690
  }]
2483
- }], ctorParameters: function () { return [{ type: StatusRequestService }, { type: ListenStatusService }, { type: NextActionService }]; } });
2691
+ }], ctorParameters: function () { return [{ type: UrlService }, { type: StatusRequestService }, { type: ListenStatusService }, { type: NextActionService }]; } });
2484
2692
 
2485
2693
  /**
2486
2694
  * default image for purchase item is set on Publisher Account side.
@@ -2792,6 +3000,7 @@ class PaymentService {
2792
3000
  this.data = await this.initializeService.request(config);
2793
3001
  this.fields = this.getFields();
2794
3002
  this.form = this.formService.createForm(this.fields);
3003
+ this.listenSyncValidationErrors(this.form);
2795
3004
  this.emitFinanceDetails(this.data.paymentForm?.summary);
2796
3005
  this.setupSyncService(this.form, this.fields);
2797
3006
  return this.fields.filter((field) => field?.isVisible === "1" /* XpsBoolean.true */);
@@ -2829,15 +3038,13 @@ class PaymentService {
2829
3038
  throw new Error('Should submit form first');
2830
3039
  }
2831
3040
  const params = {
3041
+ pid: this.config.paymentMethodId,
2832
3042
  invoice: parseInt(this.data.fixInvoice ?? ''),
2833
3043
  signature: this.data.signature ?? '',
2834
3044
  locale: this.data.fields.find((field) => field.name === 'locale')?.value ??
2835
3045
  'en',
2836
3046
  };
2837
- return this.statusService.getStatus({
2838
- ...params,
2839
- pid: this.config.paymentMethodId,
2840
- });
3047
+ return this.statusService.getStatus(params);
2841
3048
  }
2842
3049
  getFieldConfig(field) {
2843
3050
  return this.controlConfigService.getConfig(field);
@@ -2867,6 +3074,31 @@ class PaymentService {
2867
3074
  .pipe(takeUntil(this.destroy$))
2868
3075
  .subscribe((financeDetails) => (this.financeDetails = financeDetails));
2869
3076
  }
3077
+ listenSyncValidationErrors(form) {
3078
+ form.statusChanges.subscribe(() => {
3079
+ const controls = this.form?.controls;
3080
+ if (controls) {
3081
+ const invalidControls = Object.entries(controls).filter(([key]) => controls[key].invalid);
3082
+ if (invalidControls.length) {
3083
+ const syncValidationErrors = invalidControls
3084
+ .map(([controlName, control]) => {
3085
+ const error = control.errors?.['rewritableError'];
3086
+ if (!error) {
3087
+ return null;
3088
+ }
3089
+ return {
3090
+ code: 101,
3091
+ fieldValidationError: error?.code,
3092
+ message: error?.message ?? '',
3093
+ element_name: controlName,
3094
+ };
3095
+ })
3096
+ .filter(Boolean);
3097
+ this.nextActionService.emitFlowUpdates(new ShowErrorsAction(syncValidationErrors));
3098
+ }
3099
+ }
3100
+ });
3101
+ }
2870
3102
  }
2871
3103
  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 });
2872
3104
  PaymentService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PaymentService, providedIn: 'root' });
@@ -2980,16 +3212,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
2980
3212
  }], ctorParameters: function () { return [{ type: SettingsService }, { type: RefundPolicyService }, { type: SecureConnectionService }, { type: DisclaimerService }]; } });
2981
3213
 
2982
3214
  class CoreLibraryService {
2983
- constructor(settingsService, countryService, paymentMethodsService, savedMethodsService, userBalanceService, paymentService, deviceFingerPrintService, financeDetailsService, legalService, nextActionService) {
3215
+ constructor(settingsService, countryService, paymentMethodsService, savedMethodsService, userBalanceService, paymentConfigService, paymentService, deviceFingerPrintService, financeDetailsService, legalService, statusService, nextActionService) {
2984
3216
  this.settingsService = settingsService;
2985
3217
  this.countryService = countryService;
2986
3218
  this.paymentMethodsService = paymentMethodsService;
2987
3219
  this.savedMethodsService = savedMethodsService;
2988
3220
  this.userBalanceService = userBalanceService;
3221
+ this.paymentConfigService = paymentConfigService;
2989
3222
  this.paymentService = paymentService;
2990
3223
  this.deviceFingerPrintService = deviceFingerPrintService;
2991
3224
  this.financeDetailsService = financeDetailsService;
2992
3225
  this.legalService = legalService;
3226
+ this.statusService = statusService;
2993
3227
  this.nextActionService = nextActionService;
2994
3228
  this.paymentMethods = {
2995
3229
  getList: async () => this.paymentMethodsService.getList(),
@@ -3002,12 +3236,16 @@ class CoreLibraryService {
3002
3236
  await this.settingsService.init(configuration);
3003
3237
  await this.deviceFingerPrintService.init();
3004
3238
  }
3239
+ async getStatus(url) {
3240
+ return this.statusService.getStatusWithUrlSearchParams(url);
3241
+ }
3005
3242
  setCountry(country) {
3006
3243
  this.countryService.setCountry(country);
3007
3244
  }
3008
3245
  createPayment(config) {
3246
+ const enrichedConfig = this.paymentConfigService.enrich(config);
3009
3247
  return {
3010
- initialize: async () => this.paymentService.initialize(config),
3248
+ initialize: async () => this.paymentService.initialize(enrichedConfig),
3011
3249
  submit: async () => this.paymentService.submit(),
3012
3250
  getFields: () => this.paymentService.getFields(),
3013
3251
  validate: async (field) => this.paymentService.validate(field),
@@ -3030,14 +3268,14 @@ class CoreLibraryService {
3030
3268
  return masksFunctionsMap[sanitizedName];
3031
3269
  }
3032
3270
  }
3033
- CoreLibraryService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryService, deps: [{ token: SettingsService }, { token: CountryService }, { token: PaymentMethodsService }, { token: SavedMethodsService }, { token: UserBalanceService }, { token: PaymentService }, { token: DeviceFingerPrintService }, { token: FinanceDetailsService }, { token: LegalService }, { token: NextActionService }], target: i0.ɵɵFactoryTarget.Injectable });
3271
+ CoreLibraryService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryService, deps: [{ token: SettingsService }, { token: CountryService }, { token: PaymentMethodsService }, { token: SavedMethodsService }, { token: UserBalanceService }, { token: PaymentConfigService }, { token: PaymentService }, { token: DeviceFingerPrintService }, { token: FinanceDetailsService }, { token: LegalService }, { token: StatusService }, { token: NextActionService }], target: i0.ɵɵFactoryTarget.Injectable });
3034
3272
  CoreLibraryService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryService, providedIn: 'root' });
3035
3273
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryService, decorators: [{
3036
3274
  type: Injectable,
3037
3275
  args: [{
3038
3276
  providedIn: 'root',
3039
3277
  }]
3040
- }], ctorParameters: function () { return [{ type: SettingsService }, { type: CountryService }, { type: PaymentMethodsService }, { type: SavedMethodsService }, { type: UserBalanceService }, { type: PaymentService }, { type: DeviceFingerPrintService }, { type: FinanceDetailsService }, { type: LegalService }, { type: NextActionService }]; } });
3278
+ }], ctorParameters: function () { return [{ type: SettingsService }, { type: CountryService }, { type: PaymentMethodsService }, { type: SavedMethodsService }, { type: UserBalanceService }, { type: PaymentConfigService }, { type: PaymentService }, { type: DeviceFingerPrintService }, { type: FinanceDetailsService }, { type: LegalService }, { type: StatusService }, { type: NextActionService }]; } });
3041
3279
 
3042
3280
  class HttpError extends AppError {
3043
3281
  constructor(error, req) {
@@ -3148,6 +3386,7 @@ CoreLibraryModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", versi
3148
3386
  useValue: nextActions,
3149
3387
  },
3150
3388
  ...nextActions,
3389
+ ...flowUpdateNextActions,
3151
3390
  ], imports: [HttpClientModule, FormModule] });
3152
3391
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryModule, decorators: [{
3153
3392
  type: NgModule,
@@ -3178,6 +3417,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
3178
3417
  useValue: nextActions,
3179
3418
  },
3180
3419
  ...nextActions,
3420
+ ...flowUpdateNextActions,
3181
3421
  ],
3182
3422
  }]
3183
3423
  }] });