@xsolla/payment-client-core 0.0.4 → 0.0.6
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.
- package/esm2020/lib/core/device-finger-print/device-finger-print-components.interface.mjs +2 -0
- package/esm2020/lib/core/device-finger-print/device-finger-print.service.mjs +167 -0
- package/esm2020/lib/core/device-finger-print/fingerprint-js.interface.mjs +2 -0
- package/esm2020/lib/core/device-finger-print/hash.type.mjs +2 -0
- package/esm2020/lib/core/exceptions-handling/elk/additional-info.interface.mjs +2 -0
- package/esm2020/lib/core/exceptions-handling/elk/elk-logger.service.mjs +120 -0
- package/esm2020/lib/core/exceptions-handling/elk/error-without-meta-fields.interface.mjs +2 -0
- package/esm2020/lib/core/exceptions-handling/elk/log-message.interface.mjs +2 -0
- package/esm2020/lib/core/exceptions-handling/errors/default-terminal-error.class.mjs +8 -0
- package/esm2020/lib/core/exceptions-handling/errors/elk-error-types.enum.mjs +13 -0
- package/esm2020/lib/core/exceptions-handling/errors/tagged-error.class.mjs +16 -0
- package/esm2020/lib/core/exceptions-handling/errors/terminal-error.class.mjs +8 -0
- package/esm2020/lib/core/exceptions-handling/errors/token-error.class.mjs +7 -0
- package/esm2020/lib/core/exceptions-handling/errors/ws-error.class.mjs +10 -0
- package/esm2020/lib/core/payment/actions/action-factory-value.interface.mjs +2 -0
- package/esm2020/lib/core/payment/actions/action-type-command.map.mjs +6 -0
- package/esm2020/lib/core/payment/actions/action.interface.mjs +2 -0
- package/esm2020/lib/core/payment/actions/check-status/check-status.action.class.mjs +16 -0
- package/esm2020/lib/core/payment/actions/check-status/check-status.action.token.mjs +11 -0
- package/esm2020/lib/core/payment/actions/check-status/check-status.action.type.mjs +2 -0
- package/esm2020/lib/core/payment/actions/next-action.interface.mjs +2 -0
- package/esm2020/lib/core/payment/actions/next-action.service.mjs +55 -0
- package/esm2020/lib/core/payment/actions/next-actions.mjs +11 -0
- package/esm2020/lib/core/payment/actions/show-fields/show-fields.action.class.mjs +16 -0
- package/esm2020/lib/core/payment/actions/show-fields/show-fields.action.token.mjs +11 -0
- package/esm2020/lib/core/payment/actions/show-fields/show-fields.action.type.mjs +2 -0
- package/esm2020/lib/core/payment/actions/status-updated/status-updated.action.class.mjs +13 -0
- package/esm2020/lib/core/payment/actions/status-updated/status-updated.action.token.mjs +11 -0
- package/esm2020/lib/core/payment/actions/status-updated/status-updated.action.type.mjs +2 -0
- package/esm2020/lib/core/payment/field-names.enum.mjs +64 -0
- package/esm2020/lib/core/payment/field.interface.mjs +1 -1
- package/esm2020/lib/core/payment/form/common-control-config.interface.mjs +2 -0
- package/esm2020/lib/core/payment/form/controls/control-config.mjs +6 -0
- package/esm2020/lib/core/payment/form/controls/control-config.service.mjs +39 -0
- package/esm2020/lib/core/payment/form/controls/control-type.type.mjs +2 -0
- package/esm2020/lib/core/payment/form/controls/text-control.config.mjs +8 -0
- package/esm2020/lib/core/payment/form/converters/converter.abstract.mjs +75 -0
- package/esm2020/lib/core/payment/form/converters/converters-map.interface.mjs +2 -0
- package/esm2020/lib/core/payment/form/converters/converters-map.mjs +9 -0
- package/esm2020/lib/core/payment/form/converters/email.converter.mjs +29 -0
- package/esm2020/lib/core/payment/form/converters/zip.converter.mjs +64 -0
- package/esm2020/lib/core/payment/form/form-state.interface.mjs +2 -0
- package/esm2020/lib/core/payment/form/form.module.mjs +33 -0
- package/esm2020/lib/core/payment/form/form.service.mjs +28 -0
- package/esm2020/lib/core/payment/form/validators/convert.function.mjs +22 -0
- package/esm2020/lib/core/payment/form/validators/email-validator.mjs +7 -0
- package/esm2020/lib/core/payment/form/validators/required-validator.mjs +6 -0
- package/esm2020/lib/core/payment/form/validators/restricted-value.validator.mjs +6 -0
- package/esm2020/lib/core/payment/form/validators/validation-error.interface.mjs +2 -0
- package/esm2020/lib/core/payment/form/validators/validation-errors.interface.mjs +2 -0
- package/esm2020/lib/core/payment/form/validators/validator-fn.type.mjs +2 -0
- package/esm2020/lib/core/payment/initialize/initialize-request-params.interface.mjs +2 -0
- package/esm2020/lib/core/payment/initialize/initialize-response.class.mjs +43 -0
- package/esm2020/lib/core/payment/initialize/initialize-response.token.mjs +8 -0
- package/esm2020/lib/core/payment/initialize/initialize.service.mjs +46 -0
- package/esm2020/lib/core/payment/payment-form.interface.mjs +2 -0
- package/esm2020/lib/core/payment/payment.interface.mjs +1 -1
- package/esm2020/lib/core/payment/payment.service.mjs +37 -14
- package/esm2020/lib/core/payment/status/check-status/check-status.service.mjs +56 -0
- package/esm2020/lib/core/payment/status/check-status/request/check-status-request.class.mjs +16 -0
- package/esm2020/lib/core/payment/status/check-status/request/check-status-request.token.mjs +8 -0
- package/esm2020/lib/core/payment/status/check-status/response/check-status-response.class.mjs +9 -0
- package/esm2020/lib/core/payment/status/check-status/response/check-status-response.token.mjs +8 -0
- package/esm2020/lib/core/payment/status/listen-status/listen-status.service.mjs +112 -0
- package/esm2020/lib/core/payment/status/status-groups.mjs +7 -0
- package/esm2020/lib/core/payment/status/status-params.interface.mjs +2 -0
- package/esm2020/lib/core/payment/status/status-request/request/status-request.class.mjs +22 -0
- package/esm2020/lib/core/payment/status/status-request/request/status-request.token.mjs +8 -0
- package/esm2020/lib/core/payment/status/status-request/response/status-response.class.mjs +96 -0
- package/esm2020/lib/core/payment/status/status-request/response/status-response.token.mjs +8 -0
- package/esm2020/lib/core/payment/status/status-request/status-request-params.interface.mjs +2 -0
- package/esm2020/lib/core/payment/status/status-request/status-request.service.mjs +68 -0
- package/esm2020/lib/core/payment/status/status-settings.interface.mjs +2 -0
- package/esm2020/lib/core/payment/status/status-updated.interface.mjs +2 -0
- package/esm2020/lib/core/payment/status/status.interface.mjs +1 -1
- package/esm2020/lib/core/payment/status/status.service.mjs +38 -0
- package/esm2020/lib/core/payment/status/websocket-status/websocket-status.enum.mjs +6 -0
- package/esm2020/lib/core/payment/status/websocket-status/websocket-status.service.mjs +76 -0
- package/esm2020/lib/core/payment/submit/request/submit-request.class.mjs +16 -0
- package/esm2020/lib/core/payment/submit/request/submit-request.token.mjs +8 -0
- package/esm2020/lib/core/payment/submit/response/submit-response.class.mjs +31 -0
- package/esm2020/lib/core/payment/submit/response/submit-response.token.mjs +8 -0
- package/esm2020/lib/core/payment/submit/submit.service.mjs +59 -0
- package/esm2020/lib/core/payment/sync/field-sync-state.interface.mjs +2 -0
- package/esm2020/lib/core/payment/sync/sync-request.class.mjs +31 -0
- package/esm2020/lib/core/payment/sync/sync-request.token.mjs +8 -0
- package/esm2020/lib/core/payment/sync/sync-response.class.mjs +14 -0
- package/esm2020/lib/core/payment/sync/sync-response.token.mjs +8 -0
- package/esm2020/lib/core/payment/sync/sync.service.mjs +91 -0
- package/esm2020/lib/core/payment/xps-api-part-request.abstract.mjs +8 -0
- package/esm2020/lib/core/payment/xps-api-part.abstract.mjs +19 -0
- package/esm2020/lib/core/payment/xps-error.interface.mjs +1 -1
- package/esm2020/lib/core/payment/xps-request.abstract.mjs +8 -0
- package/esm2020/lib/core/payment/xps-response.interface.mjs +1 -1
- package/esm2020/lib/core/properties.type.mjs +2 -0
- package/esm2020/lib/core/web-socket/centrifugo-web-socket.service.mjs +200 -0
- package/esm2020/lib/core/web-socket/nchan-web-socket.service.mjs +116 -0
- package/esm2020/lib/core/web-socket/web-socket-client-type.enum.mjs +6 -0
- package/esm2020/lib/core/web-socket/web-socket.factory.mjs +28 -0
- package/esm2020/lib/core/web-socket/web-socket.interface.mjs +2 -0
- package/esm2020/lib/core/xps-boolean.enum.mjs +2 -0
- package/esm2020/lib/core-library.module.mjs +43 -4
- package/esm2020/lib/core-library.service.mjs +18 -11
- package/fesm2015/xsolla-payment-client-core.mjs +2201 -87
- package/fesm2015/xsolla-payment-client-core.mjs.map +1 -1
- package/fesm2020/xsolla-payment-client-core.mjs +2117 -83
- package/fesm2020/xsolla-payment-client-core.mjs.map +1 -1
- package/lib/core/device-finger-print/device-finger-print-components.interface.d.ts +4 -0
- package/lib/core/device-finger-print/device-finger-print.service.d.ts +44 -0
- package/lib/core/device-finger-print/fingerprint-js.interface.d.ts +6 -0
- package/lib/core/device-finger-print/hash.type.d.ts +3 -0
- package/lib/core/exceptions-handling/elk/additional-info.interface.d.ts +19 -0
- package/lib/core/exceptions-handling/elk/elk-logger.service.d.ts +27 -0
- package/lib/core/exceptions-handling/elk/error-without-meta-fields.interface.d.ts +8 -0
- package/lib/core/exceptions-handling/elk/log-message.interface.d.ts +8 -0
- package/lib/core/exceptions-handling/errors/default-terminal-error.class.d.ts +4 -0
- package/lib/core/exceptions-handling/errors/elk-error-types.enum.d.ts +11 -0
- package/lib/core/exceptions-handling/errors/tagged-error.class.d.ts +10 -0
- package/lib/core/exceptions-handling/errors/terminal-error.class.d.ts +5 -0
- package/lib/core/exceptions-handling/errors/token-error.class.d.ts +4 -0
- package/lib/core/exceptions-handling/errors/ws-error.class.d.ts +5 -0
- package/lib/core/payment/actions/action-factory-value.interface.d.ts +5 -0
- package/lib/core/payment/actions/action-type-command.map.d.ts +4 -0
- package/lib/core/payment/actions/check-status/check-status.action.class.d.ts +8 -0
- package/lib/core/payment/actions/check-status/check-status.action.token.d.ts +4 -0
- package/lib/core/payment/actions/check-status/check-status.action.type.d.ts +12 -0
- package/lib/core/payment/actions/next-action.interface.d.ts +4 -0
- package/lib/core/payment/actions/next-action.service.d.ts +20 -0
- package/lib/core/payment/actions/next-actions.d.ts +5 -0
- package/lib/core/payment/actions/show-fields/show-fields.action.class.d.ts +8 -0
- package/lib/core/payment/actions/show-fields/show-fields.action.token.d.ts +4 -0
- package/lib/core/payment/actions/show-fields/show-fields.action.type.d.ts +12 -0
- package/lib/core/payment/actions/status-updated/status-updated.action.class.d.ts +8 -0
- package/lib/core/payment/actions/status-updated/status-updated.action.token.d.ts +4 -0
- package/lib/core/payment/actions/status-updated/status-updated.action.type.d.ts +11 -0
- package/lib/core/payment/field-names.enum.d.ts +62 -0
- package/lib/core/payment/field.interface.d.ts +5 -5
- package/lib/core/payment/form/common-control-config.interface.d.ts +9 -0
- package/lib/core/payment/form/controls/control-config.d.ts +9 -0
- package/lib/core/payment/form/controls/control-config.service.d.ts +15 -0
- package/lib/core/payment/form/controls/control-type.type.d.ts +1 -0
- package/lib/core/payment/form/controls/text-control.config.d.ts +11 -0
- package/lib/core/payment/form/converters/converter.abstract.d.ts +23 -0
- package/lib/core/payment/form/converters/converters-map.d.ts +4 -0
- package/lib/core/payment/form/converters/converters-map.interface.d.ts +5 -0
- package/lib/core/payment/form/converters/email.converter.d.ts +14 -0
- package/lib/core/payment/form/converters/zip.converter.d.ts +21 -0
- package/lib/core/payment/form/form-state.interface.d.ts +3 -0
- package/lib/core/payment/form/form.module.d.ts +7 -0
- package/lib/core/payment/form/form.service.d.ts +12 -0
- package/lib/core/payment/form/validators/convert.function.d.ts +3 -0
- package/lib/core/payment/form/validators/email-validator.d.ts +2 -0
- package/lib/core/payment/form/validators/required-validator.d.ts +2 -0
- package/lib/core/payment/form/validators/restricted-value.validator.d.ts +2 -0
- package/lib/core/payment/form/validators/validation-error.interface.d.ts +4 -0
- package/lib/core/payment/form/validators/validation-errors.interface.d.ts +4 -0
- package/lib/core/payment/form/validators/validator-fn.type.d.ts +3 -0
- package/lib/core/payment/initialize/initialize-response.class.d.ts +7 -0
- package/lib/core/payment/initialize/initialize-response.token.d.ts +6 -0
- package/lib/core/payment/initialize/initialize.service.d.ts +18 -0
- package/lib/core/payment/payment-form.interface.d.ts +39 -0
- package/lib/core/payment/payment.interface.d.ts +12 -8
- package/lib/core/payment/payment.service.d.ts +23 -8
- package/lib/core/payment/status/check-status/check-status.service.d.ts +20 -0
- package/lib/core/payment/status/check-status/request/check-status-request.class.d.ts +8 -0
- package/lib/core/payment/status/check-status/request/check-status-request.token.d.ts +6 -0
- package/lib/core/payment/status/check-status/response/check-status-response.class.d.ts +8 -0
- package/lib/core/payment/status/check-status/response/check-status-response.token.d.ts +7 -0
- package/lib/core/payment/status/listen-status/listen-status.service.d.ts +28 -0
- package/lib/core/payment/status/status-groups.d.ts +5 -0
- package/lib/core/payment/status/status-params.interface.d.ts +9 -0
- package/lib/core/payment/status/status-request/request/status-request.class.d.ts +17 -0
- package/lib/core/payment/status/status-request/request/status-request.token.d.ts +6 -0
- package/lib/core/payment/status/status-request/response/status-response.class.d.ts +14 -0
- package/lib/core/payment/status/status-request/response/status-response.token.d.ts +7 -0
- package/lib/core/payment/status/status-request/status-request-params.interface.d.ts +10 -0
- package/lib/core/payment/status/status-request/status-request.service.d.ts +21 -0
- package/lib/core/payment/status/status-settings.interface.d.ts +13 -0
- package/lib/core/payment/status/status-updated.interface.d.ts +6 -0
- package/lib/core/payment/status/status.interface.d.ts +0 -1
- package/lib/core/payment/status/status.service.d.ts +16 -0
- package/lib/core/payment/status/websocket-status/websocket-status.enum.d.ts +4 -0
- package/lib/core/payment/status/websocket-status/websocket-status.service.d.ts +24 -0
- package/lib/core/payment/submit/request/submit-request.class.d.ts +13 -0
- package/lib/core/payment/submit/request/submit-request.token.d.ts +6 -0
- package/lib/core/payment/submit/response/submit-response.class.d.ts +26 -0
- package/lib/core/payment/submit/response/submit-response.token.d.ts +6 -0
- package/lib/core/payment/submit/submit.service.d.ts +21 -0
- package/lib/core/payment/sync/field-sync-state.interface.d.ts +5 -0
- package/lib/core/payment/sync/sync-request.class.d.ts +15 -0
- package/lib/core/payment/sync/sync-request.token.d.ts +6 -0
- package/lib/core/payment/sync/sync-response.class.d.ts +11 -0
- package/lib/core/payment/sync/sync-response.token.d.ts +6 -0
- package/lib/core/payment/sync/sync.service.d.ts +27 -0
- package/lib/core/payment/xps-api-part-request.abstract.d.ts +6 -0
- package/lib/core/payment/xps-api-part.abstract.d.ts +8 -0
- package/lib/core/payment/xps-error.interface.d.ts +1 -0
- package/lib/core/payment/xps-request.abstract.d.ts +6 -0
- package/lib/core/payment/xps-response.interface.d.ts +3 -6
- package/lib/core/properties.type.d.ts +3 -0
- package/lib/core/web-socket/centrifugo-web-socket.service.d.ts +41 -0
- package/lib/core/web-socket/nchan-web-socket.service.d.ts +30 -0
- package/lib/core/web-socket/web-socket-client-type.enum.d.ts +4 -0
- package/lib/core/web-socket/web-socket.factory.d.ts +13 -0
- package/lib/core/web-socket/web-socket.interface.d.ts +9 -0
- package/lib/core/xps-boolean.enum.d.ts +4 -0
- package/lib/core-library.module.d.ts +2 -1
- package/lib/core-library.service.d.ts +6 -2
- package/package.json +19 -4
- package/xsolla-payment-client-core-0.0.6.tgz +0 -0
- package/esm2020/lib/core/boolean-string.enum.mjs +0 -6
- package/esm2020/lib/core/payment/actions/action.type.mjs +0 -2
- package/esm2020/lib/core/payment/actions/check-status.action.type.mjs +0 -2
- package/esm2020/lib/core/payment/actions/next-action.type.mjs +0 -2
- package/esm2020/lib/core/payment/initialize-request-params.interface.mjs +0 -2
- package/esm2020/lib/core/payment/initialize.service.mjs +0 -39
- package/lib/core/boolean-string.enum.d.ts +0 -4
- package/lib/core/payment/actions/check-status.action.type.d.ts +0 -12
- package/lib/core/payment/actions/next-action.type.d.ts +0 -2
- package/lib/core/payment/initialize.service.d.ts +0 -16
- package/xsolla-payment-client-core-0.0.4.tgz +0 -0
- /package/lib/core/payment/actions/{action.type.d.ts → action.interface.d.ts} +0 -0
- /package/lib/core/payment/{initialize-request-params.interface.d.ts → initialize/initialize-request-params.interface.d.ts} +0 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, Injectable, Inject, NgModule } from '@angular/core';
|
|
3
|
-
import { firstValueFrom, lastValueFrom, map, throwError } from 'rxjs';
|
|
2
|
+
import { InjectionToken, Injectable, Inject, isDevMode, NgModule } from '@angular/core';
|
|
3
|
+
import { firstValueFrom, lastValueFrom, map, BehaviorSubject, Subject, 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 {
|
|
6
|
+
import { UntypedFormGroup, Validators, UntypedFormControl, ReactiveFormsModule } from '@angular/forms';
|
|
7
|
+
import { filter, map as map$1, catchError } from 'rxjs/operators';
|
|
7
8
|
import * as i1$1 from '@angular/router';
|
|
8
9
|
|
|
9
10
|
class AppError extends Error {
|
|
@@ -397,6 +398,2050 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
|
|
|
397
398
|
args: [userBalanceResponseFactoryToken]
|
|
398
399
|
}] }, { type: SettingsService }, { type: SecureApiClient }]; } });
|
|
399
400
|
|
|
401
|
+
class InitializeResponse {
|
|
402
|
+
constructor(response) {
|
|
403
|
+
this.paymentForm = null;
|
|
404
|
+
this.paymentForm = this.extractPaymentForm(response);
|
|
405
|
+
}
|
|
406
|
+
extractPaymentForm(response) {
|
|
407
|
+
if (!response) {
|
|
408
|
+
return null;
|
|
409
|
+
}
|
|
410
|
+
return {
|
|
411
|
+
totalAmount: response.buyData.sum,
|
|
412
|
+
currency: response.buyData.currency,
|
|
413
|
+
fields: Object.keys(response.form).map((key) => response.form[key]),
|
|
414
|
+
taxDisclaimer: response.taxDisclaimer,
|
|
415
|
+
number: response.number,
|
|
416
|
+
barcode: response.barcode,
|
|
417
|
+
instruction: response.instruction,
|
|
418
|
+
offers: response.offers,
|
|
419
|
+
error: response.error,
|
|
420
|
+
errors: response.errors,
|
|
421
|
+
restrictions: response.restrictions,
|
|
422
|
+
info: response.info,
|
|
423
|
+
buyData: response.buyData,
|
|
424
|
+
pid: response.pid,
|
|
425
|
+
messages: response.messages ?? [],
|
|
426
|
+
title: response.title,
|
|
427
|
+
summary: response.summary,
|
|
428
|
+
skipForm: response.skipForm,
|
|
429
|
+
isSavedMethodPayment: !!response.form?.saved_method_id,
|
|
430
|
+
couponCode: response.form?.couponCode?.value || '',
|
|
431
|
+
publicId: response.public_id,
|
|
432
|
+
skipCheckout: response.skipCheckout,
|
|
433
|
+
koreaNotification: response.form.korea_limits_instruction,
|
|
434
|
+
isCheckout: response.isCheckout,
|
|
435
|
+
categories: response.categories,
|
|
436
|
+
hasFatalErrors: response.textAll?.fatal,
|
|
437
|
+
userSession: response.userSession,
|
|
438
|
+
statusText: response.status?.statusData?.stateText ?? null,
|
|
439
|
+
country: response.country ? response.country.iso : null,
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
const initializeResponseFactoryToken = new InjectionToken('InitializeResponse');
|
|
445
|
+
const initializeResponseFactoryProvider = {
|
|
446
|
+
provide: initializeResponseFactoryToken,
|
|
447
|
+
useValue: (...args) => new InitializeResponse(...args),
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
class InitializeService {
|
|
451
|
+
constructor(responseFactory, secureApi, settingsService, countryService) {
|
|
452
|
+
this.responseFactory = responseFactory;
|
|
453
|
+
this.secureApi = secureApi;
|
|
454
|
+
this.settingsService = settingsService;
|
|
455
|
+
this.countryService = countryService;
|
|
456
|
+
this.apiRoute = 'directpayment';
|
|
457
|
+
}
|
|
458
|
+
async request(config) {
|
|
459
|
+
const requestParams = {
|
|
460
|
+
access_token: this.settingsService.token,
|
|
461
|
+
pid: String(config.paymentMethodId),
|
|
462
|
+
country: this.countryService.getCountry(),
|
|
463
|
+
returnUrl: config.returnUrl,
|
|
464
|
+
};
|
|
465
|
+
return lastValueFrom(this.secureApi
|
|
466
|
+
.post(this.apiRoute, new URLSearchParams({ ...requestParams }), {
|
|
467
|
+
headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
|
|
468
|
+
responseType: 'json',
|
|
469
|
+
})
|
|
470
|
+
.pipe(map((response) => this.responseFactory(response)))).catch((error) => {
|
|
471
|
+
throw new ResponseError(error.message);
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
InitializeService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, deps: [{ token: initializeResponseFactoryToken }, { token: SecureApiClient }, { token: SettingsService }, { token: CountryService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
476
|
+
InitializeService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, providedIn: 'root' });
|
|
477
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, decorators: [{
|
|
478
|
+
type: Injectable,
|
|
479
|
+
args: [{
|
|
480
|
+
providedIn: 'root',
|
|
481
|
+
}]
|
|
482
|
+
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
483
|
+
type: Inject,
|
|
484
|
+
args: [initializeResponseFactoryToken]
|
|
485
|
+
}] }, { type: SecureApiClient }, { type: SettingsService }, { type: CountryService }]; } });
|
|
486
|
+
|
|
487
|
+
class XpsApiPartRequest {
|
|
488
|
+
addXpsParameters(parameters) {
|
|
489
|
+
for (const key in parameters) {
|
|
490
|
+
this[`xps_${key}`] = parameters[key];
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
class TokenError extends AppError {
|
|
496
|
+
constructor() {
|
|
497
|
+
super('XPS API needs token.');
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
class SubmitRequest extends XpsApiPartRequest {
|
|
502
|
+
constructor(parameters) {
|
|
503
|
+
super();
|
|
504
|
+
const { token, dfpHash } = parameters;
|
|
505
|
+
if (token === null) {
|
|
506
|
+
throw new TokenError();
|
|
507
|
+
}
|
|
508
|
+
this.access_token = token;
|
|
509
|
+
if (dfpHash) {
|
|
510
|
+
this.xps_dfp_hash = dfpHash;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
const submitRequestFactoryToken = new InjectionToken('SubmitRequest');
|
|
516
|
+
const submitRequestFactoryProvider = {
|
|
517
|
+
provide: submitRequestFactoryToken,
|
|
518
|
+
useValue: (...args) => new SubmitRequest(...args),
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
var XpsCommand;
|
|
522
|
+
(function (XpsCommand) {
|
|
523
|
+
XpsCommand["form"] = "form";
|
|
524
|
+
XpsCommand["check"] = "check";
|
|
525
|
+
XpsCommand["status"] = "status";
|
|
526
|
+
XpsCommand["checkout"] = "checkout";
|
|
527
|
+
XpsCommand["account"] = "account";
|
|
528
|
+
XpsCommand["create"] = "create";
|
|
529
|
+
})(XpsCommand || (XpsCommand = {}));
|
|
530
|
+
|
|
531
|
+
var FieldNames;
|
|
532
|
+
(function (FieldNames) {
|
|
533
|
+
FieldNames["address1"] = "address1";
|
|
534
|
+
FieldNames["address2"] = "address2";
|
|
535
|
+
FieldNames["address"] = "address";
|
|
536
|
+
FieldNames["allowRecurrentSubscription"] = "allowRecurrentSubscription";
|
|
537
|
+
FieldNames["allowSubscription"] = "allowSubscription";
|
|
538
|
+
FieldNames["apt"] = "apt";
|
|
539
|
+
FieldNames["availableCardTypes"] = "available_card_types";
|
|
540
|
+
FieldNames["bank"] = "bank";
|
|
541
|
+
FieldNames["birthDate"] = "birth_date";
|
|
542
|
+
FieldNames["cardMonth"] = "card_month";
|
|
543
|
+
FieldNames["cardYear"] = "card_year";
|
|
544
|
+
FieldNames["cardNumber"] = "card_number";
|
|
545
|
+
FieldNames["cardholdername"] = "cardholdername";
|
|
546
|
+
FieldNames["city"] = "city";
|
|
547
|
+
FieldNames["couponCode"] = "couponCode";
|
|
548
|
+
FieldNames["cpfName"] = "cpf_name";
|
|
549
|
+
FieldNames["cpfNumber"] = "cpf_number";
|
|
550
|
+
FieldNames["cvv"] = "cvv";
|
|
551
|
+
FieldNames["description"] = "description";
|
|
552
|
+
FieldNames["email"] = "email";
|
|
553
|
+
FieldNames["psEmail"] = "psEmail";
|
|
554
|
+
FieldNames["euCheck"] = "eu_check";
|
|
555
|
+
FieldNames["extraCvv"] = "extra_cvv";
|
|
556
|
+
FieldNames["extraCardNumber"] = "extra_card_number";
|
|
557
|
+
FieldNames["extraCardType"] = "extra_card_type";
|
|
558
|
+
FieldNames["fName"] = "f_name";
|
|
559
|
+
FieldNames["installments"] = "installments";
|
|
560
|
+
FieldNames["lName"] = "l_name";
|
|
561
|
+
FieldNames["needInstallments"] = "needInstallments";
|
|
562
|
+
FieldNames["personId"] = "person_id";
|
|
563
|
+
FieldNames["personIdAr"] = "person_id_ar";
|
|
564
|
+
FieldNames["personIdCo"] = "person_id_co";
|
|
565
|
+
FieldNames["phone"] = "phone";
|
|
566
|
+
FieldNames["purchaseDescription"] = "purchaseDescription";
|
|
567
|
+
FieldNames["recurrentType"] = "recurrent_type";
|
|
568
|
+
FieldNames["rockstarTaxes"] = "rockstar_taxes";
|
|
569
|
+
FieldNames["state"] = "state";
|
|
570
|
+
FieldNames["street"] = "street";
|
|
571
|
+
FieldNames["streetNumber"] = "street_number";
|
|
572
|
+
FieldNames["take2Taxes"] = "take2_taxes";
|
|
573
|
+
FieldNames["termsAndConditions"] = "termsAndConditions";
|
|
574
|
+
FieldNames["termsAndConditionsAtariPp"] = "termsAndConditionsAtariPP";
|
|
575
|
+
FieldNames["termsAndConditionsAtariTc"] = "termsAndConditionsAtariTC";
|
|
576
|
+
FieldNames["termsAndConditionsHtcEula"] = "termsAndConditionsHtcEula";
|
|
577
|
+
FieldNames["termsAndConditionsRobloxEula"] = "termsAndConditionsRobloxEula";
|
|
578
|
+
FieldNames["termsAndConditionsRolandEula"] = "termsAndConditionsRolandEula";
|
|
579
|
+
FieldNames["termsAndConditionsDeusLoVultEula"] = "termsAndConditionsDeusLoVultEula";
|
|
580
|
+
FieldNames["termsAndConditionsOnzenga"] = "termsAndConditionsOnzenga";
|
|
581
|
+
FieldNames["xsollaTipsAmount"] = "xsollaTipsAmount";
|
|
582
|
+
FieldNames["zip"] = "zip";
|
|
583
|
+
FieldNames["allowSave"] = "allowSave";
|
|
584
|
+
FieldNames["koreaLimitsInstruction"] = "korea_limits_instruction";
|
|
585
|
+
FieldNames["tokenApplePay"] = "token_applepay";
|
|
586
|
+
FieldNames["fixInvoice"] = "fix_invoice";
|
|
587
|
+
FieldNames["fixPid"] = "fix_pid";
|
|
588
|
+
FieldNames["signature"] = "signature";
|
|
589
|
+
FieldNames["qr"] = "qr";
|
|
590
|
+
FieldNames["sum"] = "sum";
|
|
591
|
+
FieldNames["out"] = "out";
|
|
592
|
+
FieldNames["tinkoffDisclaimer"] = "ps.tinkoff.disclaimer";
|
|
593
|
+
})(FieldNames || (FieldNames = {}));
|
|
594
|
+
|
|
595
|
+
class SubmitResponse {
|
|
596
|
+
constructor(parameters, responseNumber = 0) {
|
|
597
|
+
this.responseNumber = responseNumber;
|
|
598
|
+
/* Todo split into properties */
|
|
599
|
+
this.parameters = parameters;
|
|
600
|
+
this.fields = Object.keys(parameters.form).map((key) => parameters.form[key]);
|
|
601
|
+
if (parameters.onlineBanking) {
|
|
602
|
+
this.onlineBanking = {
|
|
603
|
+
url: parameters.onlineBanking.value,
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
this.isNeedRedirect =
|
|
607
|
+
parameters.currentCommand === XpsCommand.account ||
|
|
608
|
+
(parameters.currentCommand === XpsCommand.checkout &&
|
|
609
|
+
Boolean(parameters.checkout));
|
|
610
|
+
this.buyData = parameters.buyData;
|
|
611
|
+
this.fixInvoice = this.fields.find((field) => field.name === FieldNames.fixInvoice)?.value;
|
|
612
|
+
this.signature = this.fields.find((field) => field.name === FieldNames.signature)?.value;
|
|
613
|
+
this.hasFatalErrors = parameters.textAll?.fatal;
|
|
614
|
+
this.userSession = parameters.userSession;
|
|
615
|
+
this.pid = parameters.pid;
|
|
616
|
+
this.errors = parameters.errors;
|
|
617
|
+
this.summary = parameters.summary;
|
|
618
|
+
this.title = parameters.title;
|
|
619
|
+
this.currentCommand = parameters.currentCommand;
|
|
620
|
+
this.messages = parameters.messages;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
const submitResponseFactoryToken = new InjectionToken('SubmitResponse');
|
|
625
|
+
const submitResponseFactoryProvider = {
|
|
626
|
+
provide: submitResponseFactoryToken,
|
|
627
|
+
useValue: (...args) => new SubmitResponse(...args),
|
|
628
|
+
};
|
|
629
|
+
|
|
630
|
+
class TerminalError extends AppError {
|
|
631
|
+
constructor(message, code) {
|
|
632
|
+
super(message);
|
|
633
|
+
this.code = code;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
class DefaultTerminalError extends TerminalError {
|
|
638
|
+
constructor() {
|
|
639
|
+
const message = `It's not you, it's us, but we can help. Please contact our customer support.`;
|
|
640
|
+
super(message, '1000-0002');
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
class DeviceFingerPrintService {
|
|
645
|
+
constructor(secureApi, settingsService, window) {
|
|
646
|
+
this.secureApi = secureApi;
|
|
647
|
+
this.settingsService = settingsService;
|
|
648
|
+
this.window = window;
|
|
649
|
+
this.apiRoute = 'dfp';
|
|
650
|
+
this.fingerprintApiUrl = 'https://afs.xsolla.com/dfp/api/v1/';
|
|
651
|
+
}
|
|
652
|
+
async init() {
|
|
653
|
+
if (!this.settingsService.isInitialized) {
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
this.fingerprintJs = await this.loadFingerprintJs();
|
|
657
|
+
this.hash = await this.buildHash();
|
|
658
|
+
this.antifraudFingerprintLibrary =
|
|
659
|
+
await this.loadAntifraudFingerprintLibrary();
|
|
660
|
+
}
|
|
661
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
662
|
+
async getHash() {
|
|
663
|
+
return this.hash;
|
|
664
|
+
}
|
|
665
|
+
async loadFingerprintJs() {
|
|
666
|
+
const { default: library, murmurX64Hash128: getHash } = await import('@fingerprintjs/fingerprintjs');
|
|
667
|
+
return { library, getHash };
|
|
668
|
+
}
|
|
669
|
+
async loadAntifraudFingerprintLibrary() {
|
|
670
|
+
const library = await import('@xsolla/antifraud-fingerprint');
|
|
671
|
+
return library.default;
|
|
672
|
+
}
|
|
673
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
674
|
+
async makeAntifraudFingerprint() {
|
|
675
|
+
if (!this.settingsService.token) {
|
|
676
|
+
return null;
|
|
677
|
+
}
|
|
678
|
+
const antifraudFingerprint = this.antifraudFingerprintLibrary;
|
|
679
|
+
try {
|
|
680
|
+
return new antifraudFingerprint({
|
|
681
|
+
api: {
|
|
682
|
+
url: this.fingerprintApiUrl,
|
|
683
|
+
token: this.settingsService.token,
|
|
684
|
+
timeout: 3000,
|
|
685
|
+
},
|
|
686
|
+
retry: {
|
|
687
|
+
num: 1,
|
|
688
|
+
timeout: 500,
|
|
689
|
+
},
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
catch (error) {
|
|
693
|
+
return null;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
/**
|
|
697
|
+
*Загружаем библиотеку, генерируем данные,
|
|
698
|
+
*хешируем с помощью BASE64 и отправляем на бэкенд,
|
|
699
|
+
*в ответ получаем dfp_hash.
|
|
700
|
+
**/
|
|
701
|
+
async buildHash() {
|
|
702
|
+
const fingerPrintData = await this.generate();
|
|
703
|
+
const hash = await this.send(fingerPrintData).catch(() => {
|
|
704
|
+
return null;
|
|
705
|
+
});
|
|
706
|
+
return JSON.stringify(hash);
|
|
707
|
+
}
|
|
708
|
+
/**
|
|
709
|
+
*Новая версия библиотеки содержит не все компоненты, некоторые приходится имплементировать самостоятельно
|
|
710
|
+
**/
|
|
711
|
+
getHasLiedResolution() {
|
|
712
|
+
const { screen } = this.window;
|
|
713
|
+
return (screen.width < screen.availWidth || screen.height < screen.availHeight);
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
*Бэкенд заточен под конкретные поля, которые необходимо смапить.
|
|
717
|
+
**/
|
|
718
|
+
getComponents(components) {
|
|
719
|
+
return {
|
|
720
|
+
user_agent: navigator.userAgent,
|
|
721
|
+
language: components.languages.value?.shift()?.shift() ?? '',
|
|
722
|
+
color_depth: components.colorDepth.value,
|
|
723
|
+
device_memory: components.deviceMemory.value,
|
|
724
|
+
hardware_concurrency: components.hardwareConcurrency.value,
|
|
725
|
+
resolution: components.screenResolution.value,
|
|
726
|
+
available_resolution: components.screenResolution.value,
|
|
727
|
+
timezone_offset: new Date().getTimezoneOffset(),
|
|
728
|
+
session_storage: components.sessionStorage.value ? 1 : 0,
|
|
729
|
+
local_storage: components.localStorage.value ? 1 : 0,
|
|
730
|
+
indexed_db: components.indexedDB.value ? 1 : 0,
|
|
731
|
+
open_database: components.openDatabase.value ? 1 : 0,
|
|
732
|
+
navigator_platform: components.platform.value,
|
|
733
|
+
regular_plugins: components.plugins.value?.map((plugin) => plugin.name) ?? [],
|
|
734
|
+
canvas: components.canvas.value?.text,
|
|
735
|
+
webgl: components.canvas.value?.text,
|
|
736
|
+
webgl_vendor: components.vendor.value,
|
|
737
|
+
has_lied_resolution: this.getHasLiedResolution(),
|
|
738
|
+
touch_support: Object.values(components.touchSupport.value ?? {}),
|
|
739
|
+
js_fonts: components.fonts.value,
|
|
740
|
+
};
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Получаем данные dfp с помощью FingerprintJS, мапим необходимые поля, добавляем хэш
|
|
744
|
+
**/
|
|
745
|
+
async generate() {
|
|
746
|
+
const { library, getHash } = this.fingerprintJs;
|
|
747
|
+
const fingerprint = await library.load();
|
|
748
|
+
const commonFingerPrintData = await fingerprint.get();
|
|
749
|
+
const fingerPrintData = this.getComponents(commonFingerPrintData.components);
|
|
750
|
+
fingerPrintData.hash = getHash(JSON.stringify(fingerPrintData));
|
|
751
|
+
return fingerPrintData;
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Отправка dfp на сервер, в ответ получаем dfp_hash
|
|
755
|
+
**/
|
|
756
|
+
async send(fingerPrintData) {
|
|
757
|
+
const token = this.settingsService.token;
|
|
758
|
+
if (token === null) {
|
|
759
|
+
throw new DefaultTerminalError();
|
|
760
|
+
}
|
|
761
|
+
const requestBody = {
|
|
762
|
+
access_token: token,
|
|
763
|
+
'dfp[200]': '',
|
|
764
|
+
};
|
|
765
|
+
requestBody['dfp[200]'] = btoa(encodeURIComponent(JSON.stringify(fingerPrintData)));
|
|
766
|
+
return lastValueFrom(this.secureApi.post(this.apiRoute, new URLSearchParams(requestBody), {
|
|
767
|
+
headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
|
|
768
|
+
responseType: 'json',
|
|
769
|
+
}))
|
|
770
|
+
.then((response) => {
|
|
771
|
+
return response.dfp_hash;
|
|
772
|
+
})
|
|
773
|
+
.then(async (hash) => {
|
|
774
|
+
const fingerprint = await this.makeAntifraudFingerprint();
|
|
775
|
+
if (!fingerprint) {
|
|
776
|
+
return null;
|
|
777
|
+
}
|
|
778
|
+
await fingerprint
|
|
779
|
+
?.dispatch(hash['200'])
|
|
780
|
+
.catch((err) => console.log(err));
|
|
781
|
+
const afsHash = await fingerprint.hash();
|
|
782
|
+
return { '301': afsHash, ...hash };
|
|
783
|
+
})
|
|
784
|
+
.catch((error) => {
|
|
785
|
+
const response = error.getHttpErrorData().response;
|
|
786
|
+
throw new TerminalError(response.data?.errors[0]?.message ?? '', response.data?.errors[0]?.support_code ?? '');
|
|
787
|
+
});
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
DeviceFingerPrintService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: DeviceFingerPrintService, deps: [{ token: SecureApiClient }, { token: SettingsService }, { token: windowToken }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
791
|
+
DeviceFingerPrintService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: DeviceFingerPrintService, providedIn: 'root' });
|
|
792
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: DeviceFingerPrintService, decorators: [{
|
|
793
|
+
type: Injectable,
|
|
794
|
+
args: [{
|
|
795
|
+
providedIn: 'root',
|
|
796
|
+
}]
|
|
797
|
+
}], ctorParameters: function () { return [{ type: SecureApiClient }, { type: SettingsService }, { type: undefined, decorators: [{
|
|
798
|
+
type: Inject,
|
|
799
|
+
args: [windowToken]
|
|
800
|
+
}] }]; } });
|
|
801
|
+
|
|
802
|
+
class SubmitService {
|
|
803
|
+
constructor(requestFactory, responseFactory, settingsService, deviceFingerPrintService, secureApi) {
|
|
804
|
+
this.requestFactory = requestFactory;
|
|
805
|
+
this.responseFactory = responseFactory;
|
|
806
|
+
this.settingsService = settingsService;
|
|
807
|
+
this.deviceFingerPrintService = deviceFingerPrintService;
|
|
808
|
+
this.secureApi = secureApi;
|
|
809
|
+
this.directPaymentApiRoute = 'directpayment';
|
|
810
|
+
}
|
|
811
|
+
// NB: Never add 'async' statement for this method!
|
|
812
|
+
// 'Async' statement wraps current promise into another.
|
|
813
|
+
// In this way two promises become unequal, that can broke XPS API requests logic.
|
|
814
|
+
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
|
815
|
+
request(fields, form) {
|
|
816
|
+
const responsePromise = this.deviceFingerPrintService
|
|
817
|
+
.getHash()
|
|
818
|
+
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
|
819
|
+
.then((dfpHash) => {
|
|
820
|
+
const request = this.requestFactory({
|
|
821
|
+
token: this.settingsService.token,
|
|
822
|
+
fields,
|
|
823
|
+
form,
|
|
824
|
+
dfpHash,
|
|
825
|
+
});
|
|
826
|
+
return lastValueFrom(this.secureApi.post(this.directPaymentApiRoute, request, {
|
|
827
|
+
headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
|
|
828
|
+
responseType: 'json',
|
|
829
|
+
}))
|
|
830
|
+
.then((response) => this.responseFactory(response))
|
|
831
|
+
.catch((error) => {
|
|
832
|
+
throw new ResponseError(error.message);
|
|
833
|
+
});
|
|
834
|
+
});
|
|
835
|
+
return responsePromise;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
SubmitService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SubmitService, deps: [{ token: submitRequestFactoryToken }, { token: submitResponseFactoryToken }, { token: SettingsService }, { token: DeviceFingerPrintService }, { token: SecureApiClient }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
839
|
+
SubmitService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SubmitService, providedIn: 'root' });
|
|
840
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SubmitService, decorators: [{
|
|
841
|
+
type: Injectable,
|
|
842
|
+
args: [{ providedIn: 'root' }]
|
|
843
|
+
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
844
|
+
type: Inject,
|
|
845
|
+
args: [submitRequestFactoryToken]
|
|
846
|
+
}] }, { type: undefined, decorators: [{
|
|
847
|
+
type: Inject,
|
|
848
|
+
args: [submitResponseFactoryToken]
|
|
849
|
+
}] }, { type: SettingsService }, { type: DeviceFingerPrintService }, { type: SecureApiClient }]; } });
|
|
850
|
+
|
|
851
|
+
class XpsRequest {
|
|
852
|
+
addXpsParameters(parameters) {
|
|
853
|
+
for (const key in parameters) {
|
|
854
|
+
this[`xps_${key}`] = parameters[key];
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
860
|
+
class SyncRequest extends XpsRequest {
|
|
861
|
+
constructor(parameters) {
|
|
862
|
+
super();
|
|
863
|
+
this.xps_fix_command = 'calculate';
|
|
864
|
+
this.access_token = parameters.token;
|
|
865
|
+
const fieldsValues = this.getFieldsValues(parameters.changedField, parameters.fields, parameters.form);
|
|
866
|
+
this.addXpsParameters({
|
|
867
|
+
...fieldsValues,
|
|
868
|
+
change_element: parameters.changedField.name,
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
getFieldsValues(changedField, fields, form) {
|
|
872
|
+
const fieldsMap = this.getFieldsMap(fields);
|
|
873
|
+
return changedField?.javascript?.change.params.reduce((xpsParams, fieldName) => {
|
|
874
|
+
const formControl = form.get(fieldName);
|
|
875
|
+
const field = fieldsMap.get(fieldName);
|
|
876
|
+
if (formControl || field) {
|
|
877
|
+
xpsParams[fieldName] = formControl?.value ?? field?.value;
|
|
878
|
+
}
|
|
879
|
+
return xpsParams;
|
|
880
|
+
}, {});
|
|
881
|
+
}
|
|
882
|
+
getFieldsMap(fields) {
|
|
883
|
+
const map = new Map();
|
|
884
|
+
fields.forEach((field) => map.set(field.name, field));
|
|
885
|
+
return map;
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
const syncRequestFactoryToken = new InjectionToken('SyncRequest');
|
|
890
|
+
const syncRequestFactoryProvider = {
|
|
891
|
+
provide: syncRequestFactoryToken,
|
|
892
|
+
useValue: (...args) => new SyncRequest(...args),
|
|
893
|
+
};
|
|
894
|
+
|
|
895
|
+
class SyncResponse {
|
|
896
|
+
constructor(changedField, response) {
|
|
897
|
+
const fieldError = response?.errors?.find((error) => error.element_name === changedField.name);
|
|
898
|
+
if (fieldError) {
|
|
899
|
+
this.rewritableError = {
|
|
900
|
+
code: fieldError.code,
|
|
901
|
+
message: fieldError.message,
|
|
902
|
+
};
|
|
903
|
+
}
|
|
904
|
+
this.fields = Object.keys(response.form).map((key) => response.form[key]);
|
|
905
|
+
this.parameters = response;
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
const syncResponseFactoryToken = new InjectionToken('SyncResponse');
|
|
910
|
+
const syncResponseFactoryProvider = {
|
|
911
|
+
provide: syncResponseFactoryToken,
|
|
912
|
+
useValue: (...args) => new SyncResponse(...args),
|
|
913
|
+
};
|
|
914
|
+
|
|
915
|
+
class SyncService {
|
|
916
|
+
constructor(requestFactory, responseFactory, secureApi, settingsService) {
|
|
917
|
+
this.requestFactory = requestFactory;
|
|
918
|
+
this.responseFactory = responseFactory;
|
|
919
|
+
this.secureApi = secureApi;
|
|
920
|
+
this.settingsService = settingsService;
|
|
921
|
+
this.apiRoute = 'directpayment';
|
|
922
|
+
this.prevFieldSyncStates = {};
|
|
923
|
+
this.form = new UntypedFormGroup({});
|
|
924
|
+
this.fields = [];
|
|
925
|
+
}
|
|
926
|
+
setup(form, fields) {
|
|
927
|
+
this.reset();
|
|
928
|
+
this.form = form;
|
|
929
|
+
this.fields = fields;
|
|
930
|
+
}
|
|
931
|
+
reset() {
|
|
932
|
+
this.prevFieldSyncStates = {};
|
|
933
|
+
this.form = new UntypedFormGroup({});
|
|
934
|
+
this.fields = [];
|
|
935
|
+
}
|
|
936
|
+
async validate(field) {
|
|
937
|
+
if (!this.isReadyField(field)) {
|
|
938
|
+
return Promise.resolve(null);
|
|
939
|
+
}
|
|
940
|
+
const control = this.form.get(field.name);
|
|
941
|
+
const value = control?.value;
|
|
942
|
+
const prevFieldState = this.getPrevFieldSyncState(field);
|
|
943
|
+
const isInitialValue = value === field.value && !prevFieldState;
|
|
944
|
+
if (isInitialValue) {
|
|
945
|
+
return Promise.resolve(null);
|
|
946
|
+
}
|
|
947
|
+
if (prevFieldState && value === prevFieldState.value) {
|
|
948
|
+
return Promise.resolve(prevFieldState.result);
|
|
949
|
+
}
|
|
950
|
+
const requestPromise = this.request(field);
|
|
951
|
+
this.setPrevFieldSyncState(field, value, requestPromise);
|
|
952
|
+
return requestPromise.then((response) => {
|
|
953
|
+
return response.rewritableError ?? null;
|
|
954
|
+
});
|
|
955
|
+
}
|
|
956
|
+
async request(field) {
|
|
957
|
+
const requestParams = this.requestFactory({
|
|
958
|
+
token: this.settingsService.token,
|
|
959
|
+
changedField: field,
|
|
960
|
+
fields: this.fields,
|
|
961
|
+
form: this.form,
|
|
962
|
+
});
|
|
963
|
+
return lastValueFrom(this.secureApi.post(this.apiRoute, new URLSearchParams(requestParams), {
|
|
964
|
+
headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
|
|
965
|
+
responseType: 'json',
|
|
966
|
+
})).then((response) => {
|
|
967
|
+
return this.responseFactory(field, response);
|
|
968
|
+
});
|
|
969
|
+
}
|
|
970
|
+
isReadyField(field) {
|
|
971
|
+
const isSyncEnabled = !!field.javascript?.change;
|
|
972
|
+
const isExistsInForm = !!this.form?.get(field.name);
|
|
973
|
+
return isSyncEnabled && isExistsInForm;
|
|
974
|
+
}
|
|
975
|
+
getPrevFieldSyncState(field) {
|
|
976
|
+
return this.prevFieldSyncStates[field.name];
|
|
977
|
+
}
|
|
978
|
+
setPrevFieldSyncState(field, value, result) {
|
|
979
|
+
this.prevFieldSyncStates[field.name] = { value, result };
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
SyncService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SyncService, deps: [{ token: syncRequestFactoryToken }, { token: syncResponseFactoryToken }, { token: SecureApiClient }, { token: SettingsService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
983
|
+
SyncService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SyncService, providedIn: 'root' });
|
|
984
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: SyncService, decorators: [{
|
|
985
|
+
type: Injectable,
|
|
986
|
+
args: [{
|
|
987
|
+
providedIn: 'root',
|
|
988
|
+
}]
|
|
989
|
+
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
990
|
+
type: Inject,
|
|
991
|
+
args: [syncRequestFactoryToken]
|
|
992
|
+
}] }, { type: undefined, decorators: [{
|
|
993
|
+
type: Inject,
|
|
994
|
+
args: [syncResponseFactoryToken]
|
|
995
|
+
}] }, { type: SecureApiClient }, { type: SettingsService }]; } });
|
|
996
|
+
|
|
997
|
+
class ControlConfig {
|
|
998
|
+
constructor() {
|
|
999
|
+
this.shouldHideUserInput = false;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
class TextControlConfig extends ControlConfig {
|
|
1004
|
+
constructor() {
|
|
1005
|
+
super(...arguments);
|
|
1006
|
+
this.controlType = 'text';
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
function convert(validator, message) {
|
|
1011
|
+
return (control) => {
|
|
1012
|
+
const errors = validator(control);
|
|
1013
|
+
if (!errors) {
|
|
1014
|
+
return errors;
|
|
1015
|
+
}
|
|
1016
|
+
const firstErrorKey = Object.keys(errors)[0];
|
|
1017
|
+
let error = errors[firstErrorKey];
|
|
1018
|
+
error = typeof error === 'object' && error !== null ? error : {};
|
|
1019
|
+
const rewritableError = { ...error };
|
|
1020
|
+
rewritableError.message = message;
|
|
1021
|
+
if (error[firstErrorKey] != null) {
|
|
1022
|
+
rewritableError.value = error[firstErrorKey];
|
|
1023
|
+
}
|
|
1024
|
+
if (rewritableError.requiredLength) {
|
|
1025
|
+
rewritableError.number = rewritableError.requiredLength;
|
|
1026
|
+
}
|
|
1027
|
+
errors.rewritableError = rewritableError;
|
|
1028
|
+
return errors;
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
const emailRegexp = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i; // eslint-disable-line
|
|
1033
|
+
function emailValidator() {
|
|
1034
|
+
return convert(Validators.pattern(emailRegexp), 'Enter a valid email');
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
function requiredValidator() {
|
|
1038
|
+
return convert(Validators.required, 'Required');
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
class Converter {
|
|
1042
|
+
constructor(syncService) {
|
|
1043
|
+
this.syncService = syncService;
|
|
1044
|
+
}
|
|
1045
|
+
convertToConfig(field, formState) {
|
|
1046
|
+
const config = this.createControlConfig(field, formState);
|
|
1047
|
+
if (formState?.disabled) {
|
|
1048
|
+
config.disabled = true;
|
|
1049
|
+
}
|
|
1050
|
+
return config;
|
|
1051
|
+
}
|
|
1052
|
+
convertToFormControl(field) {
|
|
1053
|
+
return new UntypedFormControl(this.getValue(field), this.getValidators(field), this.getAsyncValidators(field));
|
|
1054
|
+
}
|
|
1055
|
+
getValidators(field) {
|
|
1056
|
+
const validators = [];
|
|
1057
|
+
if (field.isMandatory === "1" /* XpsBoolean.true */) {
|
|
1058
|
+
validators.push(requiredValidator());
|
|
1059
|
+
}
|
|
1060
|
+
if (field.regex) {
|
|
1061
|
+
const match = /^\/(.*)\/([gim]*)$/.exec(field.regex);
|
|
1062
|
+
if (match) {
|
|
1063
|
+
const pattern = new RegExp(match[1], match[2]);
|
|
1064
|
+
const errorMessage = field.validation_error_msg
|
|
1065
|
+
? field.validation_error_msg
|
|
1066
|
+
: 'Enter valid data';
|
|
1067
|
+
validators.push(convert(Validators.pattern(pattern), errorMessage));
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
return validators;
|
|
1071
|
+
}
|
|
1072
|
+
getAsyncValidators(field) {
|
|
1073
|
+
return async () => this.syncService.validate(field);
|
|
1074
|
+
}
|
|
1075
|
+
createDefaultControlConfig(controlConfigClass, field) {
|
|
1076
|
+
const config = new controlConfigClass();
|
|
1077
|
+
this.copyCommonOptions(config, field);
|
|
1078
|
+
return config;
|
|
1079
|
+
}
|
|
1080
|
+
getValue(field) {
|
|
1081
|
+
return field.value;
|
|
1082
|
+
}
|
|
1083
|
+
getDataType() {
|
|
1084
|
+
return 'text';
|
|
1085
|
+
}
|
|
1086
|
+
getAutocomplete() {
|
|
1087
|
+
return 'off';
|
|
1088
|
+
}
|
|
1089
|
+
shouldHideUserInput() {
|
|
1090
|
+
return false;
|
|
1091
|
+
}
|
|
1092
|
+
getCommonControlConfig(field) {
|
|
1093
|
+
return {
|
|
1094
|
+
name: field.name,
|
|
1095
|
+
title: field.title,
|
|
1096
|
+
labelHint: field.label_hint,
|
|
1097
|
+
dataType: this.getDataType(),
|
|
1098
|
+
readonly: field.isReadonly === "1" /* XpsBoolean.true */,
|
|
1099
|
+
placeholder: field.example,
|
|
1100
|
+
autocomplete: this.getAutocomplete(),
|
|
1101
|
+
};
|
|
1102
|
+
}
|
|
1103
|
+
copyCommonOptions(target, field) {
|
|
1104
|
+
const commonControlConfig = this.getCommonControlConfig(field);
|
|
1105
|
+
Object.keys(commonControlConfig).forEach((sourceKey) => {
|
|
1106
|
+
if (!(sourceKey in target)) {
|
|
1107
|
+
target[sourceKey] = commonControlConfig[sourceKey];
|
|
1108
|
+
}
|
|
1109
|
+
});
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
class EmailConverter extends Converter {
|
|
1114
|
+
constructor(syncService) {
|
|
1115
|
+
super(syncService);
|
|
1116
|
+
}
|
|
1117
|
+
getValidators(field) {
|
|
1118
|
+
return super.getValidators(field).concat([emailValidator()]);
|
|
1119
|
+
}
|
|
1120
|
+
createControlConfig(field) {
|
|
1121
|
+
const config = this.createDefaultControlConfig(TextControlConfig, field);
|
|
1122
|
+
config.autocomplete = 'email';
|
|
1123
|
+
config.icon = 'mail';
|
|
1124
|
+
return config;
|
|
1125
|
+
}
|
|
1126
|
+
getDataType() {
|
|
1127
|
+
return 'email';
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
EmailConverter.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: EmailConverter, deps: [{ token: SyncService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1131
|
+
EmailConverter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: EmailConverter });
|
|
1132
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: EmailConverter, decorators: [{
|
|
1133
|
+
type: Injectable
|
|
1134
|
+
}], ctorParameters: function () { return [{ type: SyncService }]; } });
|
|
1135
|
+
|
|
1136
|
+
const restrictedValueValidator = (restrictedValue) => {
|
|
1137
|
+
return ({ value }) => {
|
|
1138
|
+
return value !== restrictedValue ? null : { valueAllowed: false };
|
|
1139
|
+
};
|
|
1140
|
+
};
|
|
1141
|
+
|
|
1142
|
+
class ZipConverter extends Converter {
|
|
1143
|
+
constructor(syncService, countryService) {
|
|
1144
|
+
super(syncService);
|
|
1145
|
+
this.countryService = countryService;
|
|
1146
|
+
this.minLength = 3;
|
|
1147
|
+
this.maxLength = 10;
|
|
1148
|
+
this.usCountryLength = 5;
|
|
1149
|
+
}
|
|
1150
|
+
get isUsCountry() {
|
|
1151
|
+
return this.countryService.getCountry() === 'US';
|
|
1152
|
+
}
|
|
1153
|
+
getValidators(field) {
|
|
1154
|
+
const minLength = this.isUsCountry ? this.usCountryLength : this.minLength;
|
|
1155
|
+
const maxLength = this.isUsCountry ? this.usCountryLength : this.maxLength;
|
|
1156
|
+
const validators = super
|
|
1157
|
+
.getValidators(field)
|
|
1158
|
+
.concat([
|
|
1159
|
+
convert(Validators.minLength(minLength), 'Enter at least ${minLength} characters'),
|
|
1160
|
+
convert(Validators.maxLength(maxLength), 'Enter no more than ${maxLength} characters'),
|
|
1161
|
+
]);
|
|
1162
|
+
if (this.isUsCountry) {
|
|
1163
|
+
validators.push(convert(restrictedValueValidator('00000'), 'Enter a valid ZIP code'));
|
|
1164
|
+
}
|
|
1165
|
+
return validators;
|
|
1166
|
+
}
|
|
1167
|
+
createControlConfig(field) {
|
|
1168
|
+
const config = this.createDefaultControlConfig(TextControlConfig, field);
|
|
1169
|
+
config.icon = 'location';
|
|
1170
|
+
if (this.isUsCountry) {
|
|
1171
|
+
config.maskConfig = {
|
|
1172
|
+
mask: () => new Array(this.usCountryLength).fill('9').join(''),
|
|
1173
|
+
guide: false,
|
|
1174
|
+
unmaskModelValue: true,
|
|
1175
|
+
showMask: true,
|
|
1176
|
+
};
|
|
1177
|
+
config.inputMode = 'numeric';
|
|
1178
|
+
}
|
|
1179
|
+
else {
|
|
1180
|
+
config.maxLength = this.maxLength;
|
|
1181
|
+
}
|
|
1182
|
+
return config;
|
|
1183
|
+
}
|
|
1184
|
+
getAutocomplete() {
|
|
1185
|
+
return 'postal-code';
|
|
1186
|
+
}
|
|
1187
|
+
getDataType() {
|
|
1188
|
+
return 'text';
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
ZipConverter.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ZipConverter, deps: [{ token: SyncService }, { token: CountryService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1192
|
+
ZipConverter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ZipConverter });
|
|
1193
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ZipConverter, decorators: [{
|
|
1194
|
+
type: Injectable
|
|
1195
|
+
}], ctorParameters: function () { return [{ type: SyncService }, { type: CountryService }]; } });
|
|
1196
|
+
|
|
1197
|
+
const convertersMapToken = new InjectionToken('ConvertersTokensMap');
|
|
1198
|
+
const convertersMap = {
|
|
1199
|
+
zip: ZipConverter,
|
|
1200
|
+
email: EmailConverter,
|
|
1201
|
+
};
|
|
1202
|
+
|
|
1203
|
+
class ControlConfigService {
|
|
1204
|
+
constructor(convertersMap, injector) {
|
|
1205
|
+
this.convertersMap = convertersMap;
|
|
1206
|
+
this.injector = injector;
|
|
1207
|
+
}
|
|
1208
|
+
getFormControl(field) {
|
|
1209
|
+
const converter = this.getConverter(field);
|
|
1210
|
+
if (!converter) {
|
|
1211
|
+
return null;
|
|
1212
|
+
}
|
|
1213
|
+
return converter.convertToFormControl(field);
|
|
1214
|
+
}
|
|
1215
|
+
getConverter(field) {
|
|
1216
|
+
if (!field) {
|
|
1217
|
+
return null;
|
|
1218
|
+
}
|
|
1219
|
+
const sanitizedName = field.name.replace(/^fix_/i, '');
|
|
1220
|
+
let converter = this.convertersMap[sanitizedName];
|
|
1221
|
+
if (!converter) {
|
|
1222
|
+
converter = this.convertersMap[field.type];
|
|
1223
|
+
}
|
|
1224
|
+
if (!converter) {
|
|
1225
|
+
return null;
|
|
1226
|
+
}
|
|
1227
|
+
return this.injector.get(converter);
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
ControlConfigService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ControlConfigService, deps: [{ token: convertersMapToken }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1231
|
+
ControlConfigService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ControlConfigService });
|
|
1232
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ControlConfigService, decorators: [{
|
|
1233
|
+
type: Injectable
|
|
1234
|
+
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
1235
|
+
type: Inject,
|
|
1236
|
+
args: [convertersMapToken]
|
|
1237
|
+
}] }, { type: i0.Injector }]; } });
|
|
1238
|
+
|
|
1239
|
+
class FormService {
|
|
1240
|
+
constructor(controlConfigService) {
|
|
1241
|
+
this.controlConfigService = controlConfigService;
|
|
1242
|
+
}
|
|
1243
|
+
createForm(fields) {
|
|
1244
|
+
const controls = this.getVisibleFields(fields).reduce((result, field) => {
|
|
1245
|
+
const formControl = this.controlConfigService.getFormControl(field);
|
|
1246
|
+
if (formControl) {
|
|
1247
|
+
result[field.name] = formControl;
|
|
1248
|
+
}
|
|
1249
|
+
return result;
|
|
1250
|
+
}, {});
|
|
1251
|
+
return new UntypedFormGroup(controls);
|
|
1252
|
+
}
|
|
1253
|
+
getVisibleFields(fields) {
|
|
1254
|
+
return fields.filter(({ isVisible }) => isVisible === "1" /* XpsBoolean.true */);
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
FormService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: FormService, deps: [{ token: ControlConfigService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1258
|
+
FormService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: FormService });
|
|
1259
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: FormService, decorators: [{
|
|
1260
|
+
type: Injectable
|
|
1261
|
+
}], ctorParameters: function () { return [{ type: ControlConfigService }]; } });
|
|
1262
|
+
|
|
1263
|
+
class StatusUpdatedAction {
|
|
1264
|
+
constructor(statusResponse) {
|
|
1265
|
+
this.type = 'status_updated';
|
|
1266
|
+
this.data = {
|
|
1267
|
+
statusState: statusResponse.status.statusState,
|
|
1268
|
+
invoice: statusResponse.status.invoice,
|
|
1269
|
+
isSuccess: statusResponse.status.isSuccess,
|
|
1270
|
+
isCanceled: statusResponse.status.isCanceled,
|
|
1271
|
+
group: statusResponse.status.group,
|
|
1272
|
+
};
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
class XpsApiPart {
|
|
1277
|
+
constructor() {
|
|
1278
|
+
this.response = new BehaviorSubject(null);
|
|
1279
|
+
}
|
|
1280
|
+
get response$() {
|
|
1281
|
+
return this.response
|
|
1282
|
+
.asObservable()
|
|
1283
|
+
.pipe(filter((response) => response !== null));
|
|
1284
|
+
}
|
|
1285
|
+
emitResponse(response) {
|
|
1286
|
+
this.response.next(response);
|
|
1287
|
+
}
|
|
1288
|
+
get currentValue() {
|
|
1289
|
+
return this.response.getValue();
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
1294
|
+
class StatusRequest extends XpsApiPartRequest {
|
|
1295
|
+
constructor(parameters) {
|
|
1296
|
+
super();
|
|
1297
|
+
this.xps_fix_command = 'status';
|
|
1298
|
+
if (parameters.token === null) {
|
|
1299
|
+
throw new TokenError();
|
|
1300
|
+
}
|
|
1301
|
+
this.access_token = parameters.token;
|
|
1302
|
+
this.xps_fix_invoice = parameters.invoice;
|
|
1303
|
+
this.xps_fix_pid = parameters.pid;
|
|
1304
|
+
this.xps_signature = parameters.signature;
|
|
1305
|
+
this.xps_fix_testProject = parameters.testProject;
|
|
1306
|
+
this.xps_fix_testPs = parameters.testPs;
|
|
1307
|
+
this.xps_fix_testXsolla = parameters.testXsolla;
|
|
1308
|
+
this.xps_fix_userReturnStatus = parameters.userReturnStatus;
|
|
1309
|
+
this.xps_locale = parameters.locale;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
const statusRequestFactoryToken = new InjectionToken('StatusRequest');
|
|
1314
|
+
const statusRequestFactoryProvider = {
|
|
1315
|
+
provide: statusRequestFactoryToken,
|
|
1316
|
+
useValue: (...args) => new StatusRequest(...args),
|
|
1317
|
+
};
|
|
1318
|
+
|
|
1319
|
+
var StatusGroups;
|
|
1320
|
+
(function (StatusGroups) {
|
|
1321
|
+
StatusGroups["troubled"] = "troubled";
|
|
1322
|
+
StatusGroups["done"] = "done";
|
|
1323
|
+
StatusGroups["invoice"] = "invoice";
|
|
1324
|
+
})(StatusGroups || (StatusGroups = {}));
|
|
1325
|
+
|
|
1326
|
+
var StatusEnum;
|
|
1327
|
+
(function (StatusEnum) {
|
|
1328
|
+
StatusEnum["created"] = "created";
|
|
1329
|
+
StatusEnum["awaiting"] = "awaiting";
|
|
1330
|
+
StatusEnum["processing"] = "processing";
|
|
1331
|
+
StatusEnum["authorized"] = "authorized";
|
|
1332
|
+
StatusEnum["held"] = "held";
|
|
1333
|
+
StatusEnum["done"] = "done";
|
|
1334
|
+
StatusEnum["error"] = "error";
|
|
1335
|
+
StatusEnum["canceled"] = "canceled";
|
|
1336
|
+
})(StatusEnum || (StatusEnum = {}));
|
|
1337
|
+
|
|
1338
|
+
class StatusResponse {
|
|
1339
|
+
constructor(parameters) {
|
|
1340
|
+
if (parameters.errors?.[0]) {
|
|
1341
|
+
this.error = {
|
|
1342
|
+
code: parameters.errors[0].code.toString(),
|
|
1343
|
+
message: parameters.errors[0].message,
|
|
1344
|
+
};
|
|
1345
|
+
}
|
|
1346
|
+
if (!parameters.status) {
|
|
1347
|
+
throw new TerminalError(this.error?.message ?? '', this.error?.code.toString() ?? '');
|
|
1348
|
+
}
|
|
1349
|
+
this.status = {
|
|
1350
|
+
statusState: parameters.status.statusData.stateText,
|
|
1351
|
+
email: parameters.status.statusData.email,
|
|
1352
|
+
webSocketUrl: parameters.status.statusData.webSocketChannelUrl,
|
|
1353
|
+
webSocketChannelName: parameters.status.statusData.webSocketChannelName,
|
|
1354
|
+
webSocketClientType: parameters.status.statusData.webSocketClientType,
|
|
1355
|
+
financeInfo: parameters.status.text.info,
|
|
1356
|
+
discount: parameters.status.text.info.discount
|
|
1357
|
+
? Math.abs(Number.parseFloat(parameters.status.text.info.discount?.value ?? ''))
|
|
1358
|
+
: null,
|
|
1359
|
+
isCancelUser: parameters.status.isCancelUser,
|
|
1360
|
+
postMessageStatus: parameters.status.isCancelUser
|
|
1361
|
+
? StatusGroups.troubled
|
|
1362
|
+
: parameters.status.group,
|
|
1363
|
+
virtualCurrencyAmount: parameters.status.statusData.out,
|
|
1364
|
+
backUrlSettings: {
|
|
1365
|
+
backUrl: parameters.status.text.backurl,
|
|
1366
|
+
backUrlAction: parameters.status.text.backurl_action,
|
|
1367
|
+
backUrlCaption: parameters.status.text.backurl_caption,
|
|
1368
|
+
returnRegion: parameters.status.return_region,
|
|
1369
|
+
},
|
|
1370
|
+
additionalBackButton: this.getAdditionalBackButton(parameters.status),
|
|
1371
|
+
group: parameters.status.group,
|
|
1372
|
+
needToCheck: parameters.status.needToCheck,
|
|
1373
|
+
autoRedirect: parameters.status.autoredirect,
|
|
1374
|
+
statusMessage: parameters.status.text.state,
|
|
1375
|
+
userId: parameters.status.statusData.v1,
|
|
1376
|
+
invoice: parameters.status.statusData.invoice,
|
|
1377
|
+
pid: parameters.status.statusData.pid,
|
|
1378
|
+
projectAmount: this.getProjectAmount(parameters.status),
|
|
1379
|
+
titleClass: parameters.status.title_class,
|
|
1380
|
+
paymentCountryIso: parameters.status.statusData.payment_country_iso,
|
|
1381
|
+
order: parameters.status.text.order,
|
|
1382
|
+
};
|
|
1383
|
+
if (parameters.form) {
|
|
1384
|
+
this.status.userReturnStatus = this.getUserReturnStatus(parameters.form);
|
|
1385
|
+
}
|
|
1386
|
+
if (this.status.statusState === StatusEnum.done ||
|
|
1387
|
+
this.status.statusState === StatusEnum.authorized) {
|
|
1388
|
+
this.status.isSuccess = true;
|
|
1389
|
+
}
|
|
1390
|
+
if (this.status.statusState === StatusEnum.canceled ||
|
|
1391
|
+
this.status.isCancelUser) {
|
|
1392
|
+
this.status.isCanceled = true;
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
getUserReturnStatus(form) {
|
|
1396
|
+
const value = form['fix_userReturnStatus']?.value;
|
|
1397
|
+
if (value === 'undefined')
|
|
1398
|
+
return undefined;
|
|
1399
|
+
return value;
|
|
1400
|
+
}
|
|
1401
|
+
getProjectAmount(status) {
|
|
1402
|
+
if (!status.statusData.projectAmount) {
|
|
1403
|
+
return;
|
|
1404
|
+
}
|
|
1405
|
+
const [amount, currency] = status.statusData.projectAmount.split(' ');
|
|
1406
|
+
return {
|
|
1407
|
+
amount,
|
|
1408
|
+
currency,
|
|
1409
|
+
};
|
|
1410
|
+
}
|
|
1411
|
+
getAdditionalBackButton(status) {
|
|
1412
|
+
if (!status.text.is_additional_back_url_enabled) {
|
|
1413
|
+
return {
|
|
1414
|
+
link: '',
|
|
1415
|
+
action: '',
|
|
1416
|
+
label: '',
|
|
1417
|
+
region: '',
|
|
1418
|
+
isEnabled: false,
|
|
1419
|
+
};
|
|
1420
|
+
}
|
|
1421
|
+
return {
|
|
1422
|
+
link: status.text.additional_back_url_link ?? '',
|
|
1423
|
+
action: status.text.additional_back_url_action ?? '',
|
|
1424
|
+
label: status.text.additional_back_url_label ?? '',
|
|
1425
|
+
region: status.additional_button_return_region ?? '',
|
|
1426
|
+
isEnabled: status.text.is_additional_back_url_enabled,
|
|
1427
|
+
};
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
const statusResponseFactoryToken = new InjectionToken('StatusResponse');
|
|
1432
|
+
const statusResponseFactoryProvider = {
|
|
1433
|
+
provide: statusResponseFactoryToken,
|
|
1434
|
+
useValue: (...args) => new StatusResponse(...args),
|
|
1435
|
+
};
|
|
1436
|
+
|
|
1437
|
+
class StatusRequestService extends XpsApiPart {
|
|
1438
|
+
constructor(secureApiClient, settingsService, requestFactory, responseFactory) {
|
|
1439
|
+
super();
|
|
1440
|
+
this.secureApiClient = secureApiClient;
|
|
1441
|
+
this.settingsService = settingsService;
|
|
1442
|
+
this.requestFactory = requestFactory;
|
|
1443
|
+
this.responseFactory = responseFactory;
|
|
1444
|
+
this.apiRoute = 'directpayment';
|
|
1445
|
+
}
|
|
1446
|
+
setRequestParams(params) {
|
|
1447
|
+
this.requestParams = {
|
|
1448
|
+
locale: params.locale,
|
|
1449
|
+
testProject: params.testProject,
|
|
1450
|
+
testPs: params.testPs,
|
|
1451
|
+
testXsolla: params.testXsolla,
|
|
1452
|
+
userReturnStatus: params.userReturnStatus,
|
|
1453
|
+
invoice: params.invoice,
|
|
1454
|
+
pid: params.pid,
|
|
1455
|
+
signature: params.signature,
|
|
1456
|
+
};
|
|
1457
|
+
}
|
|
1458
|
+
request() {
|
|
1459
|
+
const requestParams = this.requestFactory({
|
|
1460
|
+
token: this.settingsService.token,
|
|
1461
|
+
...this.requestParams,
|
|
1462
|
+
});
|
|
1463
|
+
lastValueFrom(this.secureApiClient.post(this.apiRoute, new URLSearchParams(requestParams), {
|
|
1464
|
+
headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
|
|
1465
|
+
responseType: 'json',
|
|
1466
|
+
}))
|
|
1467
|
+
.then((response) => {
|
|
1468
|
+
const statusResponse = this.responseFactory({
|
|
1469
|
+
status: response.status,
|
|
1470
|
+
errors: response.errors,
|
|
1471
|
+
form: response.form,
|
|
1472
|
+
});
|
|
1473
|
+
this.emitResponse(statusResponse);
|
|
1474
|
+
})
|
|
1475
|
+
.catch((e) => {
|
|
1476
|
+
throw new TerminalError(e.message, e.code);
|
|
1477
|
+
});
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
StatusRequestService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: StatusRequestService, deps: [{ token: SecureApiClient }, { token: SettingsService }, { token: statusRequestFactoryToken }, { token: statusResponseFactoryToken }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1481
|
+
StatusRequestService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: StatusRequestService, providedIn: 'root' });
|
|
1482
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: StatusRequestService, decorators: [{
|
|
1483
|
+
type: Injectable,
|
|
1484
|
+
args: [{
|
|
1485
|
+
providedIn: 'root',
|
|
1486
|
+
}]
|
|
1487
|
+
}], ctorParameters: function () { return [{ type: SecureApiClient }, { type: SettingsService }, { type: undefined, decorators: [{
|
|
1488
|
+
type: Inject,
|
|
1489
|
+
args: [statusRequestFactoryToken]
|
|
1490
|
+
}] }, { type: undefined, decorators: [{
|
|
1491
|
+
type: Inject,
|
|
1492
|
+
args: [statusResponseFactoryToken]
|
|
1493
|
+
}] }]; } });
|
|
1494
|
+
|
|
1495
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
1496
|
+
class CheckStatusRequest extends XpsApiPartRequest {
|
|
1497
|
+
constructor(token, invoice) {
|
|
1498
|
+
super();
|
|
1499
|
+
this.xps_fix_command = 'status';
|
|
1500
|
+
this.section = 'getstatus';
|
|
1501
|
+
if (token === null) {
|
|
1502
|
+
throw new TokenError();
|
|
1503
|
+
}
|
|
1504
|
+
this.access_token = token;
|
|
1505
|
+
this.invoice = invoice;
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
const checkStatusRequestFactoryToken = new InjectionToken('CheckStatusRequest');
|
|
1510
|
+
const checkStatusRequestFactoryProvider = {
|
|
1511
|
+
provide: checkStatusRequestFactoryToken,
|
|
1512
|
+
useValue: (...args) => new CheckStatusRequest(...args),
|
|
1513
|
+
};
|
|
1514
|
+
|
|
1515
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
1516
|
+
class CheckStatusResponse {
|
|
1517
|
+
constructor(parameters) {
|
|
1518
|
+
this.status = parameters.status;
|
|
1519
|
+
this.final = parameters.final;
|
|
1520
|
+
this.isPaymentAccountAttached = parameters.isPaymentAccountAttached;
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
const checkStatusResponseFactoryToken = new InjectionToken('CheckStatusResponse');
|
|
1525
|
+
const checkStatusResponseFactoryProvider = {
|
|
1526
|
+
provide: checkStatusResponseFactoryToken,
|
|
1527
|
+
useValue: (...args) => new CheckStatusResponse(...args),
|
|
1528
|
+
};
|
|
1529
|
+
|
|
1530
|
+
class CheckStatusService extends XpsApiPart {
|
|
1531
|
+
constructor(secureApiClient, settingsService, requestFactory, responseFactory) {
|
|
1532
|
+
super();
|
|
1533
|
+
this.secureApiClient = secureApiClient;
|
|
1534
|
+
this.settingsService = settingsService;
|
|
1535
|
+
this.requestFactory = requestFactory;
|
|
1536
|
+
this.responseFactory = responseFactory;
|
|
1537
|
+
this.apiRoute = 'directpayment';
|
|
1538
|
+
}
|
|
1539
|
+
setRequestParams(invoice) {
|
|
1540
|
+
this.invoice = invoice;
|
|
1541
|
+
}
|
|
1542
|
+
request() {
|
|
1543
|
+
const requestParams = this.requestFactory(this.settingsService.token, this.invoice);
|
|
1544
|
+
lastValueFrom(this.secureApiClient.post(this.apiRoute, new URLSearchParams({ ...requestParams }), {
|
|
1545
|
+
headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
|
|
1546
|
+
responseType: 'json',
|
|
1547
|
+
}))
|
|
1548
|
+
.then((response) => {
|
|
1549
|
+
const checkStatusResponse = this.responseFactory({
|
|
1550
|
+
status: response.status,
|
|
1551
|
+
final: response.final,
|
|
1552
|
+
isPaymentAccountAttached: response.is_payment_account_attached,
|
|
1553
|
+
});
|
|
1554
|
+
this.emitResponse(checkStatusResponse);
|
|
1555
|
+
})
|
|
1556
|
+
.catch((error) => {
|
|
1557
|
+
throw new ResponseError(error.message);
|
|
1558
|
+
});
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
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 });
|
|
1562
|
+
CheckStatusService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CheckStatusService, providedIn: 'root' });
|
|
1563
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CheckStatusService, decorators: [{
|
|
1564
|
+
type: Injectable,
|
|
1565
|
+
args: [{
|
|
1566
|
+
providedIn: 'root',
|
|
1567
|
+
}]
|
|
1568
|
+
}], ctorParameters: function () { return [{ type: SecureApiClient }, { type: SettingsService }, { type: undefined, decorators: [{
|
|
1569
|
+
type: Inject,
|
|
1570
|
+
args: [checkStatusRequestFactoryToken]
|
|
1571
|
+
}] }, { type: undefined, decorators: [{
|
|
1572
|
+
type: Inject,
|
|
1573
|
+
args: [checkStatusResponseFactoryToken]
|
|
1574
|
+
}] }]; } });
|
|
1575
|
+
|
|
1576
|
+
var WebSocketStatus;
|
|
1577
|
+
(function (WebSocketStatus) {
|
|
1578
|
+
WebSocketStatus["statusChanged"] = "status_changed";
|
|
1579
|
+
WebSocketStatus["troubledStatus"] = "troubled_status";
|
|
1580
|
+
})(WebSocketStatus || (WebSocketStatus = {}));
|
|
1581
|
+
|
|
1582
|
+
var WebSocketClientType;
|
|
1583
|
+
(function (WebSocketClientType) {
|
|
1584
|
+
WebSocketClientType["nchan"] = "nchan";
|
|
1585
|
+
WebSocketClientType["centrifugo"] = "centrifugo";
|
|
1586
|
+
})(WebSocketClientType || (WebSocketClientType = {}));
|
|
1587
|
+
|
|
1588
|
+
class NchanWebSocketService {
|
|
1589
|
+
constructor() {
|
|
1590
|
+
this.type = WebSocketClientType.nchan;
|
|
1591
|
+
this.reconnectionTimerId = null;
|
|
1592
|
+
this.incomingMessages$ = new Subject();
|
|
1593
|
+
this.successfulReconnectionEventsProxy$ = new Subject();
|
|
1594
|
+
}
|
|
1595
|
+
async open() {
|
|
1596
|
+
if (this.openPromise && !this.isClosed()) {
|
|
1597
|
+
return this.openPromise;
|
|
1598
|
+
}
|
|
1599
|
+
this.openPromise = this.createConnection()
|
|
1600
|
+
.catch(async () => {
|
|
1601
|
+
return this.waitWhileNotReconnect();
|
|
1602
|
+
})
|
|
1603
|
+
.then(() => {
|
|
1604
|
+
this.connection.onclose = async () => this.open();
|
|
1605
|
+
});
|
|
1606
|
+
return this.openPromise;
|
|
1607
|
+
}
|
|
1608
|
+
close() {
|
|
1609
|
+
this.clearReconnectionTimer();
|
|
1610
|
+
if (this.isClosed()) {
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1613
|
+
this.connection.onclose = null;
|
|
1614
|
+
this.connection.close();
|
|
1615
|
+
}
|
|
1616
|
+
get messages$() {
|
|
1617
|
+
return this.incomingMessages$
|
|
1618
|
+
.asObservable()
|
|
1619
|
+
.pipe(map$1((event) => event.data));
|
|
1620
|
+
}
|
|
1621
|
+
subscribeOnSuccessfulReconnection(next) {
|
|
1622
|
+
return this.successfulReconnectionEventsProxy$
|
|
1623
|
+
.asObservable()
|
|
1624
|
+
.subscribe(next);
|
|
1625
|
+
}
|
|
1626
|
+
isClosed() {
|
|
1627
|
+
if (!this.connection) {
|
|
1628
|
+
return true;
|
|
1629
|
+
}
|
|
1630
|
+
return [this.connection.CLOSED, this.connection.CLOSING].includes(this.connection.readyState);
|
|
1631
|
+
}
|
|
1632
|
+
clearReconnectionTimer() {
|
|
1633
|
+
if (this.reconnectionTimerId) {
|
|
1634
|
+
clearTimeout(this.reconnectionTimerId);
|
|
1635
|
+
this.reconnectionTimerId = null;
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
setFirstReconnectionTimeout() {
|
|
1639
|
+
const min = NchanWebSocketService.timeoutsMs.reconnection -
|
|
1640
|
+
NchanWebSocketService.timeoutsMs.reconnectionMaxDeviation;
|
|
1641
|
+
const max = NchanWebSocketService.timeoutsMs.reconnection +
|
|
1642
|
+
NchanWebSocketService.timeoutsMs.reconnectionMaxDeviation;
|
|
1643
|
+
this.reconnectionTimeoutMs =
|
|
1644
|
+
Math.floor(Math.random() * (max - min + 1)) + min;
|
|
1645
|
+
}
|
|
1646
|
+
incrementReconnectionTimeout() {
|
|
1647
|
+
this.reconnectionTimeoutMs =
|
|
1648
|
+
this.reconnectionTimeoutMs *
|
|
1649
|
+
NchanWebSocketService.reconnectionTimeoutIncrementFactor;
|
|
1650
|
+
}
|
|
1651
|
+
async createConnection() {
|
|
1652
|
+
this.connection = new WebSocket(this.url);
|
|
1653
|
+
this.connection.onmessage = this.incomingMessages$.next.bind(this.incomingMessages$);
|
|
1654
|
+
return new Promise((resolve, reject) => {
|
|
1655
|
+
this.connection.onopen = () => {
|
|
1656
|
+
clearTimeout(this.openConnectionTimerId);
|
|
1657
|
+
resolve();
|
|
1658
|
+
};
|
|
1659
|
+
this.connection.onclose = () => {
|
|
1660
|
+
reject();
|
|
1661
|
+
};
|
|
1662
|
+
});
|
|
1663
|
+
}
|
|
1664
|
+
async reconnect() {
|
|
1665
|
+
this.clearReconnectionTimer();
|
|
1666
|
+
return new Promise((resolve) => {
|
|
1667
|
+
this.reconnectionTimerId = setTimeout(() => {
|
|
1668
|
+
this.createConnection()
|
|
1669
|
+
.then(() => resolve(true))
|
|
1670
|
+
.catch(() => resolve(false));
|
|
1671
|
+
this.incrementReconnectionTimeout();
|
|
1672
|
+
}, this.reconnectionTimeoutMs);
|
|
1673
|
+
});
|
|
1674
|
+
}
|
|
1675
|
+
async waitWhileNotReconnect() {
|
|
1676
|
+
this.clearReconnectionTimer();
|
|
1677
|
+
this.setFirstReconnectionTimeout();
|
|
1678
|
+
let isConnected = false;
|
|
1679
|
+
while (!isConnected) {
|
|
1680
|
+
isConnected = await this.reconnect();
|
|
1681
|
+
}
|
|
1682
|
+
this.successfulReconnectionEventsProxy$.next();
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
NchanWebSocketService.reconnectionTimeoutIncrementFactor = 2;
|
|
1686
|
+
NchanWebSocketService.timeoutsMs = {
|
|
1687
|
+
reconnection: 1500,
|
|
1688
|
+
reconnectionMaxDeviation: 1500,
|
|
1689
|
+
};
|
|
1690
|
+
NchanWebSocketService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: NchanWebSocketService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1691
|
+
NchanWebSocketService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: NchanWebSocketService, providedIn: 'root' });
|
|
1692
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: NchanWebSocketService, decorators: [{
|
|
1693
|
+
type: Injectable,
|
|
1694
|
+
args: [{
|
|
1695
|
+
providedIn: 'root',
|
|
1696
|
+
}]
|
|
1697
|
+
}] });
|
|
1698
|
+
|
|
1699
|
+
var ErrorTags;
|
|
1700
|
+
(function (ErrorTags) {
|
|
1701
|
+
ErrorTags["APP"] = "appError";
|
|
1702
|
+
ErrorTags["HTTP"] = "httpError";
|
|
1703
|
+
ErrorTags["JS"] = "jsError";
|
|
1704
|
+
ErrorTags["WS"] = "webSocket";
|
|
1705
|
+
ErrorTags["ENCRYPT"] = "encrypt";
|
|
1706
|
+
ErrorTags["APPLEPAY"] = "applepay";
|
|
1707
|
+
ErrorTags["HEADLESS_UI"] = "headlessUi";
|
|
1708
|
+
ErrorTags["GOOGLEPAY"] = "googlepay";
|
|
1709
|
+
ErrorTags["PAYTM"] = "paytm";
|
|
1710
|
+
})(ErrorTags || (ErrorTags = {}));
|
|
1711
|
+
|
|
1712
|
+
class TaggedError extends Error {
|
|
1713
|
+
constructor(message, tags) {
|
|
1714
|
+
super(message);
|
|
1715
|
+
this.tags = [];
|
|
1716
|
+
this.parentTag = ErrorTags.HEADLESS_UI;
|
|
1717
|
+
this.tags = this.childTag
|
|
1718
|
+
? [this.parentTag, this.childTag]
|
|
1719
|
+
: [this.parentTag];
|
|
1720
|
+
if (tags) {
|
|
1721
|
+
const newTags = tags.filter((t, i, arr) => !this.tags.includes(t) && arr.indexOf(t) == i);
|
|
1722
|
+
this.tags = [...this.tags, ...newTags];
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
class WsError extends TaggedError {
|
|
1728
|
+
constructor(message, channelName, tags) {
|
|
1729
|
+
tags = tags ? [...tags, ErrorTags.WS] : [ErrorTags.WS];
|
|
1730
|
+
const messageWithChannel = `${message}. ChannelName - ${channelName}`;
|
|
1731
|
+
super(messageWithChannel, tags);
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
class ElkLoggerService {
|
|
1736
|
+
constructor(window, settingsService, http, ngZone) {
|
|
1737
|
+
this.window = window;
|
|
1738
|
+
this.settingsService = settingsService;
|
|
1739
|
+
this.http = http;
|
|
1740
|
+
this.ngZone = ngZone;
|
|
1741
|
+
this.vendors = new RegExp('node_modules\\/(@angular|zone).*.js$');
|
|
1742
|
+
this.stackTrace = this.loadStackTrace();
|
|
1743
|
+
}
|
|
1744
|
+
handleError(error) {
|
|
1745
|
+
this.ngZone.runOutsideAngular(() => {
|
|
1746
|
+
if (isDevMode()) {
|
|
1747
|
+
console.error(error);
|
|
1748
|
+
return;
|
|
1749
|
+
}
|
|
1750
|
+
this.parseError(error).catch(console.log);
|
|
1751
|
+
});
|
|
1752
|
+
}
|
|
1753
|
+
log(message, tags, extra) {
|
|
1754
|
+
const logTags = [ErrorTags.HEADLESS_UI, ...tags];
|
|
1755
|
+
if (isDevMode()) {
|
|
1756
|
+
console.log(message, tags);
|
|
1757
|
+
return;
|
|
1758
|
+
}
|
|
1759
|
+
const logMessage = {
|
|
1760
|
+
additionalInfo: this.getAdditionalInfo(),
|
|
1761
|
+
extra,
|
|
1762
|
+
message,
|
|
1763
|
+
};
|
|
1764
|
+
this.sendLog(logMessage, logTags);
|
|
1765
|
+
}
|
|
1766
|
+
async parseError(error) {
|
|
1767
|
+
const errorObj = error instanceof TaggedError
|
|
1768
|
+
? error
|
|
1769
|
+
: new TaggedError(error.message || error.toString());
|
|
1770
|
+
errorObj.trace = await this.getErrorTrace(errorObj);
|
|
1771
|
+
errorObj.additionalInfo = this.getAdditionalInfo();
|
|
1772
|
+
const { tags } = errorObj;
|
|
1773
|
+
const cleanError = this.removeErrorMetaFields(errorObj);
|
|
1774
|
+
this.sendLog(cleanError, tags);
|
|
1775
|
+
return errorObj;
|
|
1776
|
+
}
|
|
1777
|
+
async loadStackTrace() {
|
|
1778
|
+
const library = await import('stacktrace-js');
|
|
1779
|
+
return library.default;
|
|
1780
|
+
}
|
|
1781
|
+
async getErrorTrace(error) {
|
|
1782
|
+
const stackTrace = await this.stackTrace;
|
|
1783
|
+
const stackFramesArr = await stackTrace.fromError(error);
|
|
1784
|
+
const filteredFramesArr = stackFramesArr.filter(({ fileName }) => fileName && !this.vendors.test(fileName));
|
|
1785
|
+
return filteredFramesArr
|
|
1786
|
+
.map((stackFrame) => stackFrame.toString())
|
|
1787
|
+
.join('\n');
|
|
1788
|
+
}
|
|
1789
|
+
getAdditionalInfo() {
|
|
1790
|
+
const extractUrlHost = (url) => url.replace(/^https?:\/\/([^/?#]+).*$/i, '$1');
|
|
1791
|
+
return {
|
|
1792
|
+
location: {
|
|
1793
|
+
url: this.window.location.href,
|
|
1794
|
+
},
|
|
1795
|
+
project: {
|
|
1796
|
+
id: this.settingsService.project.id,
|
|
1797
|
+
},
|
|
1798
|
+
referrer: {
|
|
1799
|
+
url: this.window.document.referrer,
|
|
1800
|
+
},
|
|
1801
|
+
viewport: {
|
|
1802
|
+
width: this.window.document.documentElement.clientWidth,
|
|
1803
|
+
height: this.window.document.documentElement.clientHeight,
|
|
1804
|
+
},
|
|
1805
|
+
cdn_address: this.settingsService.settings.cdnUrl
|
|
1806
|
+
? extractUrlHost(this.settingsService.settings.cdnUrl)
|
|
1807
|
+
: 'none',
|
|
1808
|
+
country: this.settingsService.user.country.value,
|
|
1809
|
+
local: this.settingsService.user.country.localized_name,
|
|
1810
|
+
};
|
|
1811
|
+
}
|
|
1812
|
+
removeErrorMetaFields(error) {
|
|
1813
|
+
const metaPropList = [
|
|
1814
|
+
'parentTag',
|
|
1815
|
+
'childTag',
|
|
1816
|
+
'RESTRICTED_KEYS_REGEXP',
|
|
1817
|
+
'tags',
|
|
1818
|
+
];
|
|
1819
|
+
Object.keys(error).forEach((key) => {
|
|
1820
|
+
if (metaPropList.includes(key))
|
|
1821
|
+
delete error[key];
|
|
1822
|
+
});
|
|
1823
|
+
// implementing own 'message' property from prototype
|
|
1824
|
+
return { ...error, message: error.message };
|
|
1825
|
+
}
|
|
1826
|
+
sendLog(message, tags) {
|
|
1827
|
+
const url = `https://logs-01.xsolla.com/tag/${tags.join(',')}`;
|
|
1828
|
+
firstValueFrom(this.http.post(url, message, {
|
|
1829
|
+
headers: new HttpHeaders().set('Content-Type', 'text/plain'),
|
|
1830
|
+
responseType: 'text',
|
|
1831
|
+
})).catch((err) => console.error('Elk Logger: request error', err));
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
ElkLoggerService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ElkLoggerService, deps: [{ token: windowToken }, { token: SettingsService }, { token: i1.HttpClient }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1835
|
+
ElkLoggerService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ElkLoggerService, providedIn: 'root' });
|
|
1836
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ElkLoggerService, decorators: [{
|
|
1837
|
+
type: Injectable,
|
|
1838
|
+
args: [{
|
|
1839
|
+
providedIn: 'root',
|
|
1840
|
+
}]
|
|
1841
|
+
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
1842
|
+
type: Inject,
|
|
1843
|
+
args: [windowToken]
|
|
1844
|
+
}] }, { type: SettingsService }, { type: i1.HttpClient }, { type: i0.NgZone }]; } });
|
|
1845
|
+
|
|
1846
|
+
class CentrifugoWebSocketService {
|
|
1847
|
+
constructor(elkLoggerService) {
|
|
1848
|
+
this.elkLoggerService = elkLoggerService;
|
|
1849
|
+
this.type = WebSocketClientType.centrifugo;
|
|
1850
|
+
this.reconnectionTimerId = null;
|
|
1851
|
+
this.isConnectionOpen = false;
|
|
1852
|
+
this.isConnecting = false;
|
|
1853
|
+
this.incomingMessages$ = new Subject();
|
|
1854
|
+
this.successfulReconnectionEventsProxy$ = new Subject();
|
|
1855
|
+
}
|
|
1856
|
+
async open(url, channel) {
|
|
1857
|
+
if (url === this.url && channel === this.channel) {
|
|
1858
|
+
return;
|
|
1859
|
+
}
|
|
1860
|
+
try {
|
|
1861
|
+
this.url = url;
|
|
1862
|
+
this.channel = channel;
|
|
1863
|
+
await this.createConnection(url, channel);
|
|
1864
|
+
}
|
|
1865
|
+
catch (error) {
|
|
1866
|
+
// @ts-expect-error error is unknown
|
|
1867
|
+
const message = (error?.message || error);
|
|
1868
|
+
const unknownError = new WsError(`unknown websocket error: ${message}`, channel);
|
|
1869
|
+
this.elkLoggerService.handleError(unknownError);
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
close() {
|
|
1873
|
+
this.clearReconnectionTimer();
|
|
1874
|
+
if (!this.isConnectionOpen) {
|
|
1875
|
+
return;
|
|
1876
|
+
}
|
|
1877
|
+
this.connection.disconnect();
|
|
1878
|
+
}
|
|
1879
|
+
get messages$() {
|
|
1880
|
+
return (this.incomingMessages$
|
|
1881
|
+
.asObservable()
|
|
1882
|
+
// event don't respect type from argument, it's weird
|
|
1883
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
1884
|
+
.pipe(map$1((event) => event.data)));
|
|
1885
|
+
}
|
|
1886
|
+
subscribeOnSuccessfulReconnection(next) {
|
|
1887
|
+
return this.successfulReconnectionEventsProxy$
|
|
1888
|
+
.asObservable()
|
|
1889
|
+
.subscribe(next);
|
|
1890
|
+
}
|
|
1891
|
+
clearReconnectionTimer() {
|
|
1892
|
+
if (this.reconnectionTimerId) {
|
|
1893
|
+
clearTimeout(this.reconnectionTimerId);
|
|
1894
|
+
this.reconnectionTimerId = null;
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
setFirstReconnectionTimeout() {
|
|
1898
|
+
const min = CentrifugoWebSocketService.timeoutsMs.reconnection -
|
|
1899
|
+
CentrifugoWebSocketService.timeoutsMs.reconnectionMaxDeviation;
|
|
1900
|
+
const max = CentrifugoWebSocketService.timeoutsMs.reconnection +
|
|
1901
|
+
CentrifugoWebSocketService.timeoutsMs.reconnectionMaxDeviation;
|
|
1902
|
+
this.reconnectionTimeoutMs =
|
|
1903
|
+
Math.floor(Math.random() * (max - min + 1)) + min;
|
|
1904
|
+
}
|
|
1905
|
+
incrementReconnectionTimeout() {
|
|
1906
|
+
this.reconnectionTimeoutMs =
|
|
1907
|
+
this.reconnectionTimeoutMs *
|
|
1908
|
+
CentrifugoWebSocketService.reconnectionTimeoutIncrementFactor;
|
|
1909
|
+
}
|
|
1910
|
+
async getCentrifugoClient() {
|
|
1911
|
+
return import('centrifuge').then((module) => module.Centrifuge);
|
|
1912
|
+
}
|
|
1913
|
+
async createConnection(url, channel) {
|
|
1914
|
+
if (this.isConnectionOpen || this.isConnecting) {
|
|
1915
|
+
return;
|
|
1916
|
+
}
|
|
1917
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1918
|
+
const CentrifugeClient = await this.getCentrifugoClient();
|
|
1919
|
+
const websocketUrl = url ?? this.url;
|
|
1920
|
+
const websocketChannel = channel ?? this.channel;
|
|
1921
|
+
this.connection = new CentrifugeClient(websocketUrl, {
|
|
1922
|
+
debug: true,
|
|
1923
|
+
maxReconnectDelay: 1500,
|
|
1924
|
+
maxServerPingDelay: 1000,
|
|
1925
|
+
});
|
|
1926
|
+
return new Promise((resolve, reject) => {
|
|
1927
|
+
this.connection
|
|
1928
|
+
.on('connecting', () => {
|
|
1929
|
+
this.isConnecting = true;
|
|
1930
|
+
})
|
|
1931
|
+
.on('connected', () => {
|
|
1932
|
+
this.onConnect();
|
|
1933
|
+
resolve();
|
|
1934
|
+
})
|
|
1935
|
+
.on('disconnected', (ctx) => {
|
|
1936
|
+
this.onDisconnect(ctx, websocketChannel);
|
|
1937
|
+
reject();
|
|
1938
|
+
})
|
|
1939
|
+
.on('error', (ctx) => {
|
|
1940
|
+
const message = `code ${ctx.error.code} - ${ctx.error.message}`;
|
|
1941
|
+
this.elkLoggerService.log(`connection error: ${message}`, [ErrorTags.WS], {
|
|
1942
|
+
channel: websocketChannel,
|
|
1943
|
+
});
|
|
1944
|
+
})
|
|
1945
|
+
.connect();
|
|
1946
|
+
this.subscription = this.connection.newSubscription(websocketChannel, this.getSubscriptionOptions(websocketChannel));
|
|
1947
|
+
this.subscription
|
|
1948
|
+
.on('subscribed', (ctx) => {
|
|
1949
|
+
this.subscriptionPosition = ctx.streamPosition;
|
|
1950
|
+
this.prevSubscribedChannel = websocketChannel;
|
|
1951
|
+
})
|
|
1952
|
+
.on('publication', (ctx) => {
|
|
1953
|
+
const message = ctx.data;
|
|
1954
|
+
this.elkLoggerService.log(`websocket message received: ${message}`, [ErrorTags.WS], {
|
|
1955
|
+
channel: websocketChannel,
|
|
1956
|
+
});
|
|
1957
|
+
this.incomingMessages$.next(ctx);
|
|
1958
|
+
})
|
|
1959
|
+
.on('error', (ctx) => {
|
|
1960
|
+
const message = `code ${ctx.error.code} - ${ctx.error.message}`;
|
|
1961
|
+
this.elkLoggerService.log(`subscription error: ${message}`, [ErrorTags.WS], {
|
|
1962
|
+
channel: websocketChannel,
|
|
1963
|
+
});
|
|
1964
|
+
})
|
|
1965
|
+
.subscribe();
|
|
1966
|
+
});
|
|
1967
|
+
}
|
|
1968
|
+
onConnect() {
|
|
1969
|
+
clearTimeout(this.openConnectionTimerId);
|
|
1970
|
+
this.isConnecting = false;
|
|
1971
|
+
this.isConnectionOpen = true;
|
|
1972
|
+
}
|
|
1973
|
+
onDisconnect(ctx, websocketChannel) {
|
|
1974
|
+
this.isConnecting = false;
|
|
1975
|
+
this.isConnectionOpen = false;
|
|
1976
|
+
/* If connection error, cause any connection error isn't 0 */
|
|
1977
|
+
if (ctx.code !== 0) {
|
|
1978
|
+
const message = `code ${ctx.code} - ${ctx.reason}`;
|
|
1979
|
+
this.elkLoggerService.log(`disconnected error: ${message}`, [ErrorTags.WS], {
|
|
1980
|
+
channel: websocketChannel,
|
|
1981
|
+
});
|
|
1982
|
+
(async () => {
|
|
1983
|
+
await this.waitWhileNotReconnect();
|
|
1984
|
+
})();
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
async reconnect() {
|
|
1988
|
+
this.clearReconnectionTimer();
|
|
1989
|
+
return new Promise((resolve) => {
|
|
1990
|
+
this.reconnectionTimerId = setTimeout(() => {
|
|
1991
|
+
this.createConnection()
|
|
1992
|
+
.then(() => resolve(true))
|
|
1993
|
+
.catch(() => resolve(false));
|
|
1994
|
+
this.incrementReconnectionTimeout();
|
|
1995
|
+
}, this.reconnectionTimeoutMs);
|
|
1996
|
+
});
|
|
1997
|
+
}
|
|
1998
|
+
async waitWhileNotReconnect() {
|
|
1999
|
+
this.clearReconnectionTimer();
|
|
2000
|
+
this.setFirstReconnectionTimeout();
|
|
2001
|
+
let isConnected = false;
|
|
2002
|
+
const beforeTimer = performance.now();
|
|
2003
|
+
while (!isConnected) {
|
|
2004
|
+
isConnected = await this.reconnect();
|
|
2005
|
+
}
|
|
2006
|
+
const afterTimer = performance.now();
|
|
2007
|
+
const timerDuration = afterTimer - beforeTimer;
|
|
2008
|
+
this.elkLoggerService.log(`fallback to reconnection timer: duration ${timerDuration}ms`, [ErrorTags.WS], {
|
|
2009
|
+
channel: this.channel,
|
|
2010
|
+
});
|
|
2011
|
+
this.successfulReconnectionEventsProxy$.next();
|
|
2012
|
+
}
|
|
2013
|
+
getSubscriptionOptions(websocketChannel) {
|
|
2014
|
+
const options = {
|
|
2015
|
+
recoverable: true,
|
|
2016
|
+
};
|
|
2017
|
+
if (websocketChannel === this.prevSubscribedChannel &&
|
|
2018
|
+
this.subscriptionPosition) {
|
|
2019
|
+
options.since = this.subscriptionPosition;
|
|
2020
|
+
}
|
|
2021
|
+
return options;
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
CentrifugoWebSocketService.reconnectionTimeoutIncrementFactor = 2;
|
|
2025
|
+
CentrifugoWebSocketService.timeoutsMs = {
|
|
2026
|
+
reconnection: 1000,
|
|
2027
|
+
reconnectionMaxDeviation: 1000,
|
|
2028
|
+
};
|
|
2029
|
+
CentrifugoWebSocketService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CentrifugoWebSocketService, deps: [{ token: ElkLoggerService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2030
|
+
CentrifugoWebSocketService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CentrifugoWebSocketService, providedIn: 'root' });
|
|
2031
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CentrifugoWebSocketService, decorators: [{
|
|
2032
|
+
type: Injectable,
|
|
2033
|
+
args: [{
|
|
2034
|
+
providedIn: 'root',
|
|
2035
|
+
}]
|
|
2036
|
+
}], ctorParameters: function () { return [{ type: ElkLoggerService }]; } });
|
|
2037
|
+
|
|
2038
|
+
// @todo: remove this factory and switch to centrifugo client after centrifugo issues resolved
|
|
2039
|
+
class WebSocketFactory {
|
|
2040
|
+
constructor(nchanWebSocket, centrifugoWebSocket) {
|
|
2041
|
+
this.nchanWebSocket = nchanWebSocket;
|
|
2042
|
+
this.centrifugoWebSocket = centrifugoWebSocket;
|
|
2043
|
+
}
|
|
2044
|
+
createWebSocketClient(url, clientType) {
|
|
2045
|
+
if (clientType === WebSocketClientType.centrifugo) {
|
|
2046
|
+
return this.centrifugoWebSocket;
|
|
2047
|
+
}
|
|
2048
|
+
this.nchanWebSocket.url = url;
|
|
2049
|
+
return this.nchanWebSocket;
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
WebSocketFactory.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: WebSocketFactory, deps: [{ token: NchanWebSocketService }, { token: CentrifugoWebSocketService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2053
|
+
WebSocketFactory.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: WebSocketFactory, providedIn: 'root' });
|
|
2054
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: WebSocketFactory, decorators: [{
|
|
2055
|
+
type: Injectable,
|
|
2056
|
+
args: [{
|
|
2057
|
+
providedIn: 'root',
|
|
2058
|
+
}]
|
|
2059
|
+
}], ctorParameters: function () { return [{ type: NchanWebSocketService }, { type: CentrifugoWebSocketService }]; } });
|
|
2060
|
+
|
|
2061
|
+
class WebsocketStatusService {
|
|
2062
|
+
get needCheckStatus$() {
|
|
2063
|
+
return this.needCheckStatusSubject.asObservable();
|
|
2064
|
+
}
|
|
2065
|
+
get statusChanged$() {
|
|
2066
|
+
return this.statusChangedSubject.asObservable();
|
|
2067
|
+
}
|
|
2068
|
+
constructor(webSocketFactory) {
|
|
2069
|
+
this.webSocketFactory = webSocketFactory;
|
|
2070
|
+
this.reinsuranceCheckStatus = {
|
|
2071
|
+
timeoutId: null,
|
|
2072
|
+
timeoutMs: 180000,
|
|
2073
|
+
};
|
|
2074
|
+
this.needCheckStatusSubject = new Subject();
|
|
2075
|
+
this.statusChangedSubject = new Subject();
|
|
2076
|
+
this.webSocketClient = null;
|
|
2077
|
+
}
|
|
2078
|
+
async checkStatusWithWebSocket(webSocketUrl, webSocketChannelName, webSocketClientType) {
|
|
2079
|
+
this.webSocketClient = this.webSocketFactory.createWebSocketClient(webSocketUrl, webSocketClientType);
|
|
2080
|
+
await this.webSocketClient.open(webSocketUrl, webSocketChannelName);
|
|
2081
|
+
this.webSocketSubscription?.unsubscribe();
|
|
2082
|
+
this.webSocketSubscription = this.webSocketClient.messages$.subscribe((message) => this.statusProcessing(message));
|
|
2083
|
+
this.webSocketReconnectionSubscription =
|
|
2084
|
+
this.webSocketClient.subscribeOnSuccessfulReconnection(() => {
|
|
2085
|
+
this.needCheckStatusSubject.next();
|
|
2086
|
+
});
|
|
2087
|
+
this.needCheckStatusSubject.next();
|
|
2088
|
+
this.startReinsuranceCheckTimeout();
|
|
2089
|
+
}
|
|
2090
|
+
closeWebSocket() {
|
|
2091
|
+
this.removeSubscription();
|
|
2092
|
+
this.webSocketClient?.close();
|
|
2093
|
+
this.clearReinsuranceCheckTimeout();
|
|
2094
|
+
}
|
|
2095
|
+
startReinsuranceCheckTimeout() {
|
|
2096
|
+
this.clearReinsuranceCheckTimeout();
|
|
2097
|
+
this.reinsuranceCheckStatus.timeoutId = setTimeout(() => {
|
|
2098
|
+
this.needCheckStatusSubject.next();
|
|
2099
|
+
}, this.reinsuranceCheckStatus.timeoutMs);
|
|
2100
|
+
}
|
|
2101
|
+
clearReinsuranceCheckTimeout() {
|
|
2102
|
+
if (this.reinsuranceCheckStatus.timeoutId) {
|
|
2103
|
+
clearTimeout(this.reinsuranceCheckStatus.timeoutId);
|
|
2104
|
+
this.reinsuranceCheckStatus.timeoutId = null;
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
statusProcessing(message) {
|
|
2108
|
+
if (message === WebSocketStatus.statusChanged) {
|
|
2109
|
+
this.statusChangedSubject.next();
|
|
2110
|
+
this.closeWebSocket();
|
|
2111
|
+
this.clearReinsuranceCheckTimeout();
|
|
2112
|
+
}
|
|
2113
|
+
if (message === WebSocketStatus.troubledStatus) {
|
|
2114
|
+
this.clearReinsuranceCheckTimeout();
|
|
2115
|
+
this.closeWebSocket();
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
removeSubscription() {
|
|
2119
|
+
this.webSocketSubscription?.unsubscribe();
|
|
2120
|
+
this.webSocketReconnectionSubscription?.unsubscribe();
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
WebsocketStatusService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: WebsocketStatusService, deps: [{ token: WebSocketFactory }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2124
|
+
WebsocketStatusService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: WebsocketStatusService, providedIn: 'root' });
|
|
2125
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: WebsocketStatusService, decorators: [{
|
|
2126
|
+
type: Injectable,
|
|
2127
|
+
args: [{
|
|
2128
|
+
providedIn: 'root',
|
|
2129
|
+
}]
|
|
2130
|
+
}], ctorParameters: function () { return [{ type: WebSocketFactory }]; } });
|
|
2131
|
+
|
|
2132
|
+
class ListenStatusService {
|
|
2133
|
+
get websocketOpened$() {
|
|
2134
|
+
return this.websocketOpenedSubject.asObservable();
|
|
2135
|
+
}
|
|
2136
|
+
get statusUpdated$() {
|
|
2137
|
+
return this.statusUpdatedSubject.asObservable();
|
|
2138
|
+
}
|
|
2139
|
+
constructor(statusService, checkStatusService, websocketStatusService) {
|
|
2140
|
+
this.statusService = statusService;
|
|
2141
|
+
this.checkStatusService = checkStatusService;
|
|
2142
|
+
this.websocketStatusService = websocketStatusService;
|
|
2143
|
+
this.isListening = false;
|
|
2144
|
+
this.websocketOpenedSubject = new Subject();
|
|
2145
|
+
this.statusUpdatedSubject = new Subject();
|
|
2146
|
+
this.statusDoneSubject = new Subject();
|
|
2147
|
+
this.destroy$ = new Subject();
|
|
2148
|
+
}
|
|
2149
|
+
listen(invoice) {
|
|
2150
|
+
if (this.isListening) {
|
|
2151
|
+
this.stopListening();
|
|
2152
|
+
}
|
|
2153
|
+
this.destroy$ = new Subject();
|
|
2154
|
+
this.isListening = true;
|
|
2155
|
+
this.subscribeStatusUpdate(invoice);
|
|
2156
|
+
this.subscribeCheckStatusUpdate();
|
|
2157
|
+
this.subscribeWebsocketEvent();
|
|
2158
|
+
this.checkStatusService.setRequestParams(invoice);
|
|
2159
|
+
return this.statusDoneSubject.asObservable();
|
|
2160
|
+
}
|
|
2161
|
+
stopListening() {
|
|
2162
|
+
this.isListening = false;
|
|
2163
|
+
this.websocketStatusService.closeWebSocket();
|
|
2164
|
+
this.destroy$.next();
|
|
2165
|
+
this.destroy$.complete();
|
|
2166
|
+
}
|
|
2167
|
+
subscribeStatusUpdate(invoice) {
|
|
2168
|
+
this.statusService.response$
|
|
2169
|
+
.pipe(filter$1((statusResponse) => {
|
|
2170
|
+
return statusResponse?.status?.invoice === Number(invoice);
|
|
2171
|
+
}), takeUntil(this.destroy$))
|
|
2172
|
+
.subscribe((statusResponse) => {
|
|
2173
|
+
if (!statusResponse?.status) {
|
|
2174
|
+
return;
|
|
2175
|
+
}
|
|
2176
|
+
const statusSettings = {
|
|
2177
|
+
statusState: statusResponse.status.statusState,
|
|
2178
|
+
isCancelUser: statusResponse.status.isCancelUser,
|
|
2179
|
+
needWebSocket: statusResponse.status.needToCheck,
|
|
2180
|
+
backUrlSettings: statusResponse.status.backUrlSettings,
|
|
2181
|
+
autoRedirect: statusResponse.status.autoRedirect,
|
|
2182
|
+
webSocketUrl: statusResponse.status.webSocketUrl,
|
|
2183
|
+
webSocketChannelName: statusResponse.status.webSocketChannelName,
|
|
2184
|
+
webSocketClientType: statusResponse.status.webSocketClientType,
|
|
2185
|
+
};
|
|
2186
|
+
this.statusUpdatedSubject.next({
|
|
2187
|
+
statusResponse: statusResponse,
|
|
2188
|
+
statusSettings: statusSettings,
|
|
2189
|
+
});
|
|
2190
|
+
if (statusSettings.needWebSocket) {
|
|
2191
|
+
this.openWebsocket(statusSettings);
|
|
2192
|
+
return;
|
|
2193
|
+
}
|
|
2194
|
+
this.stopListening();
|
|
2195
|
+
this.statusDoneSubject.next(statusSettings);
|
|
2196
|
+
});
|
|
2197
|
+
}
|
|
2198
|
+
subscribeCheckStatusUpdate() {
|
|
2199
|
+
this.checkStatusService.response$
|
|
2200
|
+
.pipe(takeUntil(this.destroy$))
|
|
2201
|
+
.subscribe((checkStatusResponse) => {
|
|
2202
|
+
if (!checkStatusResponse?.status)
|
|
2203
|
+
return;
|
|
2204
|
+
if (checkStatusResponse.status === StatusEnum.done) {
|
|
2205
|
+
this.statusService.request();
|
|
2206
|
+
this.websocketStatusService.closeWebSocket();
|
|
2207
|
+
return;
|
|
2208
|
+
}
|
|
2209
|
+
if (checkStatusResponse.final === false) {
|
|
2210
|
+
this.websocketStatusService.startReinsuranceCheckTimeout();
|
|
2211
|
+
return;
|
|
2212
|
+
}
|
|
2213
|
+
});
|
|
2214
|
+
}
|
|
2215
|
+
subscribeWebsocketEvent() {
|
|
2216
|
+
this.websocketStatusService.needCheckStatus$
|
|
2217
|
+
.pipe(takeUntil(this.destroy$))
|
|
2218
|
+
.subscribe(() => this.checkStatusService.request());
|
|
2219
|
+
this.websocketStatusService.statusChanged$
|
|
2220
|
+
.pipe(takeUntil(this.destroy$))
|
|
2221
|
+
.subscribe(() => this.statusService.request());
|
|
2222
|
+
}
|
|
2223
|
+
openWebsocket(statusSettings) {
|
|
2224
|
+
void this.websocketStatusService.checkStatusWithWebSocket(statusSettings.webSocketUrl, statusSettings.webSocketChannelName, statusSettings.webSocketClientType);
|
|
2225
|
+
this.websocketOpenedSubject.next(statusSettings);
|
|
2226
|
+
}
|
|
2227
|
+
}
|
|
2228
|
+
ListenStatusService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ListenStatusService, deps: [{ token: StatusRequestService }, { token: CheckStatusService }, { token: WebsocketStatusService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2229
|
+
ListenStatusService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ListenStatusService, providedIn: 'root' });
|
|
2230
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: ListenStatusService, decorators: [{
|
|
2231
|
+
type: Injectable,
|
|
2232
|
+
args: [{
|
|
2233
|
+
providedIn: 'root',
|
|
2234
|
+
}]
|
|
2235
|
+
}], ctorParameters: function () { return [{ type: StatusRequestService }, { type: CheckStatusService }, { type: WebsocketStatusService }]; } });
|
|
2236
|
+
|
|
2237
|
+
class ShowFieldsAction {
|
|
2238
|
+
constructor(submitResponse) {
|
|
2239
|
+
this.type = 'show_fields';
|
|
2240
|
+
this.data = {
|
|
2241
|
+
fields: [],
|
|
2242
|
+
errors: [],
|
|
2243
|
+
messages: [],
|
|
2244
|
+
order: {},
|
|
2245
|
+
};
|
|
2246
|
+
this.data.fields = submitResponse.fields;
|
|
2247
|
+
this.data.errors = submitResponse.errors;
|
|
2248
|
+
this.data.messages = submitResponse.messages;
|
|
2249
|
+
this.data.order = submitResponse.summary;
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
|
|
2253
|
+
const showFieldsActionFactoryToken = new InjectionToken('ShowFieldsAction');
|
|
2254
|
+
const showFieldsActionFactoryProvider = {
|
|
2255
|
+
provide: showFieldsActionFactoryToken,
|
|
2256
|
+
useValue: {
|
|
2257
|
+
factory: (...args) => new ShowFieldsAction(...args),
|
|
2258
|
+
type: 'show_fields',
|
|
2259
|
+
},
|
|
2260
|
+
};
|
|
2261
|
+
|
|
2262
|
+
class CheckStatusAction {
|
|
2263
|
+
constructor(submitResponse) {
|
|
2264
|
+
this.type = 'check_status';
|
|
2265
|
+
const status = submitResponse.parameters.status;
|
|
2266
|
+
this.data = {
|
|
2267
|
+
invoice: status?.invoice,
|
|
2268
|
+
signature: submitResponse.parameters.form.signature?.value,
|
|
2269
|
+
locale: submitResponse.parameters.form.locale?.value,
|
|
2270
|
+
testPs: submitResponse.parameters.form.testPs?.value,
|
|
2271
|
+
testXsolla: submitResponse.parameters.form.testXsolla?.value,
|
|
2272
|
+
testProject: submitResponse.parameters.form.testProject?.value,
|
|
2273
|
+
userReturnStatus: submitResponse.parameters.form.userReturnStatus?.value,
|
|
2274
|
+
};
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
|
|
2278
|
+
const checkStatusActionFactoryToken = new InjectionToken('CheckStatusAction');
|
|
2279
|
+
const checkStatusActionFactoryProvider = {
|
|
2280
|
+
provide: checkStatusActionFactoryToken,
|
|
2281
|
+
useValue: {
|
|
2282
|
+
factory: (...args) => new CheckStatusAction(...args),
|
|
2283
|
+
type: 'check_status',
|
|
2284
|
+
},
|
|
2285
|
+
};
|
|
2286
|
+
|
|
2287
|
+
const statusUpdatedActionFactoryToken = new InjectionToken('StatusUpdatedAction');
|
|
2288
|
+
const statusUpdatedActionFactoryProvider = {
|
|
2289
|
+
provide: statusUpdatedActionFactoryToken,
|
|
2290
|
+
useValue: {
|
|
2291
|
+
factory: (...args) => new StatusUpdatedAction(...args),
|
|
2292
|
+
type: 'status_updated',
|
|
2293
|
+
},
|
|
2294
|
+
};
|
|
2295
|
+
|
|
2296
|
+
const nextActionsToken = new InjectionToken('Action');
|
|
2297
|
+
const nextActions = [
|
|
2298
|
+
showFieldsActionFactoryProvider,
|
|
2299
|
+
checkStatusActionFactoryProvider,
|
|
2300
|
+
statusUpdatedActionFactoryProvider,
|
|
2301
|
+
];
|
|
2302
|
+
|
|
2303
|
+
const actionTypeCommandMap = {
|
|
2304
|
+
[XpsCommand.check]: 'show_fields',
|
|
2305
|
+
[XpsCommand.status]: 'check_status',
|
|
2306
|
+
};
|
|
2307
|
+
|
|
2308
|
+
class NextActionService {
|
|
2309
|
+
get flowUpdates$() {
|
|
2310
|
+
return this.flowUpdatesSubject.asObservable();
|
|
2311
|
+
}
|
|
2312
|
+
constructor(nextActionTokens, injector) {
|
|
2313
|
+
this.nextActionTokens = nextActionTokens;
|
|
2314
|
+
this.injector = injector;
|
|
2315
|
+
this.flowUpdatesSubject = new Subject();
|
|
2316
|
+
this.nextActionsMap = new Map();
|
|
2317
|
+
this.fillNextActionsMap();
|
|
2318
|
+
}
|
|
2319
|
+
getNextAction(submitResponse) {
|
|
2320
|
+
if (!submitResponse.currentCommand) {
|
|
2321
|
+
return null;
|
|
2322
|
+
}
|
|
2323
|
+
const nextActionFactory = this.findNextAction(submitResponse.currentCommand);
|
|
2324
|
+
if (nextActionFactory) {
|
|
2325
|
+
return nextActionFactory(submitResponse);
|
|
2326
|
+
}
|
|
2327
|
+
throw new Error('Next action is undefined.');
|
|
2328
|
+
}
|
|
2329
|
+
emitFlowUpdates(action) {
|
|
2330
|
+
this.flowUpdatesSubject.next(action);
|
|
2331
|
+
}
|
|
2332
|
+
fillNextActionsMap() {
|
|
2333
|
+
this.nextActionTokens.forEach((nextAction) => {
|
|
2334
|
+
const item = this.injector.get(nextAction.provide);
|
|
2335
|
+
this.nextActionsMap.set(item.type, item.factory);
|
|
2336
|
+
});
|
|
2337
|
+
}
|
|
2338
|
+
findNextAction(command) {
|
|
2339
|
+
const actionType = actionTypeCommandMap[command];
|
|
2340
|
+
if (!actionType) {
|
|
2341
|
+
return;
|
|
2342
|
+
}
|
|
2343
|
+
return this.nextActionsMap.get(actionType);
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
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 });
|
|
2347
|
+
NextActionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: NextActionService, providedIn: 'root' });
|
|
2348
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: NextActionService, decorators: [{
|
|
2349
|
+
type: Injectable,
|
|
2350
|
+
args: [{
|
|
2351
|
+
providedIn: 'root',
|
|
2352
|
+
}]
|
|
2353
|
+
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
2354
|
+
type: Inject,
|
|
2355
|
+
args: [nextActionsToken]
|
|
2356
|
+
}] }, { type: i0.Injector }]; } });
|
|
2357
|
+
|
|
2358
|
+
class StatusService {
|
|
2359
|
+
constructor(statusRequestService, listenStatusService, nextActionService) {
|
|
2360
|
+
this.statusRequestService = statusRequestService;
|
|
2361
|
+
this.listenStatusService = listenStatusService;
|
|
2362
|
+
this.nextActionService = nextActionService;
|
|
2363
|
+
}
|
|
2364
|
+
async getStatus(params) {
|
|
2365
|
+
this.statusRequestService.setRequestParams(params);
|
|
2366
|
+
this.startWaitingStatusUpdates(params.invoice);
|
|
2367
|
+
this.statusRequestService.request();
|
|
2368
|
+
const statusResponse = await firstValueFrom(this.listenStatusService.statusUpdated$);
|
|
2369
|
+
return statusResponse.statusResponse.status;
|
|
2370
|
+
}
|
|
2371
|
+
startWaitingStatusUpdates(invoice) {
|
|
2372
|
+
this.listenStatusService.listen(invoice);
|
|
2373
|
+
this.listenStatusService.statusUpdated$
|
|
2374
|
+
.pipe(skip(1))
|
|
2375
|
+
.subscribe(({ statusResponse }) => {
|
|
2376
|
+
this.nextActionService.emitFlowUpdates(new StatusUpdatedAction(statusResponse));
|
|
2377
|
+
});
|
|
2378
|
+
}
|
|
2379
|
+
}
|
|
2380
|
+
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 });
|
|
2381
|
+
StatusService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: StatusService, providedIn: 'root' });
|
|
2382
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: StatusService, decorators: [{
|
|
2383
|
+
type: Injectable,
|
|
2384
|
+
args: [{
|
|
2385
|
+
providedIn: 'root',
|
|
2386
|
+
}]
|
|
2387
|
+
}], ctorParameters: function () { return [{ type: StatusRequestService }, { type: ListenStatusService }, { type: NextActionService }]; } });
|
|
2388
|
+
|
|
2389
|
+
class PaymentService {
|
|
2390
|
+
constructor(initializeService, submitService, syncService, formService, statusService, nextActionService) {
|
|
2391
|
+
this.initializeService = initializeService;
|
|
2392
|
+
this.submitService = submitService;
|
|
2393
|
+
this.syncService = syncService;
|
|
2394
|
+
this.formService = formService;
|
|
2395
|
+
this.statusService = statusService;
|
|
2396
|
+
this.nextActionService = nextActionService;
|
|
2397
|
+
this.form = null;
|
|
2398
|
+
this.data = null;
|
|
2399
|
+
this.fields = [];
|
|
2400
|
+
}
|
|
2401
|
+
async initialize(config) {
|
|
2402
|
+
this.config = config;
|
|
2403
|
+
this.data = await this.initializeService.request(config);
|
|
2404
|
+
this.fields = this.getFields();
|
|
2405
|
+
this.form = this.formService.createForm(this.fields);
|
|
2406
|
+
this.syncService.setup(this.form, this.fields);
|
|
2407
|
+
return this.fields;
|
|
2408
|
+
}
|
|
2409
|
+
async submit(fields, form) {
|
|
2410
|
+
const submitResponse = await this.submitService.request(fields, form);
|
|
2411
|
+
return this.nextActionService.getNextAction(submitResponse);
|
|
2412
|
+
}
|
|
2413
|
+
getFields() {
|
|
2414
|
+
return this.data?.paymentForm?.fields ?? [];
|
|
2415
|
+
}
|
|
2416
|
+
async validate(field) {
|
|
2417
|
+
return this.syncService.validate(field);
|
|
2418
|
+
}
|
|
2419
|
+
runThreeDs() {
|
|
2420
|
+
throw new Error('Method not implemented.');
|
|
2421
|
+
}
|
|
2422
|
+
getFinanceDetails() {
|
|
2423
|
+
throw new Error('Method not implemented.');
|
|
2424
|
+
}
|
|
2425
|
+
async getStatus(params) {
|
|
2426
|
+
return this.statusService.getStatus({
|
|
2427
|
+
...params,
|
|
2428
|
+
pid: this.config.paymentMethodId,
|
|
2429
|
+
});
|
|
2430
|
+
}
|
|
2431
|
+
changeFieldValue(name, value) {
|
|
2432
|
+
const formControl = this.form?.get(name);
|
|
2433
|
+
formControl?.setValue(value);
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
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: NextActionService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2437
|
+
PaymentService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PaymentService, providedIn: 'root' });
|
|
2438
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PaymentService, decorators: [{
|
|
2439
|
+
type: Injectable,
|
|
2440
|
+
args: [{
|
|
2441
|
+
providedIn: 'root',
|
|
2442
|
+
}]
|
|
2443
|
+
}], ctorParameters: function () { return [{ type: InitializeService }, { type: SubmitService }, { type: SyncService }, { type: FormService }, { type: StatusService }, { type: NextActionService }]; } });
|
|
2444
|
+
|
|
400
2445
|
class RefundPolicyService {
|
|
401
2446
|
constructor(settingsService) {
|
|
402
2447
|
this.settingsService = settingsService;
|
|
@@ -499,84 +2544,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
|
|
|
499
2544
|
}]
|
|
500
2545
|
}], ctorParameters: function () { return [{ type: SettingsService }, { type: RefundPolicyService }, { type: SecureConnectionService }, { type: DisclaimerService }]; } });
|
|
501
2546
|
|
|
502
|
-
class InitializeService {
|
|
503
|
-
constructor(secureApi, settingsService, countryService) {
|
|
504
|
-
this.secureApi = secureApi;
|
|
505
|
-
this.settingsService = settingsService;
|
|
506
|
-
this.countryService = countryService;
|
|
507
|
-
this.apiRoute = 'directpayment';
|
|
508
|
-
}
|
|
509
|
-
async request(config) {
|
|
510
|
-
const requestParams = {
|
|
511
|
-
access_token: this.settingsService.token,
|
|
512
|
-
pid: String(config.paymentMethodId),
|
|
513
|
-
country: this.countryService.getCountry(),
|
|
514
|
-
returnUrl: config.returnUrl,
|
|
515
|
-
};
|
|
516
|
-
return lastValueFrom(this.secureApi.post(this.apiRoute, new URLSearchParams({ ...requestParams }), {
|
|
517
|
-
headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8'),
|
|
518
|
-
responseType: 'json',
|
|
519
|
-
})).catch((error) => {
|
|
520
|
-
throw new ResponseError(error.message);
|
|
521
|
-
});
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
InitializeService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, deps: [{ token: SecureApiClient }, { token: SettingsService }, { token: CountryService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
525
|
-
InitializeService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, providedIn: 'root' });
|
|
526
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: InitializeService, decorators: [{
|
|
527
|
-
type: Injectable,
|
|
528
|
-
args: [{
|
|
529
|
-
providedIn: 'root',
|
|
530
|
-
}]
|
|
531
|
-
}], ctorParameters: function () { return [{ type: SecureApiClient }, { type: SettingsService }, { type: CountryService }]; } });
|
|
532
|
-
|
|
533
|
-
class PaymentService {
|
|
534
|
-
constructor(initializeService) {
|
|
535
|
-
this.initializeService = initializeService;
|
|
536
|
-
this.data = null;
|
|
537
|
-
}
|
|
538
|
-
async initialize(config) {
|
|
539
|
-
this.data = await this.initializeService.request(config);
|
|
540
|
-
return this.data;
|
|
541
|
-
}
|
|
542
|
-
submit() {
|
|
543
|
-
throw new Error('Method not implemented.');
|
|
544
|
-
}
|
|
545
|
-
getFields() {
|
|
546
|
-
throw new Error('Method not implemented.');
|
|
547
|
-
}
|
|
548
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
549
|
-
validate(field) {
|
|
550
|
-
throw new Error('Method not implemented.');
|
|
551
|
-
}
|
|
552
|
-
runThreeDs() {
|
|
553
|
-
throw new Error('Method not implemented.');
|
|
554
|
-
}
|
|
555
|
-
getFinanceDetails() {
|
|
556
|
-
throw new Error('Method not implemented.');
|
|
557
|
-
}
|
|
558
|
-
getStatus() {
|
|
559
|
-
throw new Error('Method not implemented.');
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
PaymentService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PaymentService, deps: [{ token: InitializeService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
563
|
-
PaymentService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PaymentService, providedIn: 'root' });
|
|
564
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PaymentService, decorators: [{
|
|
565
|
-
type: Injectable,
|
|
566
|
-
args: [{
|
|
567
|
-
providedIn: 'root',
|
|
568
|
-
}]
|
|
569
|
-
}], ctorParameters: function () { return [{ type: InitializeService }]; } });
|
|
570
|
-
|
|
571
2547
|
class CoreLibraryService {
|
|
572
|
-
constructor(settingsService, countryService, paymentMethodsService, savedMethodsService, userBalanceService, legalService,
|
|
2548
|
+
constructor(settingsService, countryService, paymentMethodsService, savedMethodsService, userBalanceService, paymentService, deviceFingerPrintService, legalService, nextActionService) {
|
|
573
2549
|
this.settingsService = settingsService;
|
|
574
2550
|
this.countryService = countryService;
|
|
575
2551
|
this.paymentMethodsService = paymentMethodsService;
|
|
576
2552
|
this.savedMethodsService = savedMethodsService;
|
|
577
2553
|
this.userBalanceService = userBalanceService;
|
|
578
|
-
this.legalService = legalService;
|
|
579
2554
|
this.paymentService = paymentService;
|
|
2555
|
+
this.deviceFingerPrintService = deviceFingerPrintService;
|
|
2556
|
+
this.legalService = legalService;
|
|
2557
|
+
this.nextActionService = nextActionService;
|
|
580
2558
|
this.paymentMethods = {
|
|
581
2559
|
getList: async () => this.paymentMethodsService.getList(),
|
|
582
2560
|
getQuickMethods: async () => this.paymentMethodsService.getQuickMethods(),
|
|
@@ -585,7 +2563,8 @@ class CoreLibraryService {
|
|
|
585
2563
|
};
|
|
586
2564
|
}
|
|
587
2565
|
async init(configuration) {
|
|
588
|
-
|
|
2566
|
+
await this.settingsService.init(configuration);
|
|
2567
|
+
await this.deviceFingerPrintService.init();
|
|
589
2568
|
}
|
|
590
2569
|
setCountry(country) {
|
|
591
2570
|
this.countryService.setCountry(country);
|
|
@@ -593,26 +2572,28 @@ class CoreLibraryService {
|
|
|
593
2572
|
createPayment(config) {
|
|
594
2573
|
return {
|
|
595
2574
|
initialize: async () => this.paymentService.initialize(config),
|
|
596
|
-
submit: () => this.paymentService.submit(),
|
|
2575
|
+
submit: async (fields, form) => this.paymentService.submit(fields, form),
|
|
597
2576
|
getFields: () => this.paymentService.getFields(),
|
|
598
|
-
|
|
2577
|
+
changeFieldValue: (name, value) => this.paymentService.changeFieldValue(name, value),
|
|
2578
|
+
validate: async (field) => this.paymentService.validate(field),
|
|
599
2579
|
getFinanceDetails: () => this.paymentService.getFinanceDetails(),
|
|
600
2580
|
runThreeDs: () => this.paymentService.runThreeDs(),
|
|
601
|
-
getStatus: () => this.paymentService.getStatus(),
|
|
2581
|
+
getStatus: async (params) => this.paymentService.getStatus(params),
|
|
2582
|
+
flowUpdates$: this.nextActionService.flowUpdates$,
|
|
602
2583
|
};
|
|
603
2584
|
}
|
|
604
2585
|
getLegalComponentConfig() {
|
|
605
2586
|
return this.legalService.getLegalComponentConfig();
|
|
606
2587
|
}
|
|
607
2588
|
}
|
|
608
|
-
CoreLibraryService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryService, deps: [{ token: SettingsService }, { token: CountryService }, { token: PaymentMethodsService }, { token: SavedMethodsService }, { token: UserBalanceService }, { token: LegalService }, { token:
|
|
2589
|
+
CoreLibraryService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryService, deps: [{ token: SettingsService }, { token: CountryService }, { token: PaymentMethodsService }, { token: SavedMethodsService }, { token: UserBalanceService }, { token: PaymentService }, { token: DeviceFingerPrintService }, { token: LegalService }, { token: NextActionService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
609
2590
|
CoreLibraryService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryService, providedIn: 'root' });
|
|
610
2591
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryService, decorators: [{
|
|
611
2592
|
type: Injectable,
|
|
612
2593
|
args: [{
|
|
613
2594
|
providedIn: 'root',
|
|
614
2595
|
}]
|
|
615
|
-
}], ctorParameters: function () { return [{ type: SettingsService }, { type: CountryService }, { type: PaymentMethodsService }, { type: SavedMethodsService }, { type: UserBalanceService }, { type: LegalService }, { type:
|
|
2596
|
+
}], ctorParameters: function () { return [{ type: SettingsService }, { type: CountryService }, { type: PaymentMethodsService }, { type: SavedMethodsService }, { type: UserBalanceService }, { type: PaymentService }, { type: DeviceFingerPrintService }, { type: LegalService }, { type: NextActionService }]; } });
|
|
616
2597
|
|
|
617
2598
|
class HttpError extends AppError {
|
|
618
2599
|
constructor(error, req) {
|
|
@@ -669,10 +2650,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
|
|
|
669
2650
|
type: Injectable
|
|
670
2651
|
}], ctorParameters: function () { return [{ type: i1$1.Router }]; } });
|
|
671
2652
|
|
|
2653
|
+
class FormModule {
|
|
2654
|
+
}
|
|
2655
|
+
FormModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: FormModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2656
|
+
FormModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.7", ngImport: i0, type: FormModule, imports: [ReactiveFormsModule] });
|
|
2657
|
+
FormModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: FormModule, providers: [
|
|
2658
|
+
FormService,
|
|
2659
|
+
ControlConfigService,
|
|
2660
|
+
ZipConverter,
|
|
2661
|
+
EmailConverter,
|
|
2662
|
+
{ provide: convertersMapToken, useValue: convertersMap },
|
|
2663
|
+
], imports: [ReactiveFormsModule] });
|
|
2664
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: FormModule, decorators: [{
|
|
2665
|
+
type: NgModule,
|
|
2666
|
+
args: [{
|
|
2667
|
+
imports: [ReactiveFormsModule],
|
|
2668
|
+
providers: [
|
|
2669
|
+
FormService,
|
|
2670
|
+
ControlConfigService,
|
|
2671
|
+
ZipConverter,
|
|
2672
|
+
EmailConverter,
|
|
2673
|
+
{ provide: convertersMapToken, useValue: convertersMap },
|
|
2674
|
+
],
|
|
2675
|
+
}]
|
|
2676
|
+
}] });
|
|
2677
|
+
|
|
672
2678
|
class CoreLibraryModule {
|
|
673
2679
|
}
|
|
674
2680
|
CoreLibraryModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
675
|
-
CoreLibraryModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryModule, imports: [HttpClientModule] });
|
|
2681
|
+
CoreLibraryModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryModule, imports: [HttpClientModule, FormModule] });
|
|
676
2682
|
CoreLibraryModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryModule, providers: [
|
|
677
2683
|
{
|
|
678
2684
|
provide: HTTP_INTERCEPTORS,
|
|
@@ -683,11 +2689,25 @@ CoreLibraryModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", versi
|
|
|
683
2689
|
paymentMethodsResponseFactoryProvider,
|
|
684
2690
|
savedMethodsResponseFactoryProvider,
|
|
685
2691
|
userBalanceResponseFactoryProvider,
|
|
686
|
-
|
|
2692
|
+
initializeResponseFactoryProvider,
|
|
2693
|
+
submitRequestFactoryProvider,
|
|
2694
|
+
submitResponseFactoryProvider,
|
|
2695
|
+
syncRequestFactoryProvider,
|
|
2696
|
+
syncResponseFactoryProvider,
|
|
2697
|
+
statusRequestFactoryProvider,
|
|
2698
|
+
statusResponseFactoryProvider,
|
|
2699
|
+
checkStatusRequestFactoryProvider,
|
|
2700
|
+
checkStatusResponseFactoryProvider,
|
|
2701
|
+
{
|
|
2702
|
+
provide: nextActionsToken,
|
|
2703
|
+
useValue: nextActions,
|
|
2704
|
+
},
|
|
2705
|
+
...nextActions,
|
|
2706
|
+
], imports: [HttpClientModule, FormModule] });
|
|
687
2707
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: CoreLibraryModule, decorators: [{
|
|
688
2708
|
type: NgModule,
|
|
689
2709
|
args: [{
|
|
690
|
-
imports: [HttpClientModule],
|
|
2710
|
+
imports: [HttpClientModule, FormModule],
|
|
691
2711
|
providers: [
|
|
692
2712
|
{
|
|
693
2713
|
provide: HTTP_INTERCEPTORS,
|
|
@@ -698,6 +2718,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
|
|
|
698
2718
|
paymentMethodsResponseFactoryProvider,
|
|
699
2719
|
savedMethodsResponseFactoryProvider,
|
|
700
2720
|
userBalanceResponseFactoryProvider,
|
|
2721
|
+
initializeResponseFactoryProvider,
|
|
2722
|
+
submitRequestFactoryProvider,
|
|
2723
|
+
submitResponseFactoryProvider,
|
|
2724
|
+
syncRequestFactoryProvider,
|
|
2725
|
+
syncResponseFactoryProvider,
|
|
2726
|
+
statusRequestFactoryProvider,
|
|
2727
|
+
statusResponseFactoryProvider,
|
|
2728
|
+
checkStatusRequestFactoryProvider,
|
|
2729
|
+
checkStatusResponseFactoryProvider,
|
|
2730
|
+
{
|
|
2731
|
+
provide: nextActionsToken,
|
|
2732
|
+
useValue: nextActions,
|
|
2733
|
+
},
|
|
2734
|
+
...nextActions,
|
|
701
2735
|
],
|
|
702
2736
|
}]
|
|
703
2737
|
}] });
|