@spare-technologies/spare-link 0.1.0-beta.1 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +119 -63
- package/lib/commonjs/core/models/payment-return-params.js +245 -20
- package/lib/commonjs/core/models/payment-return-params.js.map +1 -1
- package/lib/commonjs/core/models/pending-session-record.js +2 -0
- package/lib/commonjs/core/models/pending-session-record.js.map +1 -0
- package/lib/commonjs/core/services/hosted-flow-controller.js +333 -0
- package/lib/commonjs/core/services/hosted-flow-controller.js.map +1 -0
- package/lib/commonjs/core/services/hosted-flow-state.js +96 -0
- package/lib/commonjs/core/services/hosted-flow-state.js.map +1 -0
- package/lib/commonjs/index.js +42 -164
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/internal/bank-redirect.js +20 -9
- package/lib/commonjs/internal/bank-redirect.js.map +1 -1
- package/lib/commonjs/internal/hosted/bridge-message.js +107 -0
- package/lib/commonjs/internal/hosted/bridge-message.js.map +1 -0
- package/lib/commonjs/internal/hosted/hosted-url.js +41 -0
- package/lib/commonjs/internal/hosted/hosted-url.js.map +1 -0
- package/lib/commonjs/internal/index.js +0 -7
- package/lib/commonjs/internal/index.js.map +1 -1
- package/lib/commonjs/internal/redact-uri.js +59 -15
- package/lib/commonjs/internal/redact-uri.js.map +1 -1
- package/lib/commonjs/internal/secure-store-pending-session-store.js +20 -25
- package/lib/commonjs/internal/secure-store-pending-session-store.js.map +1 -1
- package/lib/commonjs/internal/url-parts.js +145 -0
- package/lib/commonjs/internal/url-parts.js.map +1 -0
- package/lib/commonjs/public/index.js +0 -37
- package/lib/commonjs/public/index.js.map +1 -1
- package/lib/commonjs/public/payment-result.js +16 -4
- package/lib/commonjs/public/payment-result.js.map +1 -1
- package/lib/commonjs/public/recovery-result.js +7 -18
- package/lib/commonjs/public/recovery-result.js.map +1 -1
- package/lib/commonjs/public/spare-link-config.js +41 -16
- package/lib/commonjs/public/spare-link-config.js.map +1 -1
- package/lib/commonjs/public/spare-link-event.js +27 -33
- package/lib/commonjs/public/spare-link-event.js.map +1 -1
- package/lib/commonjs/public/spare-link-instance.js +67 -77
- package/lib/commonjs/public/spare-link-instance.js.map +1 -1
- package/lib/commonjs/public/spare-link-session.js +2 -9
- package/lib/commonjs/public/spare-link-session.js.map +1 -1
- package/lib/commonjs/public/spare-link.js +0 -12
- package/lib/commonjs/public/spare-link.js.map +1 -1
- package/lib/commonjs/ui/hooks/{use-payment-flow-state.js → use-hosted-flow-state.js} +4 -4
- package/lib/commonjs/ui/hooks/use-hosted-flow-state.js.map +1 -0
- package/lib/commonjs/ui/hosted/hosted-payment-page.js +177 -0
- package/lib/commonjs/ui/hosted/hosted-payment-page.js.map +1 -0
- package/lib/commonjs/ui/hosted/hosted-payment-webview.js +168 -0
- package/lib/commonjs/ui/hosted/hosted-payment-webview.js.map +1 -0
- package/lib/commonjs/ui/screens/index.js +3 -17
- package/lib/commonjs/ui/screens/index.js.map +1 -1
- package/lib/commonjs/ui/screens/page-unavailable-screen.js +101 -0
- package/lib/commonjs/ui/screens/page-unavailable-screen.js.map +1 -0
- package/lib/commonjs/ui/spare-link-host.js +220 -234
- package/lib/commonjs/ui/spare-link-host.js.map +1 -1
- package/lib/commonjs/ui/widgets/index.js +3 -10
- package/lib/commonjs/ui/widgets/index.js.map +1 -1
- package/lib/commonjs/version.js +1 -1
- package/lib/commonjs/version.js.map +1 -1
- package/lib/module/core/models/payment-return-params.js +235 -20
- package/lib/module/core/models/payment-return-params.js.map +1 -1
- package/lib/module/core/models/pending-session-record.js +2 -0
- package/lib/module/core/models/pending-session-record.js.map +1 -0
- package/lib/module/core/services/hosted-flow-controller.js +328 -0
- package/lib/module/core/services/hosted-flow-controller.js.map +1 -0
- package/lib/module/core/services/hosted-flow-state.js +91 -0
- package/lib/module/core/services/hosted-flow-state.js.map +1 -0
- package/lib/module/index.js +8 -22
- package/lib/module/index.js.map +1 -1
- package/lib/module/internal/bank-redirect.js +20 -9
- package/lib/module/internal/bank-redirect.js.map +1 -1
- package/lib/module/internal/hosted/bridge-message.js +104 -0
- package/lib/module/internal/hosted/bridge-message.js.map +1 -0
- package/lib/module/internal/hosted/hosted-url.js +36 -0
- package/lib/module/internal/hosted/hosted-url.js.map +1 -0
- package/lib/module/internal/index.js +0 -1
- package/lib/module/internal/index.js.map +1 -1
- package/lib/module/internal/redact-uri.js +59 -15
- package/lib/module/internal/redact-uri.js.map +1 -1
- package/lib/module/internal/secure-store-pending-session-store.js +20 -25
- package/lib/module/internal/secure-store-pending-session-store.js.map +1 -1
- package/lib/module/internal/url-parts.js +139 -0
- package/lib/module/internal/url-parts.js.map +1 -0
- package/lib/module/public/index.js +2 -3
- package/lib/module/public/index.js.map +1 -1
- package/lib/module/public/payment-result.js +16 -4
- package/lib/module/public/payment-result.js.map +1 -1
- package/lib/module/public/recovery-result.js +7 -17
- package/lib/module/public/recovery-result.js.map +1 -1
- package/lib/module/public/spare-link-config.js +42 -15
- package/lib/module/public/spare-link-config.js.map +1 -1
- package/lib/module/public/spare-link-event.js +27 -33
- package/lib/module/public/spare-link-event.js.map +1 -1
- package/lib/module/public/spare-link-instance.js +68 -72
- package/lib/module/public/spare-link-instance.js.map +1 -1
- package/lib/module/public/spare-link-session.js +2 -9
- package/lib/module/public/spare-link-session.js.map +1 -1
- package/lib/module/public/spare-link.js +1 -1
- package/lib/module/public/spare-link.js.map +1 -1
- package/lib/module/ui/hooks/{use-payment-flow-state.js → use-hosted-flow-state.js} +3 -3
- package/lib/module/ui/hooks/use-hosted-flow-state.js.map +1 -0
- package/lib/module/ui/hosted/hosted-payment-page.js +175 -0
- package/lib/module/ui/hosted/hosted-payment-page.js.map +1 -0
- package/lib/module/ui/hosted/hosted-payment-webview.js +163 -0
- package/lib/module/ui/hosted/hosted-payment-webview.js.map +1 -0
- package/lib/module/ui/screens/index.js +1 -3
- package/lib/module/ui/screens/index.js.map +1 -1
- package/lib/module/ui/screens/page-unavailable-screen.js +97 -0
- package/lib/module/ui/screens/page-unavailable-screen.js.map +1 -0
- package/lib/module/ui/spare-link-host.js +221 -236
- package/lib/module/ui/spare-link-host.js.map +1 -1
- package/lib/module/ui/widgets/index.js +1 -2
- package/lib/module/ui/widgets/index.js.map +1 -1
- package/lib/module/version.js +1 -1
- package/lib/module/version.js.map +1 -1
- package/lib/typescript/commonjs/core/models/index.d.ts +1 -123
- package/lib/typescript/commonjs/core/models/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/core/models/payment-return-params.d.ts +91 -8
- package/lib/typescript/commonjs/core/models/payment-return-params.d.ts.map +1 -1
- package/lib/typescript/commonjs/core/models/pending-session-record.d.ts +11 -0
- package/lib/typescript/commonjs/core/models/pending-session-record.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/services/hosted-flow-controller.d.ts +119 -0
- package/lib/typescript/commonjs/core/services/hosted-flow-controller.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/services/hosted-flow-state.d.ts +75 -0
- package/lib/typescript/commonjs/core/services/hosted-flow-state.d.ts.map +1 -0
- package/lib/typescript/commonjs/index.d.ts +5 -14
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/internal/bank-redirect.d.ts.map +1 -1
- package/lib/typescript/commonjs/internal/hosted/bridge-message.d.ts +44 -0
- package/lib/typescript/commonjs/internal/hosted/bridge-message.d.ts.map +1 -0
- package/lib/typescript/commonjs/internal/hosted/hosted-url.d.ts +30 -0
- package/lib/typescript/commonjs/internal/hosted/hosted-url.d.ts.map +1 -0
- package/lib/typescript/commonjs/internal/index.d.ts +0 -1
- package/lib/typescript/commonjs/internal/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/internal/redact-uri.d.ts +21 -1
- package/lib/typescript/commonjs/internal/redact-uri.d.ts.map +1 -1
- package/lib/typescript/commonjs/internal/secure-store-pending-session-store.d.ts +3 -2
- package/lib/typescript/commonjs/internal/secure-store-pending-session-store.d.ts.map +1 -1
- package/lib/typescript/commonjs/internal/url-parts.d.ts +46 -0
- package/lib/typescript/commonjs/internal/url-parts.d.ts.map +1 -0
- package/lib/typescript/commonjs/public/index.d.ts +4 -6
- package/lib/typescript/commonjs/public/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/public/payment-result.d.ts +50 -12
- package/lib/typescript/commonjs/public/payment-result.d.ts.map +1 -1
- package/lib/typescript/commonjs/public/recovery-result.d.ts +11 -20
- package/lib/typescript/commonjs/public/recovery-result.d.ts.map +1 -1
- package/lib/typescript/commonjs/public/spare-link-config.d.ts +13 -31
- package/lib/typescript/commonjs/public/spare-link-config.d.ts.map +1 -1
- package/lib/typescript/commonjs/public/spare-link-event.d.ts +29 -31
- package/lib/typescript/commonjs/public/spare-link-event.d.ts.map +1 -1
- package/lib/typescript/commonjs/public/spare-link-host-api.d.ts +1 -12
- package/lib/typescript/commonjs/public/spare-link-host-api.d.ts.map +1 -1
- package/lib/typescript/commonjs/public/spare-link-instance.d.ts +26 -20
- package/lib/typescript/commonjs/public/spare-link-instance.d.ts.map +1 -1
- package/lib/typescript/commonjs/public/spare-link-session.d.ts +3 -8
- package/lib/typescript/commonjs/public/spare-link-session.d.ts.map +1 -1
- package/lib/typescript/commonjs/public/spare-link.d.ts +1 -1
- package/lib/typescript/commonjs/public/spare-link.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/use-hosted-flow-state.d.ts +9 -0
- package/lib/typescript/commonjs/ui/hooks/use-hosted-flow-state.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/hosted/hosted-payment-page.d.ts +17 -0
- package/lib/typescript/commonjs/ui/hosted/hosted-payment-page.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/hosted/hosted-payment-webview.d.ts +43 -0
- package/lib/typescript/commonjs/ui/hosted/hosted-payment-webview.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/screens/index.d.ts +1 -3
- package/lib/typescript/commonjs/ui/screens/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/page-unavailable-screen.d.ts +18 -0
- package/lib/typescript/commonjs/ui/screens/page-unavailable-screen.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/spare-link-host.d.ts +4 -5
- package/lib/typescript/commonjs/ui/spare-link-host.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/widgets/index.d.ts +1 -2
- package/lib/typescript/commonjs/ui/widgets/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/version.d.ts +1 -1
- package/lib/typescript/commonjs/version.d.ts.map +1 -1
- package/lib/typescript/module/core/models/index.d.ts +1 -123
- package/lib/typescript/module/core/models/index.d.ts.map +1 -1
- package/lib/typescript/module/core/models/payment-return-params.d.ts +91 -8
- package/lib/typescript/module/core/models/payment-return-params.d.ts.map +1 -1
- package/lib/typescript/module/core/models/pending-session-record.d.ts +11 -0
- package/lib/typescript/module/core/models/pending-session-record.d.ts.map +1 -0
- package/lib/typescript/module/core/services/hosted-flow-controller.d.ts +119 -0
- package/lib/typescript/module/core/services/hosted-flow-controller.d.ts.map +1 -0
- package/lib/typescript/module/core/services/hosted-flow-state.d.ts +75 -0
- package/lib/typescript/module/core/services/hosted-flow-state.d.ts.map +1 -0
- package/lib/typescript/module/index.d.ts +5 -14
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/internal/bank-redirect.d.ts.map +1 -1
- package/lib/typescript/module/internal/hosted/bridge-message.d.ts +44 -0
- package/lib/typescript/module/internal/hosted/bridge-message.d.ts.map +1 -0
- package/lib/typescript/module/internal/hosted/hosted-url.d.ts +30 -0
- package/lib/typescript/module/internal/hosted/hosted-url.d.ts.map +1 -0
- package/lib/typescript/module/internal/index.d.ts +0 -1
- package/lib/typescript/module/internal/index.d.ts.map +1 -1
- package/lib/typescript/module/internal/redact-uri.d.ts +21 -1
- package/lib/typescript/module/internal/redact-uri.d.ts.map +1 -1
- package/lib/typescript/module/internal/secure-store-pending-session-store.d.ts +3 -2
- package/lib/typescript/module/internal/secure-store-pending-session-store.d.ts.map +1 -1
- package/lib/typescript/module/internal/url-parts.d.ts +46 -0
- package/lib/typescript/module/internal/url-parts.d.ts.map +1 -0
- package/lib/typescript/module/public/index.d.ts +4 -6
- package/lib/typescript/module/public/index.d.ts.map +1 -1
- package/lib/typescript/module/public/payment-result.d.ts +50 -12
- package/lib/typescript/module/public/payment-result.d.ts.map +1 -1
- package/lib/typescript/module/public/recovery-result.d.ts +11 -20
- package/lib/typescript/module/public/recovery-result.d.ts.map +1 -1
- package/lib/typescript/module/public/spare-link-config.d.ts +13 -31
- package/lib/typescript/module/public/spare-link-config.d.ts.map +1 -1
- package/lib/typescript/module/public/spare-link-event.d.ts +29 -31
- package/lib/typescript/module/public/spare-link-event.d.ts.map +1 -1
- package/lib/typescript/module/public/spare-link-host-api.d.ts +1 -12
- package/lib/typescript/module/public/spare-link-host-api.d.ts.map +1 -1
- package/lib/typescript/module/public/spare-link-instance.d.ts +26 -20
- package/lib/typescript/module/public/spare-link-instance.d.ts.map +1 -1
- package/lib/typescript/module/public/spare-link-session.d.ts +3 -8
- package/lib/typescript/module/public/spare-link-session.d.ts.map +1 -1
- package/lib/typescript/module/public/spare-link.d.ts +1 -1
- package/lib/typescript/module/public/spare-link.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/use-hosted-flow-state.d.ts +9 -0
- package/lib/typescript/module/ui/hooks/use-hosted-flow-state.d.ts.map +1 -0
- package/lib/typescript/module/ui/hosted/hosted-payment-page.d.ts +17 -0
- package/lib/typescript/module/ui/hosted/hosted-payment-page.d.ts.map +1 -0
- package/lib/typescript/module/ui/hosted/hosted-payment-webview.d.ts +43 -0
- package/lib/typescript/module/ui/hosted/hosted-payment-webview.d.ts.map +1 -0
- package/lib/typescript/module/ui/screens/index.d.ts +1 -3
- package/lib/typescript/module/ui/screens/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/page-unavailable-screen.d.ts +18 -0
- package/lib/typescript/module/ui/screens/page-unavailable-screen.d.ts.map +1 -0
- package/lib/typescript/module/ui/spare-link-host.d.ts +4 -5
- package/lib/typescript/module/ui/spare-link-host.d.ts.map +1 -1
- package/lib/typescript/module/ui/widgets/index.d.ts +1 -2
- package/lib/typescript/module/ui/widgets/index.d.ts.map +1 -1
- package/lib/typescript/module/version.d.ts +1 -1
- package/lib/typescript/module/version.d.ts.map +1 -1
- package/package.json +24 -22
- package/plugins/with-spare-link.js +6 -26
- package/src/core/models/index.ts +1 -139
- package/src/core/models/payment-return-params.ts +269 -21
- package/src/core/models/pending-session-record.ts +10 -0
- package/src/core/services/hosted-flow-controller.ts +374 -0
- package/src/core/services/hosted-flow-state.ts +123 -0
- package/src/index.ts +20 -89
- package/src/internal/bank-redirect.ts +23 -9
- package/src/internal/hosted/bridge-message.ts +106 -0
- package/src/internal/hosted/hosted-url.ts +33 -0
- package/src/internal/index.ts +0 -1
- package/src/internal/redact-uri.ts +69 -15
- package/src/internal/secure-store-pending-session-store.ts +28 -49
- package/src/internal/url-parts.ts +134 -0
- package/src/public/index.ts +2 -24
- package/src/public/payment-result.ts +50 -12
- package/src/public/recovery-result.ts +16 -25
- package/src/public/spare-link-config.ts +56 -43
- package/src/public/spare-link-event.ts +33 -42
- package/src/public/spare-link-host-api.ts +1 -14
- package/src/public/spare-link-instance.ts +57 -65
- package/src/public/spare-link-session.ts +4 -16
- package/src/public/spare-link.ts +1 -1
- package/src/ui/hooks/use-hosted-flow-state.ts +16 -0
- package/src/ui/hosted/hosted-payment-page.tsx +178 -0
- package/src/ui/hosted/hosted-payment-webview.tsx +164 -0
- package/src/ui/screens/index.ts +4 -6
- package/src/ui/screens/page-unavailable-screen.tsx +94 -0
- package/src/ui/spare-link-host.tsx +227 -247
- package/src/ui/widgets/index.ts +1 -2
- package/src/version.ts +1 -1
- package/CHANGELOG.md +0 -25
- package/lib/commonjs/core/client/link-api-client.js +0 -297
- package/lib/commonjs/core/client/link-api-client.js.map +0 -1
- package/lib/commonjs/core/errors/payment-api-error.js +0 -35
- package/lib/commonjs/core/errors/payment-api-error.js.map +0 -1
- package/lib/commonjs/core/models/link-session-status.js +0 -14
- package/lib/commonjs/core/models/link-session-status.js.map +0 -1
- package/lib/commonjs/core/models/payment-type.js +0 -45
- package/lib/commonjs/core/models/payment-type.js.map +0 -1
- package/lib/commonjs/core/models/wire-mappers.js +0 -277
- package/lib/commonjs/core/models/wire-mappers.js.map +0 -1
- package/lib/commonjs/core/services/consent-presenter.js +0 -150
- package/lib/commonjs/core/services/consent-presenter.js.map +0 -1
- package/lib/commonjs/core/services/execute-resume-if-needed.js +0 -216
- package/lib/commonjs/core/services/execute-resume-if-needed.js.map +0 -1
- package/lib/commonjs/core/services/multi-payment-rules-presenter.js +0 -151
- package/lib/commonjs/core/services/multi-payment-rules-presenter.js.map +0 -1
- package/lib/commonjs/core/services/payment-flow-controller.js +0 -547
- package/lib/commonjs/core/services/payment-flow-controller.js.map +0 -1
- package/lib/commonjs/core/services/payment-flow-state.js +0 -110
- package/lib/commonjs/core/services/payment-flow-state.js.map +0 -1
- package/lib/commonjs/core/services/payment-result-mapper.js +0 -49
- package/lib/commonjs/core/services/payment-result-mapper.js.map +0 -1
- package/lib/commonjs/core/services/presentation-utils.js +0 -11
- package/lib/commonjs/core/services/presentation-utils.js.map +0 -1
- package/lib/commonjs/core/services/redirect-buffer.js +0 -40
- package/lib/commonjs/core/services/redirect-buffer.js.map +0 -1
- package/lib/commonjs/core/services/user-friendly-messages.js +0 -46
- package/lib/commonjs/core/services/user-friendly-messages.js.map +0 -1
- package/lib/commonjs/internal/telemetry-collector.js +0 -80
- package/lib/commonjs/internal/telemetry-collector.js.map +0 -1
- package/lib/commonjs/public/constants.js +0 -21
- package/lib/commonjs/public/constants.js.map +0 -1
- package/lib/commonjs/public/spare-link-callbacks.js +0 -6
- package/lib/commonjs/public/spare-link-callbacks.js.map +0 -1
- package/lib/commonjs/ui/consent/charge-bearer-display.js +0 -99
- package/lib/commonjs/ui/consent/charge-bearer-display.js.map +0 -1
- package/lib/commonjs/ui/consent/consent-accordion.js +0 -94
- package/lib/commonjs/ui/consent/consent-accordion.js.map +0 -1
- package/lib/commonjs/ui/consent/consent-summary-section.js +0 -27
- package/lib/commonjs/ui/consent/consent-summary-section.js.map +0 -1
- package/lib/commonjs/ui/consent/cop-information.js +0 -168
- package/lib/commonjs/ui/consent/cop-information.js.map +0 -1
- package/lib/commonjs/ui/consent/international-payment-summary.js +0 -98
- package/lib/commonjs/ui/consent/international-payment-summary.js.map +0 -1
- package/lib/commonjs/ui/consent/label-value-rows.js +0 -59
- package/lib/commonjs/ui/consent/label-value-rows.js.map +0 -1
- package/lib/commonjs/ui/consent/multi-payment-rules-list.js +0 -130
- package/lib/commonjs/ui/consent/multi-payment-rules-list.js.map +0 -1
- package/lib/commonjs/ui/consent/multi-payment-summary.js +0 -99
- package/lib/commonjs/ui/consent/multi-payment-summary.js.map +0 -1
- package/lib/commonjs/ui/consent/single-payment-summary.js +0 -158
- package/lib/commonjs/ui/consent/single-payment-summary.js.map +0 -1
- package/lib/commonjs/ui/consent/terms-link.js +0 -35
- package/lib/commonjs/ui/consent/terms-link.js.map +0 -1
- package/lib/commonjs/ui/hooks/use-payment-flow-state.js.map +0 -1
- package/lib/commonjs/ui/payment-flow-page.js +0 -235
- package/lib/commonjs/ui/payment-flow-page.js.map +0 -1
- package/lib/commonjs/ui/screens/bank-selection-screen.js +0 -215
- package/lib/commonjs/ui/screens/bank-selection-screen.js.map +0 -1
- package/lib/commonjs/ui/screens/consent-details-screen.js +0 -124
- package/lib/commonjs/ui/screens/consent-details-screen.js.map +0 -1
- package/lib/commonjs/ui/screens/mandate-setup-success-screen.js +0 -79
- package/lib/commonjs/ui/screens/mandate-setup-success-screen.js.map +0 -1
- package/lib/commonjs/ui/widgets/layout-w-header.js +0 -106
- package/lib/commonjs/ui/widgets/layout-w-header.js.map +0 -1
- package/lib/commonjs/ui/widgets/stepper.js +0 -124
- package/lib/commonjs/ui/widgets/stepper.js.map +0 -1
- package/lib/module/core/client/link-api-client.js +0 -292
- package/lib/module/core/client/link-api-client.js.map +0 -1
- package/lib/module/core/errors/payment-api-error.js +0 -29
- package/lib/module/core/errors/payment-api-error.js.map +0 -1
- package/lib/module/core/models/link-session-status.js +0 -10
- package/lib/module/core/models/link-session-status.js.map +0 -1
- package/lib/module/core/models/payment-type.js +0 -36
- package/lib/module/core/models/payment-type.js.map +0 -1
- package/lib/module/core/models/wire-mappers.js +0 -263
- package/lib/module/core/models/wire-mappers.js.map +0 -1
- package/lib/module/core/services/consent-presenter.js +0 -140
- package/lib/module/core/services/consent-presenter.js.map +0 -1
- package/lib/module/core/services/execute-resume-if-needed.js +0 -211
- package/lib/module/core/services/execute-resume-if-needed.js.map +0 -1
- package/lib/module/core/services/multi-payment-rules-presenter.js +0 -146
- package/lib/module/core/services/multi-payment-rules-presenter.js.map +0 -1
- package/lib/module/core/services/payment-flow-controller.js +0 -544
- package/lib/module/core/services/payment-flow-controller.js.map +0 -1
- package/lib/module/core/services/payment-flow-state.js +0 -106
- package/lib/module/core/services/payment-flow-state.js.map +0 -1
- package/lib/module/core/services/payment-result-mapper.js +0 -45
- package/lib/module/core/services/payment-result-mapper.js.map +0 -1
- package/lib/module/core/services/presentation-utils.js +0 -7
- package/lib/module/core/services/presentation-utils.js.map +0 -1
- package/lib/module/core/services/redirect-buffer.js +0 -33
- package/lib/module/core/services/redirect-buffer.js.map +0 -1
- package/lib/module/core/services/user-friendly-messages.js +0 -42
- package/lib/module/core/services/user-friendly-messages.js.map +0 -1
- package/lib/module/internal/telemetry-collector.js +0 -75
- package/lib/module/internal/telemetry-collector.js.map +0 -1
- package/lib/module/public/constants.js +0 -17
- package/lib/module/public/constants.js.map +0 -1
- package/lib/module/public/spare-link-callbacks.js +0 -4
- package/lib/module/public/spare-link-callbacks.js.map +0 -1
- package/lib/module/ui/consent/charge-bearer-display.js +0 -95
- package/lib/module/ui/consent/charge-bearer-display.js.map +0 -1
- package/lib/module/ui/consent/consent-accordion.js +0 -90
- package/lib/module/ui/consent/consent-accordion.js.map +0 -1
- package/lib/module/ui/consent/consent-summary-section.js +0 -23
- package/lib/module/ui/consent/consent-summary-section.js.map +0 -1
- package/lib/module/ui/consent/cop-information.js +0 -165
- package/lib/module/ui/consent/cop-information.js.map +0 -1
- package/lib/module/ui/consent/international-payment-summary.js +0 -94
- package/lib/module/ui/consent/international-payment-summary.js.map +0 -1
- package/lib/module/ui/consent/label-value-rows.js +0 -55
- package/lib/module/ui/consent/label-value-rows.js.map +0 -1
- package/lib/module/ui/consent/multi-payment-rules-list.js +0 -125
- package/lib/module/ui/consent/multi-payment-rules-list.js.map +0 -1
- package/lib/module/ui/consent/multi-payment-summary.js +0 -95
- package/lib/module/ui/consent/multi-payment-summary.js.map +0 -1
- package/lib/module/ui/consent/single-payment-summary.js +0 -154
- package/lib/module/ui/consent/single-payment-summary.js.map +0 -1
- package/lib/module/ui/consent/terms-link.js +0 -31
- package/lib/module/ui/consent/terms-link.js.map +0 -1
- package/lib/module/ui/hooks/use-payment-flow-state.js.map +0 -1
- package/lib/module/ui/payment-flow-page.js +0 -232
- package/lib/module/ui/payment-flow-page.js.map +0 -1
- package/lib/module/ui/screens/bank-selection-screen.js +0 -211
- package/lib/module/ui/screens/bank-selection-screen.js.map +0 -1
- package/lib/module/ui/screens/consent-details-screen.js +0 -120
- package/lib/module/ui/screens/consent-details-screen.js.map +0 -1
- package/lib/module/ui/screens/mandate-setup-success-screen.js +0 -75
- package/lib/module/ui/screens/mandate-setup-success-screen.js.map +0 -1
- package/lib/module/ui/widgets/layout-w-header.js +0 -102
- package/lib/module/ui/widgets/layout-w-header.js.map +0 -1
- package/lib/module/ui/widgets/stepper.js +0 -120
- package/lib/module/ui/widgets/stepper.js.map +0 -1
- package/lib/typescript/commonjs/core/client/link-api-client.d.ts +0 -70
- package/lib/typescript/commonjs/core/client/link-api-client.d.ts.map +0 -1
- package/lib/typescript/commonjs/core/errors/payment-api-error.d.ts +0 -15
- package/lib/typescript/commonjs/core/errors/payment-api-error.d.ts.map +0 -1
- package/lib/typescript/commonjs/core/models/link-session-status.d.ts +0 -6
- package/lib/typescript/commonjs/core/models/link-session-status.d.ts.map +0 -1
- package/lib/typescript/commonjs/core/models/payment-type.d.ts +0 -18
- package/lib/typescript/commonjs/core/models/payment-type.d.ts.map +0 -1
- package/lib/typescript/commonjs/core/models/wire-mappers.d.ts +0 -19
- package/lib/typescript/commonjs/core/models/wire-mappers.d.ts.map +0 -1
- package/lib/typescript/commonjs/core/services/consent-presenter.d.ts +0 -67
- package/lib/typescript/commonjs/core/services/consent-presenter.d.ts.map +0 -1
- package/lib/typescript/commonjs/core/services/execute-resume-if-needed.d.ts +0 -32
- package/lib/typescript/commonjs/core/services/execute-resume-if-needed.d.ts.map +0 -1
- package/lib/typescript/commonjs/core/services/multi-payment-rules-presenter.d.ts +0 -9
- package/lib/typescript/commonjs/core/services/multi-payment-rules-presenter.d.ts.map +0 -1
- package/lib/typescript/commonjs/core/services/payment-flow-controller.d.ts +0 -146
- package/lib/typescript/commonjs/core/services/payment-flow-controller.d.ts.map +0 -1
- package/lib/typescript/commonjs/core/services/payment-flow-state.d.ts +0 -64
- package/lib/typescript/commonjs/core/services/payment-flow-state.d.ts.map +0 -1
- package/lib/typescript/commonjs/core/services/payment-result-mapper.d.ts +0 -5
- package/lib/typescript/commonjs/core/services/payment-result-mapper.d.ts.map +0 -1
- package/lib/typescript/commonjs/core/services/presentation-utils.d.ts +0 -5
- package/lib/typescript/commonjs/core/services/presentation-utils.d.ts.map +0 -1
- package/lib/typescript/commonjs/core/services/redirect-buffer.d.ts +0 -6
- package/lib/typescript/commonjs/core/services/redirect-buffer.d.ts.map +0 -1
- package/lib/typescript/commonjs/core/services/user-friendly-messages.d.ts +0 -6
- package/lib/typescript/commonjs/core/services/user-friendly-messages.d.ts.map +0 -1
- package/lib/typescript/commonjs/internal/telemetry-collector.d.ts +0 -2
- package/lib/typescript/commonjs/internal/telemetry-collector.d.ts.map +0 -1
- package/lib/typescript/commonjs/public/constants.d.ts +0 -12
- package/lib/typescript/commonjs/public/constants.d.ts.map +0 -1
- package/lib/typescript/commonjs/public/spare-link-callbacks.d.ts +0 -14
- package/lib/typescript/commonjs/public/spare-link-callbacks.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/consent/charge-bearer-display.d.ts +0 -5
- package/lib/typescript/commonjs/ui/consent/charge-bearer-display.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/consent/consent-accordion.d.ts +0 -10
- package/lib/typescript/commonjs/ui/consent/consent-accordion.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/consent/consent-summary-section.d.ts +0 -6
- package/lib/typescript/commonjs/ui/consent/consent-summary-section.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/consent/cop-information.d.ts +0 -6
- package/lib/typescript/commonjs/ui/consent/cop-information.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/consent/international-payment-summary.d.ts +0 -6
- package/lib/typescript/commonjs/ui/consent/international-payment-summary.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/consent/label-value-rows.d.ts +0 -10
- package/lib/typescript/commonjs/ui/consent/label-value-rows.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/consent/multi-payment-rules-list.d.ts +0 -15
- package/lib/typescript/commonjs/ui/consent/multi-payment-rules-list.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/consent/multi-payment-summary.d.ts +0 -6
- package/lib/typescript/commonjs/ui/consent/multi-payment-summary.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/consent/single-payment-summary.d.ts +0 -6
- package/lib/typescript/commonjs/ui/consent/single-payment-summary.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/consent/terms-link.d.ts +0 -2
- package/lib/typescript/commonjs/ui/consent/terms-link.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/hooks/use-payment-flow-state.d.ts +0 -9
- package/lib/typescript/commonjs/ui/hooks/use-payment-flow-state.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/payment-flow-page.d.ts +0 -20
- package/lib/typescript/commonjs/ui/payment-flow-page.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/screens/bank-selection-screen.d.ts +0 -15
- package/lib/typescript/commonjs/ui/screens/bank-selection-screen.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/screens/consent-details-screen.d.ts +0 -13
- package/lib/typescript/commonjs/ui/screens/consent-details-screen.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/screens/mandate-setup-success-screen.d.ts +0 -10
- package/lib/typescript/commonjs/ui/screens/mandate-setup-success-screen.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/widgets/layout-w-header.d.ts +0 -20
- package/lib/typescript/commonjs/ui/widgets/layout-w-header.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/widgets/stepper.d.ts +0 -15
- package/lib/typescript/commonjs/ui/widgets/stepper.d.ts.map +0 -1
- package/lib/typescript/module/core/client/link-api-client.d.ts +0 -70
- package/lib/typescript/module/core/client/link-api-client.d.ts.map +0 -1
- package/lib/typescript/module/core/errors/payment-api-error.d.ts +0 -15
- package/lib/typescript/module/core/errors/payment-api-error.d.ts.map +0 -1
- package/lib/typescript/module/core/models/link-session-status.d.ts +0 -6
- package/lib/typescript/module/core/models/link-session-status.d.ts.map +0 -1
- package/lib/typescript/module/core/models/payment-type.d.ts +0 -18
- package/lib/typescript/module/core/models/payment-type.d.ts.map +0 -1
- package/lib/typescript/module/core/models/wire-mappers.d.ts +0 -19
- package/lib/typescript/module/core/models/wire-mappers.d.ts.map +0 -1
- package/lib/typescript/module/core/services/consent-presenter.d.ts +0 -67
- package/lib/typescript/module/core/services/consent-presenter.d.ts.map +0 -1
- package/lib/typescript/module/core/services/execute-resume-if-needed.d.ts +0 -32
- package/lib/typescript/module/core/services/execute-resume-if-needed.d.ts.map +0 -1
- package/lib/typescript/module/core/services/multi-payment-rules-presenter.d.ts +0 -9
- package/lib/typescript/module/core/services/multi-payment-rules-presenter.d.ts.map +0 -1
- package/lib/typescript/module/core/services/payment-flow-controller.d.ts +0 -146
- package/lib/typescript/module/core/services/payment-flow-controller.d.ts.map +0 -1
- package/lib/typescript/module/core/services/payment-flow-state.d.ts +0 -64
- package/lib/typescript/module/core/services/payment-flow-state.d.ts.map +0 -1
- package/lib/typescript/module/core/services/payment-result-mapper.d.ts +0 -5
- package/lib/typescript/module/core/services/payment-result-mapper.d.ts.map +0 -1
- package/lib/typescript/module/core/services/presentation-utils.d.ts +0 -5
- package/lib/typescript/module/core/services/presentation-utils.d.ts.map +0 -1
- package/lib/typescript/module/core/services/redirect-buffer.d.ts +0 -6
- package/lib/typescript/module/core/services/redirect-buffer.d.ts.map +0 -1
- package/lib/typescript/module/core/services/user-friendly-messages.d.ts +0 -6
- package/lib/typescript/module/core/services/user-friendly-messages.d.ts.map +0 -1
- package/lib/typescript/module/internal/telemetry-collector.d.ts +0 -2
- package/lib/typescript/module/internal/telemetry-collector.d.ts.map +0 -1
- package/lib/typescript/module/public/constants.d.ts +0 -12
- package/lib/typescript/module/public/constants.d.ts.map +0 -1
- package/lib/typescript/module/public/spare-link-callbacks.d.ts +0 -14
- package/lib/typescript/module/public/spare-link-callbacks.d.ts.map +0 -1
- package/lib/typescript/module/ui/consent/charge-bearer-display.d.ts +0 -5
- package/lib/typescript/module/ui/consent/charge-bearer-display.d.ts.map +0 -1
- package/lib/typescript/module/ui/consent/consent-accordion.d.ts +0 -10
- package/lib/typescript/module/ui/consent/consent-accordion.d.ts.map +0 -1
- package/lib/typescript/module/ui/consent/consent-summary-section.d.ts +0 -6
- package/lib/typescript/module/ui/consent/consent-summary-section.d.ts.map +0 -1
- package/lib/typescript/module/ui/consent/cop-information.d.ts +0 -6
- package/lib/typescript/module/ui/consent/cop-information.d.ts.map +0 -1
- package/lib/typescript/module/ui/consent/international-payment-summary.d.ts +0 -6
- package/lib/typescript/module/ui/consent/international-payment-summary.d.ts.map +0 -1
- package/lib/typescript/module/ui/consent/label-value-rows.d.ts +0 -10
- package/lib/typescript/module/ui/consent/label-value-rows.d.ts.map +0 -1
- package/lib/typescript/module/ui/consent/multi-payment-rules-list.d.ts +0 -15
- package/lib/typescript/module/ui/consent/multi-payment-rules-list.d.ts.map +0 -1
- package/lib/typescript/module/ui/consent/multi-payment-summary.d.ts +0 -6
- package/lib/typescript/module/ui/consent/multi-payment-summary.d.ts.map +0 -1
- package/lib/typescript/module/ui/consent/single-payment-summary.d.ts +0 -6
- package/lib/typescript/module/ui/consent/single-payment-summary.d.ts.map +0 -1
- package/lib/typescript/module/ui/consent/terms-link.d.ts +0 -2
- package/lib/typescript/module/ui/consent/terms-link.d.ts.map +0 -1
- package/lib/typescript/module/ui/hooks/use-payment-flow-state.d.ts +0 -9
- package/lib/typescript/module/ui/hooks/use-payment-flow-state.d.ts.map +0 -1
- package/lib/typescript/module/ui/payment-flow-page.d.ts +0 -20
- package/lib/typescript/module/ui/payment-flow-page.d.ts.map +0 -1
- package/lib/typescript/module/ui/screens/bank-selection-screen.d.ts +0 -15
- package/lib/typescript/module/ui/screens/bank-selection-screen.d.ts.map +0 -1
- package/lib/typescript/module/ui/screens/consent-details-screen.d.ts +0 -13
- package/lib/typescript/module/ui/screens/consent-details-screen.d.ts.map +0 -1
- package/lib/typescript/module/ui/screens/mandate-setup-success-screen.d.ts +0 -10
- package/lib/typescript/module/ui/screens/mandate-setup-success-screen.d.ts.map +0 -1
- package/lib/typescript/module/ui/widgets/layout-w-header.d.ts +0 -20
- package/lib/typescript/module/ui/widgets/layout-w-header.d.ts.map +0 -1
- package/lib/typescript/module/ui/widgets/stepper.d.ts +0 -15
- package/lib/typescript/module/ui/widgets/stepper.d.ts.map +0 -1
- package/src/core/client/link-api-client.ts +0 -414
- package/src/core/errors/payment-api-error.ts +0 -35
- package/src/core/models/link-session-status.ts +0 -7
- package/src/core/models/payment-type.ts +0 -54
- package/src/core/models/wire-mappers.ts +0 -315
- package/src/core/services/consent-presenter.ts +0 -213
- package/src/core/services/execute-resume-if-needed.ts +0 -243
- package/src/core/services/multi-payment-rules-presenter.ts +0 -158
- package/src/core/services/payment-flow-controller.ts +0 -607
- package/src/core/services/payment-flow-state.ts +0 -124
- package/src/core/services/payment-result-mapper.ts +0 -41
- package/src/core/services/presentation-utils.ts +0 -4
- package/src/core/services/redirect-buffer.ts +0 -34
- package/src/core/services/user-friendly-messages.ts +0 -39
- package/src/internal/telemetry-collector.ts +0 -90
- package/src/public/constants.ts +0 -14
- package/src/public/spare-link-callbacks.ts +0 -20
- package/src/ui/consent/charge-bearer-display.tsx +0 -68
- package/src/ui/consent/consent-accordion.tsx +0 -89
- package/src/ui/consent/consent-summary-section.tsx +0 -19
- package/src/ui/consent/cop-information.tsx +0 -121
- package/src/ui/consent/international-payment-summary.tsx +0 -83
- package/src/ui/consent/label-value-rows.tsx +0 -50
- package/src/ui/consent/multi-payment-rules-list.tsx +0 -138
- package/src/ui/consent/multi-payment-summary.tsx +0 -82
- package/src/ui/consent/single-payment-summary.tsx +0 -123
- package/src/ui/consent/terms-link.tsx +0 -27
- package/src/ui/hooks/use-payment-flow-state.ts +0 -16
- package/src/ui/payment-flow-page.tsx +0 -254
- package/src/ui/screens/bank-selection-screen.tsx +0 -209
- package/src/ui/screens/consent-details-screen.tsx +0 -106
- package/src/ui/screens/mandate-setup-success-screen.tsx +0 -72
- package/src/ui/widgets/layout-w-header.tsx +0 -89
- package/src/ui/widgets/stepper.tsx +0 -126
|
@@ -1,607 +0,0 @@
|
|
|
1
|
-
import { createLogger } from '../../internal/logger';
|
|
2
|
-
import { redactPaymentReturnUri } from '../../internal/redact-uri';
|
|
3
|
-
import {
|
|
4
|
-
DEFAULT_AWAITING_CALLBACK_POLL_MS,
|
|
5
|
-
DEFAULT_AWAITING_CALLBACK_TIMEOUT_MS,
|
|
6
|
-
} from '../../public/constants';
|
|
7
|
-
import type { PaymentEnvironment } from '../../public/spare-link-config';
|
|
8
|
-
/** Simple string tag for internal controller callbacks — not the public SpareLinkEvent. */
|
|
9
|
-
type PaymentFlowEventTag =
|
|
10
|
-
| 'initialized'
|
|
11
|
-
| 'sessionLoaded'
|
|
12
|
-
| 'consentStarted'
|
|
13
|
-
| 'redirectToBank'
|
|
14
|
-
| 'bankCallbackReceived'
|
|
15
|
-
| 'succeeded'
|
|
16
|
-
| 'failed'
|
|
17
|
-
| 'cancelled'
|
|
18
|
-
| 'abandoned';
|
|
19
|
-
import type { LinkApiClient } from '../client/link-api-client';
|
|
20
|
-
import { isPaymentApiError } from '../errors/payment-api-error';
|
|
21
|
-
import type { ConsentResponse, CopResponse, LinkSessionResponse, ProviderSummary } from '../models';
|
|
22
|
-
import { isBankCallbackReceivedStatus } from '../models/link-session-status';
|
|
23
|
-
import { extractPaymentReturnErrorCode } from '../models/payment-return-params';
|
|
24
|
-
import { supportsConfirmationOfPayee } from '../models/payment-type';
|
|
25
|
-
import {
|
|
26
|
-
type PaymentFlowPhase,
|
|
27
|
-
type PaymentFlowState,
|
|
28
|
-
PaymentFlowStates,
|
|
29
|
-
} from './payment-flow-state';
|
|
30
|
-
import type { PendingSessionStore } from './pending-session-store';
|
|
31
|
-
|
|
32
|
-
/** Minimum surface required from a `Clock` injected for testability. */
|
|
33
|
-
export interface Clock {
|
|
34
|
-
now(): number;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const REAL_CLOCK: Clock = { now: () => Date.now() };
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Number of consecutive `pollStatus` transport failures we tolerate before
|
|
41
|
-
* giving up and transitioning to `failed('network_error')`. Bounds the request
|
|
42
|
-
* volume against a flaky network during the 5-minute awaiting-callback window.
|
|
43
|
-
*/
|
|
44
|
-
const POLL_STATUS_MAX_CONSECUTIVE_FAILURES = 5;
|
|
45
|
-
const log = createLogger('PaymentFlowController');
|
|
46
|
-
|
|
47
|
-
export interface PaymentFlowControllerOptions {
|
|
48
|
-
sessionToken: string;
|
|
49
|
-
apiClient: LinkApiClient;
|
|
50
|
-
pendingSessionStore?: PendingSessionStore;
|
|
51
|
-
awaitingCallbackTimeoutMs?: number;
|
|
52
|
-
/**
|
|
53
|
-
* Deployment environment. In `sandbox`, the controller treats a non-terminal
|
|
54
|
-
* `/link/status` response during awaitingCallback as success: the sandbox bank
|
|
55
|
-
* authorizes consent but never settles the payment, so the status endpoint
|
|
56
|
-
* stays non-terminal forever and the flow could otherwise only ever time out.
|
|
57
|
-
* Production keeps strict terminal-only behavior. Defaults to `production`.
|
|
58
|
-
*/
|
|
59
|
-
environment?: PaymentEnvironment;
|
|
60
|
-
/**
|
|
61
|
-
* Interval for the sandbox awaiting-callback status poll. Ignored outside
|
|
62
|
-
* sandbox. Defaults to {@link DEFAULT_AWAITING_CALLBACK_POLL_MS}.
|
|
63
|
-
*/
|
|
64
|
-
awaitingCallbackPollMs?: number;
|
|
65
|
-
/** Optional clock injection for deterministic timeout tests. */
|
|
66
|
-
clock?: Clock;
|
|
67
|
-
/** Telemetry collector — called once before POST /link/consent. */
|
|
68
|
-
collectTelemetry?: () => Promise<Record<string, unknown>>;
|
|
69
|
-
/** UUID generator used for the consent Idempotency-Key. */
|
|
70
|
-
uuid?: () => string;
|
|
71
|
-
/** Callback for internal flow event tags. Exceptions are swallowed. */
|
|
72
|
-
onEvent?: (event: PaymentFlowEventTag) => void;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
type Listener = (state: PaymentFlowState) => void;
|
|
76
|
-
|
|
77
|
-
const TERMINAL_PHASES = new Set<PaymentFlowPhase>(['succeeded', 'failed', 'cancelled']);
|
|
78
|
-
|
|
79
|
-
function isTerminal(phase: PaymentFlowPhase): boolean {
|
|
80
|
-
return TERMINAL_PHASES.has(phase);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Drives the payment flow state machine. Exposes a `subscribe`/`unsubscribe`
|
|
85
|
-
* API so React's `useSyncExternalStore` can bridge to a hook.
|
|
86
|
-
*
|
|
87
|
-
* `subscribe` fires the listener synchronously with the current state so new
|
|
88
|
-
* subscribers don't miss the initial snapshot.
|
|
89
|
-
*/
|
|
90
|
-
export class PaymentFlowController {
|
|
91
|
-
readonly sessionToken: string;
|
|
92
|
-
readonly apiClient: LinkApiClient;
|
|
93
|
-
readonly pendingSessionStore?: PendingSessionStore;
|
|
94
|
-
|
|
95
|
-
private readonly awaitingCallbackTimeoutMs: number;
|
|
96
|
-
private readonly environment: PaymentEnvironment;
|
|
97
|
-
private readonly awaitingCallbackPollMs: number;
|
|
98
|
-
private readonly clock: Clock;
|
|
99
|
-
private readonly collectTelemetry?: () => Promise<Record<string, unknown>>;
|
|
100
|
-
private readonly uuid: () => string;
|
|
101
|
-
private readonly onEventCallback?: (event: PaymentFlowEventTag) => void;
|
|
102
|
-
|
|
103
|
-
private _state: PaymentFlowState = PaymentFlowStates.idle();
|
|
104
|
-
private _listeners = new Set<Listener>();
|
|
105
|
-
private _consentIdempotencyKey: string | undefined;
|
|
106
|
-
private _callbackTimer: ReturnType<typeof setTimeout> | undefined;
|
|
107
|
-
private _awaitingCallbackStartedAtMs: number | undefined;
|
|
108
|
-
/** Last provider the user selected — retained so success/awaiting states that
|
|
109
|
-
* arrive without it (poll/callback) can still report `bankId`. */
|
|
110
|
-
private _selectedProvider: ProviderSummary | undefined;
|
|
111
|
-
private _disposed = false;
|
|
112
|
-
/** Re-entrance guard — second `hydrate()` returns the in-flight promise. */
|
|
113
|
-
private _hydratePromise: Promise<void> | undefined;
|
|
114
|
-
/** Consecutive `pollStatus` transport failures since the last successful response. */
|
|
115
|
-
private _pollStatusConsecutiveFailures = 0;
|
|
116
|
-
|
|
117
|
-
constructor(opts: PaymentFlowControllerOptions) {
|
|
118
|
-
this.sessionToken = opts.sessionToken;
|
|
119
|
-
this.apiClient = opts.apiClient;
|
|
120
|
-
if (opts.pendingSessionStore) this.pendingSessionStore = opts.pendingSessionStore;
|
|
121
|
-
this.awaitingCallbackTimeoutMs =
|
|
122
|
-
opts.awaitingCallbackTimeoutMs ?? DEFAULT_AWAITING_CALLBACK_TIMEOUT_MS;
|
|
123
|
-
this.environment = opts.environment ?? 'production';
|
|
124
|
-
this.awaitingCallbackPollMs = opts.awaitingCallbackPollMs ?? DEFAULT_AWAITING_CALLBACK_POLL_MS;
|
|
125
|
-
this.clock = opts.clock ?? REAL_CLOCK;
|
|
126
|
-
if (opts.collectTelemetry) this.collectTelemetry = opts.collectTelemetry;
|
|
127
|
-
this.uuid = opts.uuid ?? fallbackUuid;
|
|
128
|
-
if (opts.onEvent) this.onEventCallback = opts.onEvent;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// ---- Subscription API ----------------------------------------------------
|
|
132
|
-
|
|
133
|
-
get state(): PaymentFlowState {
|
|
134
|
-
return this._state;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
get awaitingCallbackStartedAtMs(): number | undefined {
|
|
138
|
-
return this._awaitingCallbackStartedAtMs;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Register a listener. The listener is invoked synchronously with the
|
|
143
|
-
* current state so new subscribers have the initial snapshot, then again
|
|
144
|
-
* on every subsequent change.
|
|
145
|
-
*/
|
|
146
|
-
subscribe(listener: Listener): () => void {
|
|
147
|
-
this._listeners.add(listener);
|
|
148
|
-
try {
|
|
149
|
-
listener(this._state);
|
|
150
|
-
} catch {
|
|
151
|
-
// swallow — listener bugs never break the controller
|
|
152
|
-
}
|
|
153
|
-
return () => {
|
|
154
|
-
this._listeners.delete(listener);
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
private setState(next: PaymentFlowState): void {
|
|
159
|
-
if (this._disposed) return;
|
|
160
|
-
this._state = next;
|
|
161
|
-
if (isTerminal(next.phase)) {
|
|
162
|
-
this.cancelCallbackTimeout();
|
|
163
|
-
this._consentIdempotencyKey = undefined;
|
|
164
|
-
}
|
|
165
|
-
for (const l of this._listeners) {
|
|
166
|
-
try {
|
|
167
|
-
l(next);
|
|
168
|
-
} catch {
|
|
169
|
-
// listener exceptions never break the controller
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
fireEvent(event: PaymentFlowEventTag): void {
|
|
175
|
-
try {
|
|
176
|
-
this.onEventCallback?.(event);
|
|
177
|
-
} catch {
|
|
178
|
-
// swallow integrator errors
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// ---- Timers --------------------------------------------------------------
|
|
183
|
-
|
|
184
|
-
private cancelCallbackTimeout(): void {
|
|
185
|
-
if (this._callbackTimer) {
|
|
186
|
-
clearTimeout(this._callbackTimer);
|
|
187
|
-
this._callbackTimer = undefined;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
private startCallbackTimeout(): void {
|
|
192
|
-
this.cancelCallbackTimeout();
|
|
193
|
-
this._callbackTimer = setTimeout(() => {
|
|
194
|
-
if (this._state.phase !== 'awaitingCallback') return;
|
|
195
|
-
void this.reportError('session_timeout');
|
|
196
|
-
}, this.awaitingCallbackTimeoutMs);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// ---- Phase transitions ---------------------------------------------------
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* `GET /link` + `GET /link/providers`, then transitions to bankSelection.
|
|
203
|
-
* Re-entrant: a second concurrent call returns the in-flight promise instead
|
|
204
|
-
* of firing duplicate requests.
|
|
205
|
-
*/
|
|
206
|
-
hydrate(): Promise<void> {
|
|
207
|
-
if (this._disposed) return Promise.resolve();
|
|
208
|
-
if (this._hydratePromise) return this._hydratePromise;
|
|
209
|
-
this._hydratePromise = this._doHydrate().finally(() => {
|
|
210
|
-
this._hydratePromise = undefined;
|
|
211
|
-
});
|
|
212
|
-
return this._hydratePromise;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
private async _doHydrate(): Promise<void> {
|
|
216
|
-
log.info('hydrate: starting session hydration');
|
|
217
|
-
this.setState(PaymentFlowStates.hydrating());
|
|
218
|
-
try {
|
|
219
|
-
const [session, providers] = await Promise.all([
|
|
220
|
-
this.apiClient.getSession(this.sessionToken),
|
|
221
|
-
this.apiClient.getProviders(this.sessionToken),
|
|
222
|
-
]);
|
|
223
|
-
log.info(`hydrate: loaded session with ${providers.length} provider(s)`);
|
|
224
|
-
this.setState(PaymentFlowStates.bankSelection({ session, providers }));
|
|
225
|
-
this.fireEvent('sessionLoaded');
|
|
226
|
-
} catch (err) {
|
|
227
|
-
log.severe(`hydrate: failed — ${err instanceof Error ? err.message : String(err)}`);
|
|
228
|
-
const code = isPaymentApiError(err) ? err.code : 'hydration_error';
|
|
229
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
230
|
-
this.setState(PaymentFlowStates.failed({ errorCode: code, errorMessage: message }));
|
|
231
|
-
throw err;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/** Move bankSelection → consentDetails. */
|
|
236
|
-
selectBank(bankId: string): void {
|
|
237
|
-
log.info(`selectBank: bankId=${bankId}`);
|
|
238
|
-
const current = this._state;
|
|
239
|
-
const session = current.session;
|
|
240
|
-
if (!session) {
|
|
241
|
-
throw new Error('Cannot select bank before session is loaded.');
|
|
242
|
-
}
|
|
243
|
-
const provider = current.providers.find((p) => p.id === bankId);
|
|
244
|
-
if (!provider) {
|
|
245
|
-
log.severe(`selectBank: unknown bankId=${bankId}`);
|
|
246
|
-
throw new Error(`Unknown bank id: ${bankId}`);
|
|
247
|
-
}
|
|
248
|
-
// Retained so success states reached via poll/callback (which don't carry
|
|
249
|
-
// the provider) still resolve a `bankId` in the PaymentResult.
|
|
250
|
-
this._selectedProvider = provider;
|
|
251
|
-
const willLoadCop = this.shouldPerformCop(session);
|
|
252
|
-
this.setState(
|
|
253
|
-
PaymentFlowStates.consentDetails({
|
|
254
|
-
session,
|
|
255
|
-
selectedProvider: provider,
|
|
256
|
-
isCopLoading: willLoadCop,
|
|
257
|
-
copApplicable: willLoadCop,
|
|
258
|
-
}),
|
|
259
|
-
);
|
|
260
|
-
if (willLoadCop) {
|
|
261
|
-
this.loadCopInBackground(session, provider);
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Best-effort Confirmation-of-Payee fetch — never blocks {@link selectBank}
|
|
267
|
-
* or fails the flow. Mirrors the Flutter controller: gated to UAE + un-verified
|
|
268
|
-
* sessions, and the result is merged into the consentDetails state only if the
|
|
269
|
-
* user is still on that screen for the same provider. Ported from
|
|
270
|
-
* `payment_flow_controller.dart:_loadCopInBackground`.
|
|
271
|
-
*/
|
|
272
|
-
private loadCopInBackground(session: LinkSessionResponse, provider: ProviderSummary): void {
|
|
273
|
-
void (async () => {
|
|
274
|
-
const cop = await this.getCoP(provider.id);
|
|
275
|
-
if (this._state.phase !== 'consentDetails') return;
|
|
276
|
-
if (this._state.selectedProvider?.id !== provider.id) return;
|
|
277
|
-
this.setState(
|
|
278
|
-
PaymentFlowStates.consentDetails({
|
|
279
|
-
session,
|
|
280
|
-
selectedProvider: provider,
|
|
281
|
-
...(cop ? { copResponse: cop } : {}),
|
|
282
|
-
isCopLoading: false,
|
|
283
|
-
copApplicable: true,
|
|
284
|
-
}),
|
|
285
|
-
);
|
|
286
|
-
})();
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
private shouldPerformCop(session: LinkSessionResponse): boolean {
|
|
290
|
-
if (this.apiClient.tenantHeader !== 'UAE') return false;
|
|
291
|
-
if (session.request.isCopVerified === true) return false;
|
|
292
|
-
if (!supportsConfirmationOfPayee(session.request)) return false;
|
|
293
|
-
return true;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
/** `POST /link/consent`, persists pending record, transitions to redirecting. */
|
|
297
|
-
async confirmConsent(): Promise<void> {
|
|
298
|
-
log.info('confirmConsent: posting consent');
|
|
299
|
-
const selectedProvider = this._state.selectedProvider;
|
|
300
|
-
if (!selectedProvider) {
|
|
301
|
-
log.severe('confirmConsent: no provider selected');
|
|
302
|
-
throw new Error('Cannot confirm consent without a selected provider.');
|
|
303
|
-
}
|
|
304
|
-
this.fireEvent('consentStarted');
|
|
305
|
-
|
|
306
|
-
if (!this._consentIdempotencyKey) {
|
|
307
|
-
this._consentIdempotencyKey = this.uuid();
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// Best-effort telemetry before posting consent.
|
|
311
|
-
await this.postTelemetryAutomatic();
|
|
312
|
-
|
|
313
|
-
let consent: ConsentResponse;
|
|
314
|
-
try {
|
|
315
|
-
consent = await this.apiClient.postConsent({
|
|
316
|
-
linkToken: this.sessionToken,
|
|
317
|
-
bankId: selectedProvider.id,
|
|
318
|
-
idempotencyKey: this._consentIdempotencyKey,
|
|
319
|
-
});
|
|
320
|
-
} catch (err) {
|
|
321
|
-
// Without this the flow would be stranded in `consentDetails` with no
|
|
322
|
-
// terminal state — the caller's catch assumes we already transitioned.
|
|
323
|
-
const code = isPaymentApiError(err) ? err.code : 'consent_failed';
|
|
324
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
325
|
-
this.setState(PaymentFlowStates.failed({ errorCode: code, errorMessage: message }));
|
|
326
|
-
void this.patchTokenBestEffort('error', code);
|
|
327
|
-
throw err;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
if (this.pendingSessionStore) {
|
|
331
|
-
try {
|
|
332
|
-
const merchantRef = this._state.session?.request?.merchantReference;
|
|
333
|
-
await this.pendingSessionStore.save({
|
|
334
|
-
sessionId: this.sessionToken,
|
|
335
|
-
selectedBankId: selectedProvider.id,
|
|
336
|
-
authorizationUrl: consent.redirectUrl,
|
|
337
|
-
consentAt: this.clock.now(),
|
|
338
|
-
recoveryAttempts: 0,
|
|
339
|
-
...(merchantRef ? { merchantRef } : {}),
|
|
340
|
-
});
|
|
341
|
-
} catch {
|
|
342
|
-
log.warning('confirmConsent: store.save() failed — continuing');
|
|
343
|
-
// store failures should not block the flow
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
log.info('confirmConsent: → redirecting');
|
|
348
|
-
this.setState(PaymentFlowStates.redirecting({ consent, selectedProvider }));
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
/**
|
|
352
|
-
* Parses a callback URI and transitions to succeeded / failed. Accepts either
|
|
353
|
-
* a `URL` instance or a string. A malformed URI resolves to
|
|
354
|
-
* `failed('invalid_callback')` instead of throwing.
|
|
355
|
-
*/
|
|
356
|
-
handleCallback(uri: URL | string): void {
|
|
357
|
-
log.info(
|
|
358
|
-
`handleCallback: received URI=${redactPaymentReturnUri(typeof uri === 'string' ? uri : uri.toString())}`,
|
|
359
|
-
);
|
|
360
|
-
// Deep-link callbacks are commonly re-delivered (cold start + warm
|
|
361
|
-
// foreground). Once the flow is terminal, ignore further callbacks so we
|
|
362
|
-
// never re-transition and re-fire terminal callbacks.
|
|
363
|
-
if (isTerminal(this._state.phase)) return;
|
|
364
|
-
let url: URL;
|
|
365
|
-
if (typeof uri === 'string') {
|
|
366
|
-
try {
|
|
367
|
-
url = new URL(uri);
|
|
368
|
-
} catch {
|
|
369
|
-
this.setState(
|
|
370
|
-
PaymentFlowStates.failed({
|
|
371
|
-
errorCode: 'invalid_callback',
|
|
372
|
-
errorMessage: 'The callback URI could not be parsed.',
|
|
373
|
-
}),
|
|
374
|
-
);
|
|
375
|
-
return;
|
|
376
|
-
}
|
|
377
|
-
} else {
|
|
378
|
-
url = uri;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
this.fireEvent('bankCallbackReceived');
|
|
382
|
-
const params = url.searchParams;
|
|
383
|
-
|
|
384
|
-
// Prefer the new `error_code` query param over legacy `error`. Also accept
|
|
385
|
-
// `status=failure` with no other code as `authorize_failed`.
|
|
386
|
-
const error = extractPaymentReturnErrorCode(params);
|
|
387
|
-
if (error) {
|
|
388
|
-
const description = params.get('error_description') ?? undefined;
|
|
389
|
-
this.setState(
|
|
390
|
-
PaymentFlowStates.failed({
|
|
391
|
-
errorCode: error,
|
|
392
|
-
...(description ? { errorMessage: description } : {}),
|
|
393
|
-
}),
|
|
394
|
-
);
|
|
395
|
-
return;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
const exchangeCode = params.get('exchange_code') ?? undefined;
|
|
399
|
-
const linkSessionId = params.get('session_id') ?? undefined;
|
|
400
|
-
const merchantRef = params.get('merchantRef') ?? undefined;
|
|
401
|
-
if (exchangeCode) {
|
|
402
|
-
this.setState(
|
|
403
|
-
PaymentFlowStates.succeeded({
|
|
404
|
-
exchangeCode,
|
|
405
|
-
...(linkSessionId ? { linkSessionId } : {}),
|
|
406
|
-
...(merchantRef ? { merchantRef } : {}),
|
|
407
|
-
...(this._selectedProvider ? { selectedProvider: this._selectedProvider } : {}),
|
|
408
|
-
...(this._state.session ? { session: this._state.session } : {}),
|
|
409
|
-
}),
|
|
410
|
-
);
|
|
411
|
-
return;
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
this.setState(
|
|
415
|
-
PaymentFlowStates.failed({
|
|
416
|
-
errorCode: 'invalid_callback',
|
|
417
|
-
errorMessage: 'The callback URI is missing required parameters.',
|
|
418
|
-
}),
|
|
419
|
-
);
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
/** Best-effort cancel — PATCH /link with action=cancel, then transitions to cancelled. */
|
|
423
|
-
async cancel(): Promise<void> {
|
|
424
|
-
log.info('cancel: user cancelled the payment flow');
|
|
425
|
-
await this.patchTokenBestEffort('cancel');
|
|
426
|
-
this.setState(PaymentFlowStates.cancelled());
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
/** Best-effort error report — sets failed state immediately, PATCH is fire-and-forget. */
|
|
430
|
-
async reportError(code: string): Promise<void> {
|
|
431
|
-
log.severe(`reportError: reporting error code=${code}`);
|
|
432
|
-
this.setState(PaymentFlowStates.failed({ errorCode: code }));
|
|
433
|
-
// Fire-and-forget; we already transitioned.
|
|
434
|
-
void this.patchTokenBestEffort('error', code);
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
private async patchTokenBestEffort(
|
|
438
|
-
action: 'cancel' | 'error',
|
|
439
|
-
errorCode?: string,
|
|
440
|
-
): Promise<void> {
|
|
441
|
-
try {
|
|
442
|
-
await this.apiClient.patchToken({
|
|
443
|
-
linkToken: this.sessionToken,
|
|
444
|
-
action,
|
|
445
|
-
...(errorCode ? { errorCode } : {}),
|
|
446
|
-
});
|
|
447
|
-
} catch {
|
|
448
|
-
// swallow — PATCH is best-effort
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
/**
|
|
453
|
-
* UI calls this after handing off to the bank — starts the 5-minute timeout
|
|
454
|
-
* and pins the awaiting-callback start time.
|
|
455
|
-
*/
|
|
456
|
-
setAwaitingCallbackState(args: { providerName?: string } = {}): void {
|
|
457
|
-
this._awaitingCallbackStartedAtMs ??= this.clock.now();
|
|
458
|
-
this.setState(
|
|
459
|
-
PaymentFlowStates.awaitingCallback({
|
|
460
|
-
...(args.providerName ? { providerName: args.providerName } : {}),
|
|
461
|
-
...(this._state.session ? { session: this._state.session } : {}),
|
|
462
|
-
...(this._selectedProvider ? { selectedProvider: this._selectedProvider } : {}),
|
|
463
|
-
}),
|
|
464
|
-
);
|
|
465
|
-
this.startCallbackTimeout();
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
/**
|
|
469
|
-
* Best-effort status polling. Transitions to a terminal state on
|
|
470
|
-
* `completed | failed | cancelled | expired`; otherwise leaves the flow in
|
|
471
|
-
* the current phase. After {@link POLL_STATUS_MAX_CONSECUTIVE_FAILURES}
|
|
472
|
-
* consecutive transport failures the controller gives up with
|
|
473
|
-
* `failed('network_error')` to stop hammering an unreachable backend.
|
|
474
|
-
*/
|
|
475
|
-
async pollStatus(): Promise<void> {
|
|
476
|
-
// A status response can land after a bank callback or the timeout has
|
|
477
|
-
// already resolved the flow; never overwrite a terminal state.
|
|
478
|
-
if (isTerminal(this._state.phase)) return;
|
|
479
|
-
try {
|
|
480
|
-
const status = await this.apiClient.getStatus(this.sessionToken);
|
|
481
|
-
this._pollStatusConsecutiveFailures = 0;
|
|
482
|
-
// Re-check: the await above yields, so a terminal callback may have
|
|
483
|
-
// arrived while the request was in flight.
|
|
484
|
-
if (isTerminal(this._state.phase)) return;
|
|
485
|
-
switch (status.status) {
|
|
486
|
-
case 'completed':
|
|
487
|
-
this.setState(
|
|
488
|
-
PaymentFlowStates.succeeded({
|
|
489
|
-
...(status.linkSessionId ? { linkSessionId: status.linkSessionId } : {}),
|
|
490
|
-
...(this._selectedProvider ? { selectedProvider: this._selectedProvider } : {}),
|
|
491
|
-
...(this._state.session ? { session: this._state.session } : {}),
|
|
492
|
-
}),
|
|
493
|
-
);
|
|
494
|
-
return;
|
|
495
|
-
case 'failed':
|
|
496
|
-
this.setState(
|
|
497
|
-
PaymentFlowStates.failed({ errorCode: status.failureCode ?? 'session_failed' }),
|
|
498
|
-
);
|
|
499
|
-
return;
|
|
500
|
-
case 'cancelled':
|
|
501
|
-
this.setState(PaymentFlowStates.cancelled());
|
|
502
|
-
return;
|
|
503
|
-
case 'expired':
|
|
504
|
-
this.setState(PaymentFlowStates.failed({ errorCode: 'session_expired' }));
|
|
505
|
-
return;
|
|
506
|
-
default:
|
|
507
|
-
// Non-terminal. In sandbox, only treat `callback_received` as success —
|
|
508
|
-
// the bank has actually returned. `redirected` means consent was posted
|
|
509
|
-
// but the user may not have authorized yet; auto-success there caused
|
|
510
|
-
// false positives on cold-start recovery.
|
|
511
|
-
if (
|
|
512
|
-
this.environment === 'sandbox' &&
|
|
513
|
-
this._state.phase === 'awaitingCallback' &&
|
|
514
|
-
isBankCallbackReceivedStatus(status.status)
|
|
515
|
-
) {
|
|
516
|
-
this.setState(
|
|
517
|
-
PaymentFlowStates.succeeded({
|
|
518
|
-
...(status.linkSessionId ? { linkSessionId: status.linkSessionId } : {}),
|
|
519
|
-
...(this._selectedProvider ? { selectedProvider: this._selectedProvider } : {}),
|
|
520
|
-
...(this._state.session ? { session: this._state.session } : {}),
|
|
521
|
-
}),
|
|
522
|
-
);
|
|
523
|
-
}
|
|
524
|
-
return;
|
|
525
|
-
}
|
|
526
|
-
} catch {
|
|
527
|
-
this._pollStatusConsecutiveFailures += 1;
|
|
528
|
-
log.warning(
|
|
529
|
-
`pollStatus: failed (${this._pollStatusConsecutiveFailures}/${POLL_STATUS_MAX_CONSECUTIVE_FAILURES})`,
|
|
530
|
-
);
|
|
531
|
-
if (this._pollStatusConsecutiveFailures >= POLL_STATUS_MAX_CONSECUTIVE_FAILURES) {
|
|
532
|
-
if (isTerminal(this._state.phase) || this._state.phase !== 'awaitingCallback') return;
|
|
533
|
-
this.setState(
|
|
534
|
-
PaymentFlowStates.failed({
|
|
535
|
-
errorCode: 'network_error',
|
|
536
|
-
errorMessage: 'Unable to reach the Spare backend after multiple attempts.',
|
|
537
|
-
}),
|
|
538
|
-
);
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
/** Best-effort telemetry — never throws, never changes state. */
|
|
544
|
-
async postTelemetry(payload: Record<string, unknown>): Promise<void> {
|
|
545
|
-
try {
|
|
546
|
-
await this.apiClient.postTelemetry({ linkToken: this.sessionToken, payload });
|
|
547
|
-
} catch (err) {
|
|
548
|
-
log.warning(
|
|
549
|
-
`postTelemetry: best-effort telemetry failed — ${err instanceof Error ? err.message : String(err)}`,
|
|
550
|
-
);
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
/** Best-effort CoP — returns result or null on failure. */
|
|
555
|
-
async getCoP(providerId?: string): Promise<CopResponse | null> {
|
|
556
|
-
try {
|
|
557
|
-
return await this.apiClient.getConfirmPayee(this.sessionToken, providerId);
|
|
558
|
-
} catch {
|
|
559
|
-
return null;
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
private async postTelemetryAutomatic(): Promise<void> {
|
|
564
|
-
if (!this.collectTelemetry) return;
|
|
565
|
-
log.fine('postTelemetryAutomatic: collecting and posting device telemetry');
|
|
566
|
-
try {
|
|
567
|
-
const payload = await this.collectTelemetry();
|
|
568
|
-
await this.apiClient.postTelemetry({ linkToken: this.sessionToken, payload });
|
|
569
|
-
} catch (err) {
|
|
570
|
-
log.warning(
|
|
571
|
-
`postTelemetryAutomatic: failed — ${err instanceof Error ? err.message : String(err)}`,
|
|
572
|
-
);
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
/** Returns the active providers list — convenience for the UI layer. */
|
|
577
|
-
get providers(): ProviderSummary[] {
|
|
578
|
-
return this._state.providers;
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
/** Returns the active session, if any. */
|
|
582
|
-
get session(): LinkSessionResponse | undefined {
|
|
583
|
-
return this._state.session;
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
/**
|
|
587
|
-
* Releases resources: cancels timers, clears listeners, and aborts the
|
|
588
|
-
* underlying API client's in-flight fetches. Idempotent.
|
|
589
|
-
*/
|
|
590
|
-
dispose(): void {
|
|
591
|
-
if (this._disposed) return;
|
|
592
|
-
log.info('dispose: releasing apiClient');
|
|
593
|
-
this._disposed = true;
|
|
594
|
-
this.cancelCallbackTimeout();
|
|
595
|
-
this._listeners.clear();
|
|
596
|
-
this.apiClient.dispose();
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
function fallbackUuid(): string {
|
|
601
|
-
const bytes = new Uint8Array(16);
|
|
602
|
-
for (let i = 0; i < 16; i += 1) bytes[i] = Math.floor(Math.random() * 256);
|
|
603
|
-
bytes[6] = ((bytes[6] ?? 0) & 0x0f) | 0x40;
|
|
604
|
-
bytes[8] = ((bytes[8] ?? 0) & 0x3f) | 0x80;
|
|
605
|
-
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');
|
|
606
|
-
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
|
|
607
|
-
}
|