flintn-checkout 0.0.9 → 0.0.11
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 +22 -25
- package/dist/index.d.mts +1 -2
- package/dist/index.d.ts +1 -2
- package/dist/index.js +138 -39
- package/dist/index.mjs +138 -39
- package/dist/react.d.mts +1 -2
- package/dist/react.d.ts +1 -2
- package/dist/react.js +151 -65
- package/dist/react.mjs +151 -65
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -6,12 +6,14 @@ FlintN Payment SDK — Embed payment forms via iframe checkout or headless hoste
|
|
|
6
6
|
```bash
|
|
7
7
|
npm install flintn-checkout
|
|
8
8
|
```
|
|
9
|
+
> **Note:** for local/non-production use, pass `origin` (e.g. `origin: 'http://localhost:3000'`).
|
|
9
10
|
|
|
10
11
|
## Iframe Checkout
|
|
11
12
|
|
|
12
13
|
Full checkout UI rendered inside a single iframe. Includes card form, express payments (Apple Pay, Google Pay, PayPal), and 3DS handling.
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
**React**
|
|
16
|
+
|
|
15
17
|
```tsx
|
|
16
18
|
import { useFlintNPayment } from 'flintn-checkout/react';
|
|
17
19
|
|
|
@@ -37,11 +39,12 @@ function Checkout() {
|
|
|
37
39
|
}
|
|
38
40
|
```
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
**Vanilla JavaScript**
|
|
43
|
+
|
|
41
44
|
```javascript
|
|
42
|
-
import {
|
|
45
|
+
import { createFlintNPayment } from 'flintn-checkout';
|
|
43
46
|
|
|
44
|
-
const payment =
|
|
47
|
+
const payment = createFlintNPayment({
|
|
45
48
|
config: {
|
|
46
49
|
clientSessionId: 'your_client_session_id',
|
|
47
50
|
},
|
|
@@ -60,11 +63,12 @@ const payment = new FlintNPayment({
|
|
|
60
63
|
|
|
61
64
|
payment.mount('#payment-container');
|
|
62
65
|
|
|
63
|
-
//
|
|
64
|
-
payment.unmount();
|
|
66
|
+
// Later, when you want to tear the widget down (e.g. on route change):
|
|
67
|
+
// payment.unmount();
|
|
65
68
|
```
|
|
66
69
|
|
|
67
|
-
|
|
70
|
+
**HTML**
|
|
71
|
+
|
|
68
72
|
```html
|
|
69
73
|
<!DOCTYPE html>
|
|
70
74
|
<html>
|
|
@@ -75,9 +79,9 @@ payment.unmount();
|
|
|
75
79
|
<div id="payment-container" style="max-width: 440px; margin: 0 auto;"></div>
|
|
76
80
|
|
|
77
81
|
<script type="module">
|
|
78
|
-
import {
|
|
82
|
+
import { createFlintNPayment } from 'flintn-checkout';
|
|
79
83
|
|
|
80
|
-
const payment =
|
|
84
|
+
const payment = createFlintNPayment({
|
|
81
85
|
config: {
|
|
82
86
|
clientSessionId: 'your_client_session_id',
|
|
83
87
|
},
|
|
@@ -107,7 +111,7 @@ Do **not** set a fixed `height` on the container — it will leave empty space b
|
|
|
107
111
|
| Option | Type | Required | Default | Description |
|
|
108
112
|
|--------|------|----------|---------|-------------|
|
|
109
113
|
| `config` | `FlintNConfig` | Yes | — | Checkout configuration |
|
|
110
|
-
| `onPayment` | `(result: PaymentResult) => void` | No | — |
|
|
114
|
+
| `onPayment` | `(result: PaymentResult) => void` | No | — | Payment result callback (success, error, cancelled) |
|
|
111
115
|
| `onReady` | `() => void` | No | — | Widget loaded and ready |
|
|
112
116
|
| `onError` | `(error: PaymentError) => void` | No | — | SDK initialization error |
|
|
113
117
|
| `debug` | `boolean` | No | `false` | Enable console debug logs |
|
|
@@ -138,7 +142,8 @@ Individual PCI-compliant input fields rendered as separate iframes. You control
|
|
|
138
142
|
|
|
139
143
|
Each field (card number, expiry, CVV) is a separate iframe. Raw card data never touches your page.
|
|
140
144
|
|
|
141
|
-
|
|
145
|
+
**React**
|
|
146
|
+
|
|
142
147
|
```tsx
|
|
143
148
|
import { useState } from 'react';
|
|
144
149
|
import { useFlintNFields } from 'flintn-checkout/react';
|
|
@@ -223,11 +228,12 @@ function CheckoutForm() {
|
|
|
223
228
|
}
|
|
224
229
|
```
|
|
225
230
|
|
|
226
|
-
|
|
231
|
+
**Vanilla JavaScript**
|
|
232
|
+
|
|
227
233
|
```javascript
|
|
228
|
-
import {
|
|
234
|
+
import { createFlintNFields } from 'flintn-checkout';
|
|
229
235
|
|
|
230
|
-
const fields =
|
|
236
|
+
const fields = createFlintNFields({
|
|
231
237
|
config: {
|
|
232
238
|
clientSessionId: 'your_client_session_id',
|
|
233
239
|
styles: {
|
|
@@ -255,8 +261,8 @@ if (validation.isValid) {
|
|
|
255
261
|
const result = await fields.submit({ cardholderName: 'John Doe' });
|
|
256
262
|
}
|
|
257
263
|
|
|
258
|
-
// Cleanup
|
|
259
|
-
fields.unmount();
|
|
264
|
+
// Cleanup (call when you're done with the form)
|
|
265
|
+
// fields.unmount();
|
|
260
266
|
```
|
|
261
267
|
|
|
262
268
|
### Hosted Fields Options (Vanilla JS)
|
|
@@ -494,15 +500,6 @@ useFlintNFields({
|
|
|
494
500
|
});
|
|
495
501
|
```
|
|
496
502
|
|
|
497
|
-
## Test Cards
|
|
498
|
-
|
|
499
|
-
| Card Number | Result |
|
|
500
|
-
|-------------|--------|
|
|
501
|
-
| `4111 1111 1111 1111` | Success |
|
|
502
|
-
| `4000 0000 0000 0002` | Declined |
|
|
503
|
-
|
|
504
|
-
Use any future expiry date and any 3-digit CVV.
|
|
505
|
-
|
|
506
503
|
## Browser Support
|
|
507
504
|
|
|
508
505
|
- Chrome (latest)
|
package/dist/index.d.mts
CHANGED
|
@@ -2,7 +2,6 @@ declare const EventType: {
|
|
|
2
2
|
readonly WIDGET_READY: "WIDGET_READY";
|
|
3
3
|
readonly WIDGET_CONFIG: "WIDGET_CONFIG";
|
|
4
4
|
readonly PAYMENT: "PAYMENT";
|
|
5
|
-
readonly EXPRESS_PAYMENT: "EXPRESS_PAYMENT";
|
|
6
5
|
readonly PAYMENT_SUCCESS: "PAYMENT_SUCCESS";
|
|
7
6
|
readonly PAYMENT_ERROR: "PAYMENT_ERROR";
|
|
8
7
|
readonly PAYMENT_CANCELLED: "PAYMENT_CANCELLED";
|
|
@@ -62,7 +61,6 @@ interface FlintNPaymentOptions {
|
|
|
62
61
|
origin?: string;
|
|
63
62
|
config: FlintNConfig;
|
|
64
63
|
onPayment?: (result: PaymentResult) => void;
|
|
65
|
-
onExpressPayment?: (result: PaymentResult) => void;
|
|
66
64
|
onReady?: () => void;
|
|
67
65
|
onError?: (error: PaymentError) => void;
|
|
68
66
|
debug?: boolean;
|
|
@@ -147,6 +145,7 @@ interface FlintNFieldInternalCallbacks {
|
|
|
147
145
|
onFocus: (fieldType: TFieldType) => void;
|
|
148
146
|
onBlur: (fieldType: TFieldType, state: FieldState) => void;
|
|
149
147
|
onHeight: (fieldType: TFieldType, height: number) => void;
|
|
148
|
+
onError?: (err: Error) => void;
|
|
150
149
|
}
|
|
151
150
|
interface FlintNField {
|
|
152
151
|
mount(selector: string | HTMLElement): void;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,6 @@ declare const EventType: {
|
|
|
2
2
|
readonly WIDGET_READY: "WIDGET_READY";
|
|
3
3
|
readonly WIDGET_CONFIG: "WIDGET_CONFIG";
|
|
4
4
|
readonly PAYMENT: "PAYMENT";
|
|
5
|
-
readonly EXPRESS_PAYMENT: "EXPRESS_PAYMENT";
|
|
6
5
|
readonly PAYMENT_SUCCESS: "PAYMENT_SUCCESS";
|
|
7
6
|
readonly PAYMENT_ERROR: "PAYMENT_ERROR";
|
|
8
7
|
readonly PAYMENT_CANCELLED: "PAYMENT_CANCELLED";
|
|
@@ -62,7 +61,6 @@ interface FlintNPaymentOptions {
|
|
|
62
61
|
origin?: string;
|
|
63
62
|
config: FlintNConfig;
|
|
64
63
|
onPayment?: (result: PaymentResult) => void;
|
|
65
|
-
onExpressPayment?: (result: PaymentResult) => void;
|
|
66
64
|
onReady?: () => void;
|
|
67
65
|
onError?: (error: PaymentError) => void;
|
|
68
66
|
debug?: boolean;
|
|
@@ -147,6 +145,7 @@ interface FlintNFieldInternalCallbacks {
|
|
|
147
145
|
onFocus: (fieldType: TFieldType) => void;
|
|
148
146
|
onBlur: (fieldType: TFieldType, state: FieldState) => void;
|
|
149
147
|
onHeight: (fieldType: TFieldType, height: number) => void;
|
|
148
|
+
onError?: (err: Error) => void;
|
|
150
149
|
}
|
|
151
150
|
interface FlintNField {
|
|
152
151
|
mount(selector: string | HTMLElement): void;
|
package/dist/index.js
CHANGED
|
@@ -40,7 +40,6 @@ var EventType = {
|
|
|
40
40
|
WIDGET_READY: "WIDGET_READY",
|
|
41
41
|
WIDGET_CONFIG: "WIDGET_CONFIG",
|
|
42
42
|
PAYMENT: "PAYMENT",
|
|
43
|
-
EXPRESS_PAYMENT: "EXPRESS_PAYMENT",
|
|
44
43
|
PAYMENT_SUCCESS: "PAYMENT_SUCCESS",
|
|
45
44
|
PAYMENT_ERROR: "PAYMENT_ERROR",
|
|
46
45
|
PAYMENT_CANCELLED: "PAYMENT_CANCELLED",
|
|
@@ -112,15 +111,38 @@ var sanitizeToken = (token) => {
|
|
|
112
111
|
// src/flintn-payment.ts
|
|
113
112
|
var DEFAULT_ORIGIN = "https://pay.flintn.com";
|
|
114
113
|
function createFlintNPayment(options) {
|
|
115
|
-
|
|
116
|
-
|
|
114
|
+
const log = (...args) => {
|
|
115
|
+
if (options.debug) console.log("[FlintN SDK]", ...args);
|
|
116
|
+
};
|
|
117
|
+
const reportInitError = (err) => {
|
|
118
|
+
const error = {
|
|
119
|
+
code: "INIT_ERROR",
|
|
120
|
+
message: err instanceof Error ? err.message : "Failed to initialize SDK"
|
|
121
|
+
};
|
|
122
|
+
queueMicrotask(() => {
|
|
123
|
+
if (options.onError) options.onError(error);
|
|
124
|
+
else console.error("[FlintN SDK]", error);
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
let origin;
|
|
128
|
+
try {
|
|
129
|
+
validateConfig(options.config);
|
|
130
|
+
origin = parseOrigin(options.origin || DEFAULT_ORIGIN);
|
|
131
|
+
} catch (err) {
|
|
132
|
+
reportInitError(err);
|
|
133
|
+
return {
|
|
134
|
+
mount() {
|
|
135
|
+
},
|
|
136
|
+
unmount() {
|
|
137
|
+
},
|
|
138
|
+
getIsReady: () => false
|
|
139
|
+
};
|
|
140
|
+
}
|
|
117
141
|
let iframe = null;
|
|
118
142
|
let container = null;
|
|
119
143
|
let isReady = false;
|
|
120
144
|
let messageHandler = null;
|
|
121
|
-
|
|
122
|
-
if (options.debug) console.log("[FlintN SDK]", ...args);
|
|
123
|
-
};
|
|
145
|
+
let iframeErrorHandler = null;
|
|
124
146
|
log("Initialized with origin:", origin);
|
|
125
147
|
const sendConfig = () => {
|
|
126
148
|
if (!iframe?.contentWindow) return;
|
|
@@ -130,10 +152,6 @@ function createFlintNPayment(options) {
|
|
|
130
152
|
);
|
|
131
153
|
log("Sent config:", sanitizeToken(options.config.clientSessionId));
|
|
132
154
|
};
|
|
133
|
-
const handlePaymentResult = (payload, callback) => {
|
|
134
|
-
if (!callback) return;
|
|
135
|
-
callback(payload);
|
|
136
|
-
};
|
|
137
155
|
const isValidRedirectUrl = (url) => {
|
|
138
156
|
try {
|
|
139
157
|
const parsed = new URL(url);
|
|
@@ -166,10 +184,7 @@ function createFlintNPayment(options) {
|
|
|
166
184
|
options.onReady?.();
|
|
167
185
|
break;
|
|
168
186
|
case EventType.PAYMENT:
|
|
169
|
-
|
|
170
|
-
break;
|
|
171
|
-
case EventType.EXPRESS_PAYMENT:
|
|
172
|
-
handlePaymentResult(payload, options.onExpressPayment);
|
|
187
|
+
options.onPayment?.(payload);
|
|
173
188
|
break;
|
|
174
189
|
case EventType.REDIRECT:
|
|
175
190
|
if (payload?.url && isValidRedirectUrl(payload.url)) {
|
|
@@ -186,12 +201,13 @@ function createFlintNPayment(options) {
|
|
|
186
201
|
const mount = (selector) => {
|
|
187
202
|
container = typeof selector === "string" ? document.querySelector(selector) : selector;
|
|
188
203
|
if (!container) {
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
);
|
|
204
|
+
const description = typeof selector === "string" ? selector : `<${selector.tagName.toLowerCase()}>`;
|
|
205
|
+
reportInitError(new Error(`Container not found: ${description}`));
|
|
206
|
+
return;
|
|
193
207
|
}
|
|
194
208
|
iframe = createIframeElement(buildIframeSrc(origin));
|
|
209
|
+
iframeErrorHandler = () => reportInitError(new Error("Failed to load checkout iframe"));
|
|
210
|
+
iframe.addEventListener("error", iframeErrorHandler);
|
|
195
211
|
container.appendChild(iframe);
|
|
196
212
|
messageHandler = handleMessage;
|
|
197
213
|
window.addEventListener("message", messageHandler);
|
|
@@ -202,15 +218,19 @@ function createFlintNPayment(options) {
|
|
|
202
218
|
window.removeEventListener("message", messageHandler);
|
|
203
219
|
messageHandler = null;
|
|
204
220
|
}
|
|
221
|
+
if (iframe && iframeErrorHandler) {
|
|
222
|
+
iframe.removeEventListener("error", iframeErrorHandler);
|
|
223
|
+
iframeErrorHandler = null;
|
|
224
|
+
}
|
|
205
225
|
if (iframe && container && container.contains(iframe)) {
|
|
206
226
|
container.removeChild(iframe);
|
|
207
227
|
}
|
|
208
228
|
iframe = null;
|
|
229
|
+
container = null;
|
|
209
230
|
isReady = false;
|
|
210
231
|
log("Unmounted");
|
|
211
232
|
};
|
|
212
|
-
|
|
213
|
-
return { mount, unmount, getIsReady };
|
|
233
|
+
return { mount, unmount, getIsReady: () => isReady };
|
|
214
234
|
}
|
|
215
235
|
|
|
216
236
|
// src/flintn-field.ts
|
|
@@ -221,6 +241,7 @@ var FIELD_TITLES = {
|
|
|
221
241
|
};
|
|
222
242
|
function createFlintNField(fieldType, origin, clientSessionId, options, callbacks, debug = false, formStyles) {
|
|
223
243
|
let iframe = null;
|
|
244
|
+
let iframeErrorHandler = null;
|
|
224
245
|
let container = null;
|
|
225
246
|
let state = {
|
|
226
247
|
isEmpty: true,
|
|
@@ -231,6 +252,14 @@ function createFlintNField(fieldType, origin, clientSessionId, options, callback
|
|
|
231
252
|
const log = (...args) => {
|
|
232
253
|
if (debug) console.log(`[FlintN SDK][${fieldType}]`, ...args);
|
|
233
254
|
};
|
|
255
|
+
const reportError = (err) => {
|
|
256
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
257
|
+
if (callbacks.onError) {
|
|
258
|
+
queueMicrotask(() => callbacks.onError(error));
|
|
259
|
+
} else {
|
|
260
|
+
console.error(`[FlintN SDK][${fieldType}]`, error);
|
|
261
|
+
}
|
|
262
|
+
};
|
|
234
263
|
const sendMessage = (type, payload) => {
|
|
235
264
|
if (!iframe?.contentWindow) return;
|
|
236
265
|
iframe.contentWindow.postMessage({ type, payload }, origin);
|
|
@@ -258,18 +287,35 @@ function createFlintNField(fieldType, origin, clientSessionId, options, callback
|
|
|
258
287
|
const mount = (selector) => {
|
|
259
288
|
container = typeof selector === "string" ? document.querySelector(selector) : selector;
|
|
260
289
|
if (!container) {
|
|
261
|
-
|
|
262
|
-
|
|
290
|
+
reportError(
|
|
291
|
+
new Error(
|
|
292
|
+
`Field container not found for "${fieldType}": ${typeof selector === "string" ? selector : "element"}`
|
|
293
|
+
)
|
|
263
294
|
);
|
|
295
|
+
return;
|
|
264
296
|
}
|
|
265
|
-
|
|
266
|
-
|
|
297
|
+
try {
|
|
298
|
+
const src = buildIframeSrc(origin) + fieldType;
|
|
299
|
+
iframe = createIframeElement2(src);
|
|
300
|
+
} catch (err) {
|
|
301
|
+
reportError(err);
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
iframeErrorHandler = () => {
|
|
305
|
+
reportError(new Error(`Failed to load ${fieldType} iframe`));
|
|
306
|
+
};
|
|
307
|
+
iframe.addEventListener("error", iframeErrorHandler);
|
|
267
308
|
container.appendChild(iframe);
|
|
268
309
|
log("Mounted", fieldType);
|
|
269
310
|
};
|
|
270
311
|
const unmount = () => {
|
|
312
|
+
if (iframe && iframeErrorHandler) {
|
|
313
|
+
iframe.removeEventListener("error", iframeErrorHandler);
|
|
314
|
+
iframeErrorHandler = null;
|
|
315
|
+
}
|
|
271
316
|
if (iframe && container?.contains(iframe)) container.removeChild(iframe);
|
|
272
317
|
iframe = null;
|
|
318
|
+
container = null;
|
|
273
319
|
state = { isEmpty: true, isValid: false, isFocused: false, error: null };
|
|
274
320
|
log("Unmounted", fieldType);
|
|
275
321
|
};
|
|
@@ -333,11 +379,46 @@ function createFlintNField(fieldType, origin, clientSessionId, options, callback
|
|
|
333
379
|
// src/flintn-fields.ts
|
|
334
380
|
var DEFAULT_ORIGIN2 = "https://pay.flintn.com";
|
|
335
381
|
var OPERATION_TIMEOUT = 3e4;
|
|
382
|
+
function createInertFields() {
|
|
383
|
+
const errorResult = {
|
|
384
|
+
status: "PAYMENT_ERROR",
|
|
385
|
+
error: { code: "INIT_ERROR", message: "SDK init failed" }
|
|
386
|
+
};
|
|
387
|
+
return {
|
|
388
|
+
createField: () => {
|
|
389
|
+
throw new Error(
|
|
390
|
+
"[FlintN SDK] Cannot create field \u2014 SDK init failed (see onError)"
|
|
391
|
+
);
|
|
392
|
+
},
|
|
393
|
+
getField: () => void 0,
|
|
394
|
+
validate: async () => ({ isValid: false, errors: {} }),
|
|
395
|
+
submit: async () => errorResult,
|
|
396
|
+
unmount: () => {
|
|
397
|
+
},
|
|
398
|
+
getIsReady: () => false
|
|
399
|
+
};
|
|
400
|
+
}
|
|
336
401
|
function createFlintNFields(options) {
|
|
337
|
-
|
|
338
|
-
|
|
402
|
+
const reportInitError = (err) => {
|
|
403
|
+
const error = {
|
|
404
|
+
code: "INIT_ERROR",
|
|
405
|
+
message: err instanceof Error ? err.message : "Failed to initialize fields"
|
|
406
|
+
};
|
|
407
|
+
queueMicrotask(() => {
|
|
408
|
+
if (options.onError) options.onError(error);
|
|
409
|
+
else console.error("[FlintN SDK]", error);
|
|
410
|
+
});
|
|
411
|
+
};
|
|
412
|
+
let origin;
|
|
413
|
+
try {
|
|
414
|
+
if (!options.config?.clientSessionId) {
|
|
415
|
+
throw new Error("config.clientSessionId is required");
|
|
416
|
+
}
|
|
417
|
+
origin = parseOrigin(options.origin || DEFAULT_ORIGIN2);
|
|
418
|
+
} catch (err) {
|
|
419
|
+
reportInitError(err);
|
|
420
|
+
return createInertFields();
|
|
339
421
|
}
|
|
340
|
-
const origin = parseOrigin(options.origin || DEFAULT_ORIGIN2);
|
|
341
422
|
const fields = /* @__PURE__ */ new Map();
|
|
342
423
|
const readyFields = /* @__PURE__ */ new Set();
|
|
343
424
|
let allReady = false;
|
|
@@ -438,7 +519,8 @@ function createFlintNFields(options) {
|
|
|
438
519
|
onFocus: onFieldFocus,
|
|
439
520
|
onBlur: onFieldBlur,
|
|
440
521
|
onHeight: () => {
|
|
441
|
-
}
|
|
522
|
+
},
|
|
523
|
+
onError: reportInitError
|
|
442
524
|
},
|
|
443
525
|
options.debug,
|
|
444
526
|
options.config.styles
|
|
@@ -467,12 +549,22 @@ function createFlintNFields(options) {
|
|
|
467
549
|
};
|
|
468
550
|
const submit = async (submitOptions = {}, skipValidation = false) => {
|
|
469
551
|
if (!fields.has(FieldType.CARD_NUMBER)) {
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
552
|
+
return {
|
|
553
|
+
status: "PAYMENT_ERROR",
|
|
554
|
+
error: {
|
|
555
|
+
code: "CARD_NUMBER_NOT_INITIALIZED",
|
|
556
|
+
message: 'card-number field not initialized. Call createField("card-number") before submit().'
|
|
557
|
+
}
|
|
558
|
+
};
|
|
473
559
|
}
|
|
474
560
|
if (pendingSubmit) {
|
|
475
|
-
|
|
561
|
+
return {
|
|
562
|
+
status: "PAYMENT_ERROR",
|
|
563
|
+
error: {
|
|
564
|
+
code: "SUBMIT_IN_PROGRESS",
|
|
565
|
+
message: "A submit is already in progress"
|
|
566
|
+
}
|
|
567
|
+
};
|
|
476
568
|
}
|
|
477
569
|
if (!skipValidation) {
|
|
478
570
|
const validation = await validate();
|
|
@@ -489,17 +581,24 @@ function createFlintNFields(options) {
|
|
|
489
581
|
return new Promise((resolve, reject) => {
|
|
490
582
|
const timer = setTimeout(() => {
|
|
491
583
|
if (pendingSubmit && pendingSubmit.timer === timer) {
|
|
492
|
-
|
|
584
|
+
const timeoutResult = {
|
|
585
|
+
status: "PAYMENT_ERROR",
|
|
586
|
+
error: {
|
|
587
|
+
code: "SUBMIT_TIMEOUT",
|
|
588
|
+
message: "Submit timed out"
|
|
589
|
+
}
|
|
590
|
+
};
|
|
591
|
+
pendingSubmit.resolve(timeoutResult);
|
|
592
|
+
options.onPayment?.(timeoutResult);
|
|
493
593
|
pendingSubmit = null;
|
|
494
594
|
}
|
|
495
595
|
}, OPERATION_TIMEOUT);
|
|
496
596
|
pendingSubmit = { resolve, reject, timer };
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
}
|
|
597
|
+
const coordinator = fields.get(FieldType.CARD_NUMBER);
|
|
598
|
+
coordinator?._sendMessage(FieldEventType.FIELD_SUBMIT, {
|
|
599
|
+
clientSessionId: options.config.clientSessionId,
|
|
600
|
+
cardholderName: submitOptions.cardholderName
|
|
601
|
+
});
|
|
503
602
|
log("Submit initiated");
|
|
504
603
|
});
|
|
505
604
|
};
|