flintn-checkout 0.0.14 → 0.0.16

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 CHANGED
@@ -243,7 +243,8 @@ Do **not** set a fixed `height` on the container — it will leave empty space b
243
243
  |----------|------|----------|-------------|
244
244
  | `clientSessionId` | `string` | Yes | Client session ID from backend |
245
245
  | `formFields` | `FormFields` | No | Form display options — layout via `formVariant`. Field visibility and requirements are controlled by the merchant session configuration, not SDK options |
246
- | `styles` | `FormStyles` | No | Custom styles for the checkout form |
246
+ | `styles` | `FormStyles` | No | Custom styles (colors, border radius, text) for the checkout form |
247
+ | `placeholders` | `FormPlaceholders` | No | Per-field placeholder text overrides (see `FormPlaceholders`) |
247
248
  | `successRedirectUrl` | `string` | No | Redirect URL after successful payment |
248
249
 
249
250
  ### React Hook Return Values
@@ -264,7 +265,12 @@ Individual PCI-compliant input fields rendered as separate iframes. You control
264
265
 
265
266
  Each field (card number, expiry, CVV) is a separate iframe. Raw card data never touches your page.
266
267
 
267
- > **Note:** Hosted Fields emits only the terminal `onPayment` event there is no `onEvent` per-attempt stream. Use Iframe Checkout if you need granular attempt analytics.
268
+ When a card payment requires 3DS, the SDK shows the bank's challenge in a
269
+ **modal dialog on your page**. The buyer can dismiss it, which surfaces as a
270
+ `THREE_DS_CANCELLED` payment error. While the challenge is open, the
271
+ `submit()` promise stays pending with a 10-minute timeout.
272
+
273
+ > **Note:** For card fields, Hosted Fields emits only the terminal `onPayment` event. The express buttons additionally emit per-attempt wallet analytics via the top-level `onEvent` callback (same `onPayment` / `onEvent` split as Iframe Checkout) — see "Express buttons" below. For full per-attempt analytics across the card form too, use Iframe Checkout.
268
274
 
269
275
  **React**
270
276
 
@@ -423,6 +429,7 @@ Additional React-only options:
423
429
  | `onChange` | `(event: FieldChangeEvent) => void` | Optional additional callback |
424
430
  | `onFocus` | `(fieldType: TFieldType) => void` | Optional additional callback |
425
431
  | `onBlur` | `(fieldType: TFieldType, state: FieldState) => void` | Optional additional callback |
432
+ | `onEvent` | `(event: ExpressAttempt) => void` | Per-attempt wallet analytics from the express buttons (see "Express buttons") |
426
433
 
427
434
  ### FieldOptions
428
435
 
@@ -438,6 +445,10 @@ Additional React-only options:
438
445
  | `cardNumberRef` | `RefObject<HTMLDivElement>` | Ref for card number container |
439
446
  | `expiryRef` | `RefObject<HTMLDivElement>` | Ref for expiry container |
440
447
  | `cvvRef` | `RefObject<HTMLDivElement>` | Ref for CVV container |
448
+ | `applePayRef` | `RefObject<HTMLDivElement>` | Ref for the Apple Pay button container (attaching it enables the wallet) |
449
+ | `googlePayRef` | `RefObject<HTMLDivElement>` | Ref for the Google Pay button container (attaching it enables the wallet) |
450
+ | `payPalRef` | `RefObject<HTMLDivElement>` | Ref for the PayPal button container (attaching it enables the wallet) |
451
+ | `expressAvailable` | `boolean` | True once wallet detection settles and at least one express button is renderable |
441
452
  | `isReady` | `boolean` | All fields loaded and ready |
442
453
  | `fieldErrors` | `Partial<Record<TFieldType, string \| null>>` | Per-field validation errors (populated after first submit) |
443
454
  | `fieldStates` | `Partial<Record<TFieldType, FieldState>>` | Per-field state (always up to date) |
@@ -478,6 +489,105 @@ Validation mirrors react-hook-form `mode: 'onSubmit'`:
478
489
  | `field.getState()` | Get current field state |
479
490
  | `field.getFieldType()` | Get the field type |
480
491
 
492
+ ### Express buttons (Apple Pay / Google Pay / PayPal)
493
+
494
+ Hosted Fields can also render **fast checkout buttons** so buyers can pay with a
495
+ wallet instead of typing card details. The buttons render **directly into your
496
+ DOM** — one element per wallet, no iframe. Your page's own layout sizes and
497
+ positions each button; wallet UI (the Apple Pay sheet or desktop QR modal, the
498
+ Google Pay sheet, the PayPal popup) overlays your page natively. Only encrypted
499
+ wallet tokens pass through the page; they are authorized against the
500
+ session-scoped payments API, so no API key ever reaches the browser. Terminal
501
+ results arrive through the **same `onPayment`** callback as the card `submit()`.
502
+
503
+ **React**
504
+
505
+ ```tsx
506
+ import { useFlintNFields } from 'flintn-checkout/react';
507
+
508
+ function CheckoutForm() {
509
+ const {
510
+ cardNumberRef, expiryRef, cvvRef,
511
+ applePayRef, googlePayRef, payPalRef, // one container per wallet
512
+ expressAvailable, // true once ≥1 wallet button is renderable
513
+ submit,
514
+ } = useFlintNFields({
515
+ config: { clientSessionId: 'your_client_session_id' },
516
+ onPayment: (result) => {
517
+ if (result.status === 'PAYMENT_SUCCESS') console.log('Paid:', result.data);
518
+ },
519
+ onEvent: (e) => console.log('express attempt:', e.event, e.method),
520
+ });
521
+
522
+ return (
523
+ <form onSubmit={(e) => { e.preventDefault(); submit(); }}>
524
+ {/* attach a ref to enable that wallet; unavailable wallets render
525
+ nothing — collapse empty containers via CSS if they carry spacing */}
526
+ <div ref={applePayRef} />
527
+ <div ref={googlePayRef} />
528
+ <div ref={payPalRef} />
529
+ {expressAvailable && <div className="divider">or pay by card</div>}
530
+
531
+ <div ref={cardNumberRef} style={{ height: 40 }} />
532
+ <div ref={expiryRef} style={{ height: 40 }} />
533
+ <div ref={cvvRef} style={{ height: 40 }} />
534
+ <button type="submit">Pay</button>
535
+ </form>
536
+ );
537
+ }
538
+ ```
539
+
540
+ **Vanilla JavaScript**
541
+
542
+ ```javascript
543
+ import { createFlintNFields } from 'flintn-checkout';
544
+
545
+ const fields = createFlintNFields({
546
+ config: { clientSessionId: 'your_client_session_id' },
547
+ onPayment: (result) => console.log('Payment result:', result),
548
+ });
549
+
550
+ const express = fields.createExpressButtons({
551
+ onCapability: (cap) => console.log('available wallets:', cap),
552
+ onEvent: (attempt) => console.log('express attempt:', attempt),
553
+ });
554
+
555
+ await express.mountExpressButtons([
556
+ { method: 'APPLE_PAY', elementSelector: '#apple-pay' },
557
+ { method: 'GOOGLE_PAY', elementSelector: '#google-pay' },
558
+ { method: 'PAYPAL', elementSelector: '#paypal' },
559
+ ]);
560
+
561
+ // unmount a single wallet, or all of them
562
+ express.unmountExpressButton('APPLE_PAY');
563
+ express.unmountAllExpressButtons();
564
+
565
+ // card fields as usual
566
+ fields.createField('card-number').mount('#card-number');
567
+ fields.createField('expiry').mount('#expiry');
568
+ fields.createField('cvv').mount('#cvv');
569
+ ```
570
+
571
+ Notes:
572
+
573
+ - **No `submit()` for express.** Wallet buttons self-trigger (the buyer taps Apple
574
+ Pay and the sheet opens). Success/error come through `onPayment`; per-attempt
575
+ analytics through the top-level `onEvent` (React) /
576
+ `createExpressButtons({ onEvent })` (vanilla).
577
+ - **Availability.** Buttons for methods that are unavailable on this
578
+ device/session are silently skipped at mount — their containers just stay
579
+ empty. `expressAvailable` (React) / the `onCapability` callback (vanilla)
580
+ gate your "or pay by card" divider.
581
+ - **Which wallets appear** is driven entirely by the merchant session config
582
+ (`payment_methods`) intersected with device support — there is no client-side
583
+ allow-list.
584
+ - **3DS** for wallet payments is handled automatically via a popup (make sure the
585
+ buyer's click isn't intercepted by a popup blocker).
586
+ - **Apple Pay domain registration.** Your live domain must be registered with
587
+ Apple (handled during merchant onboarding) — merchant validation runs against
588
+ the domain the buttons render on. On non-Safari browsers Apple's JS SDK shows
589
+ its QR-code modal over your page. Google Pay and PayPal have no such limits.
590
+
481
591
  ---
482
592
 
483
593
  ## Shared Types
@@ -502,6 +612,38 @@ interface PaymentError {
502
612
  }
503
613
  ```
504
614
 
615
+ ### Error handling
616
+
617
+ Errors surface through three separate channels — don't conflate them:
618
+
619
+ | Channel | What lands there | Show as |
620
+ |---------|------------------|---------|
621
+ | `error` / `onError` | Infrastructure: SDK failed to initialize, a container is missing, the session config couldn't load | Page-level banner ("checkout unavailable / session expired") |
622
+ | `paymentResult` / `onPayment` with `PAYMENT_ERROR` | A payment attempt failed (card or wallet) | Inline payment error, offer retry |
623
+ | `fieldErrors` | Per-field validation (populated after the first `submit()`/`validate()`) | Messages next to each field |
624
+
625
+ Common `code` values:
626
+
627
+ | Code | Channel | Meaning |
628
+ |------|---------|---------|
629
+ | `INIT_ERROR` | error | SDK could not initialize (missing `clientSessionId`, bad `origin`) |
630
+ | `MOUNT_ERROR` | error | A field/button container was not found or failed to mount |
631
+ | `SESSION_EXPIRED` (and other API codes) | error or payment | Passed through from the payments API as-is |
632
+ | `CONFIG_ERROR` | error | Session config failed to load and the API gave no code |
633
+ | `NETWORK_ERROR` / `HTTP_<status>` / `INVALID_RESPONSE` | error or payment | Network failure / HTTP error without an API code / malformed response |
634
+ | `VALIDATION_ERROR` | payment | `submit()` blocked by field validation (details in `fieldErrors`) |
635
+ | `MISSING_FIELDS` / `NOT_INITIALIZED` / `SUBMIT_IN_PROGRESS` / `SUBMIT_TIMEOUT` | payment | Card `submit()` preconditions / duplicate call / no response in time (30s; 10 min during a 3DS challenge) |
636
+ | `PAYMENT_DECLINED` / processor decline codes | payment | Declined; the processor's own code is passed through when present |
637
+ | `PAYMENT_FAILED` | payment | Non-declined failure (including unexpected 3DS outcomes) |
638
+ | `APPLE_PAY_SDK_ERROR` / `GOOGLE_PAY_SDK_ERROR` / `PAYPAL_ERROR` | payment | The wallet SDK failed mid-flow |
639
+ | `PAYPAL_MISSING_PAYMENT_ID` | payment | PayPal approved but no payment id was captured (anomaly) |
640
+ | `THREE_DS_FAILED` / `THREE_DS_CANCELLED` | payment | Challenge declined / dismissed by the buyer |
641
+ | `THREE_DS_POPUP_BLOCKED` | payment | Express buttons only — the wallet 3DS window was blocked by the browser |
642
+
643
+ Worth handling specifically: `SESSION_EXPIRED` (create a fresh session and remount),
644
+ `THREE_DS_POPUP_BLOCKED` (ask the buyer to allow popups), `VALIDATION_ERROR`
645
+ (highlight fields from `fieldErrors`). Everything else is safely generic.
646
+
505
647
  ### CheckoutEvent
506
648
 
507
649
  ```typescript
@@ -619,8 +761,13 @@ interface FormStyles {
619
761
  inputBorderHoverColor?: string;
620
762
  inputBorderFocusColor?: string;
621
763
  inputBorderErrorColor?: string;
764
+ inputTextColor?: string;
765
+ inputFontSize?: string;
766
+ inputHeight?: string;
767
+ placeholderColor?: string;
622
768
  errorMessageColor?: string;
623
769
  labelColor?: string;
770
+ labelFontSize?: string;
624
771
  dividerColor?: string;
625
772
  dividerTextColor?: string;
626
773
  safeCheckoutAccentColor?: string;
@@ -637,6 +784,8 @@ interface FormStyles {
637
784
  buttonColor?: string;
638
785
  buttonHoverColor?: string;
639
786
  buttonBorderRadius?: string;
787
+ buttonHeight?: string;
788
+ buttonFontSize?: string;
640
789
  buttonText?: string;
641
790
  cardButtonColor?: string;
642
791
  cardButtonHoverColor?: string;
@@ -644,6 +793,30 @@ interface FormStyles {
644
793
  }
645
794
  ```
646
795
 
796
+ ### FormPlaceholders
797
+
798
+ ```typescript
799
+ interface FormPlaceholders {
800
+ email?: string;
801
+ cardNumber?: string;
802
+ expiry?: string;
803
+ cvv?: string;
804
+ cardholderName?: string;
805
+ addressLine1?: string;
806
+ addressLine2?: string;
807
+ city?: string;
808
+ state?: string;
809
+ postalCode?: string;
810
+ country?: string;
811
+ }
812
+ ```
813
+
814
+ Per-field placeholder text overrides for the **iframe checkout** form, passed as
815
+ `config.placeholders` (not under `styles` — placeholder text is field content, not
816
+ visual styling). Any field left undefined keeps its built-in default placeholder.
817
+ For **hosted fields**, set placeholder text per field via the `placeholder` option
818
+ on `createField` (or the `fields` prop of `useFlintNFields`) instead.
819
+
647
820
  ### FormStyles Reference
648
821
 
649
822
  | Property | Iframe Checkout | Hosted Fields | Description |
@@ -651,16 +824,21 @@ interface FormStyles {
651
824
  | `loaderColor` | ✅ | — | Loading spinner color |
652
825
  | `backgroundColor` | ✅ | — | Form background color |
653
826
  | `lightLogos` | ✅ | — | Use light logo variants in the safe-checkout row (for dark backgrounds) |
654
- | `expressButtonsSpacing` | ✅ | — | Spacing between express payment buttons |
655
- | `expressButtonsBorderRadius` | ✅ | | Corner radius for express buttons — Apple Pay, Google Pay, PayPal, and the "Credit or debit card" button in the LIST variant (e.g. `8px`) |
827
+ | `expressButtonsSpacing` | ✅ | — | Spacing between express payment buttons. Not applicable to Hosted Fields — the buttons render into your own containers, so spacing is your page's layout |
828
+ | `expressButtonsBorderRadius` | ✅ | | Corner radius for express buttons — Apple Pay, Google Pay, PayPal, and the "Credit or debit card" button in the LIST variant (e.g. `8px`). In Hosted Fields it applies to all wallet buttons at once |
656
829
  | `inputBackgroundColor` | ✅ | ✅ | Input field background color |
657
830
  | `inputBorderRadius` | ✅ | ✅ | Input field border radius |
658
831
  | `inputBorderColor` | ✅ | ✅ | Default input border color |
659
832
  | `inputBorderHoverColor` | ✅ | ✅ | Input border color on hover |
660
833
  | `inputBorderFocusColor` | ✅ | ✅ | Input border color on focus |
661
834
  | `inputBorderErrorColor` | ✅ | ✅ | Input border color in error state |
835
+ | `inputTextColor` | ✅ | ✅ | Input text (typed value) color |
836
+ | `inputFontSize` | ✅ | ✅ | Input text font size (e.g. `16px`) |
837
+ | `inputHeight` | ✅ | ✅ | Total input field height, border included (e.g. `48px`; default `40px`) |
838
+ | `placeholderColor` | ✅ | ✅ | Input placeholder text color |
662
839
  | `errorMessageColor` | ✅ | — | Error message text color |
663
840
  | `labelColor` | ✅ | — | Field label text color |
841
+ | `labelFontSize` | ✅ | — | Field label font size (e.g. `14px`) |
664
842
  | `dividerColor` | ✅ | — | Divider line color ("or" + "safe checkout" dividers) |
665
843
  | `dividerTextColor` | ✅ | — | "or" divider text color |
666
844
  | `safeCheckoutAccentColor` | ✅ | — | "Safe" accent word color (defaults to theme success) |
@@ -677,6 +855,8 @@ interface FormStyles {
677
855
  | `buttonColor` | ✅ | — | Submit button background color |
678
856
  | `buttonHoverColor` | ✅ | — | Submit button hover color |
679
857
  | `buttonBorderRadius` | ✅ | — | Submit button border radius |
858
+ | `buttonHeight` | ✅ | — | Submit button height (e.g. `48px`; default `40px`) |
859
+ | `buttonFontSize` | ✅ | — | Submit button text font size (e.g. `16px`; default `14px`) |
680
860
  | `buttonText` | ✅ | — | Custom submit button text |
681
861
  | `cardButtonColor` | ✅ | — | Card button color (LIST variant) |
682
862
  | `cardButtonHoverColor` | ✅ | — | Card button hover color (LIST variant) |
@@ -715,6 +895,7 @@ Every cancellation still emits a `CANCELLED` `onEvent` regardless of variant, so
715
895
 
716
896
  ### Hosted Fields
717
897
  - Credit/Debit Cards (Visa, Mastercard, Amex, Discover)
898
+ - Apple Pay, Google Pay, PayPal (via the express buttons — see "Express buttons" above)
718
899
 
719
900
  ## Debug Mode
720
901
 
package/dist/index.d.mts CHANGED
@@ -20,6 +20,19 @@ type TCheckoutFormVariant = (typeof CheckoutFormVariant)[keyof typeof CheckoutFo
20
20
  interface FormFields {
21
21
  formVariant?: TCheckoutFormVariant;
22
22
  }
23
+ interface FormPlaceholders {
24
+ email?: string;
25
+ cardNumber?: string;
26
+ expiry?: string;
27
+ cvv?: string;
28
+ cardholderName?: string;
29
+ addressLine1?: string;
30
+ addressLine2?: string;
31
+ city?: string;
32
+ state?: string;
33
+ postalCode?: string;
34
+ country?: string;
35
+ }
23
36
  interface FormStyles {
24
37
  loaderColor?: string;
25
38
  backgroundColor?: string;
@@ -32,8 +45,13 @@ interface FormStyles {
32
45
  inputBorderHoverColor?: string;
33
46
  inputBorderFocusColor?: string;
34
47
  inputBorderErrorColor?: string;
48
+ inputTextColor?: string;
49
+ inputFontSize?: string;
50
+ inputHeight?: string;
51
+ placeholderColor?: string;
35
52
  errorMessageColor?: string;
36
53
  labelColor?: string;
54
+ labelFontSize?: string;
37
55
  dividerColor?: string;
38
56
  dividerTextColor?: string;
39
57
  safeCheckoutAccentColor?: string;
@@ -50,6 +68,8 @@ interface FormStyles {
50
68
  buttonColor?: string;
51
69
  buttonHoverColor?: string;
52
70
  buttonBorderRadius?: string;
71
+ buttonHeight?: string;
72
+ buttonFontSize?: string;
53
73
  buttonText?: string;
54
74
  cardButtonColor?: string;
55
75
  cardButtonHoverColor?: string;
@@ -59,6 +79,7 @@ interface FlintNConfig {
59
79
  clientSessionId: string;
60
80
  formFields?: FormFields;
61
81
  styles?: FormStyles;
82
+ placeholders?: FormPlaceholders;
62
83
  successRedirectUrl?: string;
63
84
  }
64
85
  declare const PaymentMethod: {
@@ -150,6 +171,8 @@ declare const FieldEventType: {
150
171
  readonly FIELD_VALIDATION: "FIELD_VALIDATION";
151
172
  readonly FIELD_SUBMIT_RESULT: "FIELD_SUBMIT_RESULT";
152
173
  readonly FIELD_HEIGHT: "FIELD_HEIGHT";
174
+ readonly FIELD_THREE_DS_REQUIRED: "FIELD_THREE_DS_REQUIRED";
175
+ readonly FIELD_THREE_DS_RESULT: "FIELD_THREE_DS_RESULT";
153
176
  };
154
177
  type TFieldEventType = (typeof FieldEventType)[keyof typeof FieldEventType];
155
178
  interface FieldOptions {
@@ -179,8 +202,31 @@ interface FieldsValidationResult {
179
202
  isValid: boolean;
180
203
  errors: Partial<Record<TFieldType, string | null>>;
181
204
  }
205
+ interface SubmitBillingAddress {
206
+ addressLine1?: string;
207
+ addressLine2?: string;
208
+ city?: string;
209
+ state?: string;
210
+ postalCode?: string;
211
+ country?: string;
212
+ }
182
213
  interface SubmitOptions {
183
214
  cardholderName?: string;
215
+ email?: string;
216
+ billingAddress?: SubmitBillingAddress;
217
+ }
218
+ interface ExpressCapability {
219
+ applePay: boolean;
220
+ googlePay: boolean;
221
+ paypal: boolean;
222
+ }
223
+ interface ExpressAttempt {
224
+ event: TPaymentAttemptResult;
225
+ method: TPaymentMethod;
226
+ paymentId?: string;
227
+ code?: string;
228
+ message?: string;
229
+ timestamp: number;
184
230
  }
185
231
  interface FlintNFieldsConfig {
186
232
  clientSessionId: string;
@@ -226,9 +272,144 @@ interface FlintNField {
226
272
  }
227
273
  declare function createFlintNField(fieldType: TFieldType, origin: string, clientSessionId: string, options: FieldOptions, callbacks: FlintNFieldInternalCallbacks, debug?: boolean, formStyles?: FormStyles): FlintNField;
228
274
 
275
+ declare const EXPRESS_BUTTON_HEIGHT = 40;
276
+ declare const ExpressMethod: {
277
+ readonly APPLE_PAY: "APPLE_PAY";
278
+ readonly GOOGLE_PAY: "GOOGLE_PAY";
279
+ readonly PAYPAL: "PAYPAL";
280
+ };
281
+ type TExpressMethod = (typeof ExpressMethod)[keyof typeof ExpressMethod];
282
+ /** One entry per wallet button: which method goes into which element. */
283
+ interface ExpressButtonMount {
284
+ method: TExpressMethod;
285
+ /** CSS selector or the element itself. The button fills the element. */
286
+ elementSelector: string | HTMLElement;
287
+ }
288
+ interface FlintNExpressButtonsOptions {
289
+ config: {
290
+ clientSessionId: string;
291
+ };
292
+ origin?: string;
293
+ apiUrl?: string;
294
+ buttonBorderRadius?: number;
295
+ onPayment?: (result: PaymentResult) => void;
296
+ onEvent?: (event: ExpressAttempt) => void;
297
+ onCapability?: (capability: ExpressCapability) => void;
298
+ onError?: (error: PaymentError) => void;
299
+ debug?: boolean;
300
+ }
301
+ interface FlintNExpressButtons {
302
+ mountExpressButtons(buttons: ExpressButtonMount[]): Promise<void>;
303
+ unmountExpressButton(method: TExpressMethod): void;
304
+ unmountAllExpressButtons(): void;
305
+ }
306
+ interface ApplePayConfig {
307
+ country_code: string;
308
+ supported_networks: string[];
309
+ merchant_capabilities: string[];
310
+ display_name: string;
311
+ merchant_identifier?: string;
312
+ }
313
+ interface GooglePayConfig {
314
+ environment: string;
315
+ gateway: string;
316
+ gateway_merchant_id: string;
317
+ merchant_id?: string;
318
+ merchant_name?: string;
319
+ country_code?: string;
320
+ }
321
+ interface PayPalConfig {
322
+ client_id: string;
323
+ merchant_id?: string;
324
+ }
325
+ interface SessionConfig {
326
+ session: {
327
+ amount: number;
328
+ currency_code: string;
329
+ };
330
+ payment_methods: string[];
331
+ apple_pay_config?: ApplePayConfig;
332
+ google_pay_config?: GooglePayConfig;
333
+ paypal_config?: PayPalConfig;
334
+ }
335
+ declare const AuthorizedStatus: {
336
+ readonly PENDING: "PENDING";
337
+ readonly AUTHORIZED: "AUTHORIZED";
338
+ readonly FAILED: "FAILED";
339
+ readonly DECLINED: "DECLINED";
340
+ readonly THREE_DS_INITIATED: "THREE_DS_INITIATED";
341
+ };
342
+ type TAuthorizedStatus = (typeof AuthorizedStatus)[keyof typeof AuthorizedStatus];
343
+ interface AuthorizeResponse {
344
+ id: string;
345
+ status: TAuthorizedStatus;
346
+ required_action?: {
347
+ type: string;
348
+ redirect_url: string;
349
+ };
350
+ status_reason?: {
351
+ decline_reason?: string;
352
+ message?: string;
353
+ };
354
+ }
355
+ interface ApplePayToken {
356
+ payment_data: {
357
+ data: string;
358
+ header: {
359
+ ephemeral_public_key: string;
360
+ public_key_hash: string;
361
+ transaction_id: string;
362
+ };
363
+ signature: string;
364
+ version: string;
365
+ };
366
+ payment_method: {
367
+ display_name: string;
368
+ network: string;
369
+ type: string;
370
+ };
371
+ transaction_identifier: string;
372
+ }
373
+ interface GooglePayToken {
374
+ token: string;
375
+ }
376
+ /** Terminal-ish callbacks the wallet flows report into (mirrors the iframe's ExpressAuthorizeHandlers). */
377
+ interface WalletAuthorizeHandlers {
378
+ onAuthorized: (paymentId: string) => void;
379
+ onThreeDs: (redirectUrl: string, paymentId: string) => void;
380
+ onFailed: (code: string, message: string, paymentId?: string) => void;
381
+ }
382
+
383
+ /**
384
+ * Express fast-checkout buttons (Apple Pay / Google Pay / PayPal) rendered
385
+ * DIRECTLY into the merchant's DOM — one element per wallet, Yuno-style.
386
+ * There is no iframe: wallet SDKs load on the merchant page, wallet UI
387
+ * (Apple Pay QR modal, payment sheets) overlays the page natively, and the
388
+ * page's own layout sizes the buttons. Only encrypted wallet tokens pass
389
+ * through the page; they are authorized against the session-scoped payments
390
+ * API (no API key in the browser).
391
+ */
392
+ declare function createFlintNExpressButtons(options: FlintNExpressButtonsOptions): FlintNExpressButtons;
393
+
394
+ declare const deriveApiUrl: (payOrigin: string) => string;
395
+
396
+ /**
397
+ * Per-instance express options; session/origin/onPayment come from the fields
398
+ * instance, and button styling comes from `config.styles`
399
+ * (expressButtonsBorderRadius).
400
+ */
401
+ type ExpressButtonsOptions = Pick<FlintNExpressButtonsOptions, 'apiUrl' | 'onEvent' | 'onCapability'>;
229
402
  interface FlintNFields {
230
403
  createField(fieldType: TFieldType, options?: FieldOptions): FlintNField;
231
404
  getField(fieldType: TFieldType): FlintNField | undefined;
405
+ /**
406
+ * Create the express fast-checkout buttons (Apple Pay / Google Pay /
407
+ * PayPal), rendered directly into merchant-owned elements (one per wallet —
408
+ * see `mountExpressButtons`). Terminal results flow through the same
409
+ * `onPayment` callback as the card `submit()`; per-attempt analytics and
410
+ * capability flags are delivered via the options passed here.
411
+ */
412
+ createExpressButtons(options?: ExpressButtonsOptions): FlintNExpressButtons;
232
413
  validate(): Promise<FieldsValidationResult>;
233
414
  submit(options?: SubmitOptions, skipValidation?: boolean): Promise<PaymentResult>;
234
415
  unmount(): void;
@@ -244,4 +425,4 @@ declare const validateConfig: (config: {
244
425
  }) => void;
245
426
  declare const sanitizeToken: (token: string) => string;
246
427
 
247
- export { type CheckoutEvent, CheckoutFormVariant, CheckoutView, EventType, type FieldChangeEvent, FieldEventType, type FieldOptions, type FieldState, FieldType, type FieldValidationResult, type FieldsValidationResult, type FlintNConfig, type FlintNField, type FlintNFieldInternalCallbacks, type FlintNFields, type FlintNFieldsConfig, type FlintNFieldsOptions, type FlintNPayment, type FlintNPaymentOptions, type FormFields, type FormStyles, type PaymentAttempt, PaymentAttemptResult, type PaymentError, PaymentMethod, type PaymentResult, type PaymentUI, PaymentUIEvent, type SubmitOptions, type TCheckoutFormVariant, type TCheckoutView, type TEventType, type TFieldEventType, type TFieldType, type TPaymentAttemptResult, type TPaymentMethod, type TPaymentUIEvent, buildIframeSrc, createFlintNField, createFlintNFields, createFlintNPayment, createIframeElement, isAttemptEvent, isUIEvent, parseOrigin, sanitizeToken, validateConfig };
428
+ export { type ApplePayConfig, type ApplePayToken, type AuthorizeResponse, AuthorizedStatus, type CheckoutEvent, CheckoutFormVariant, CheckoutView, EXPRESS_BUTTON_HEIGHT, EventType, type ExpressAttempt, type ExpressButtonMount, type ExpressButtonsOptions, type ExpressCapability, ExpressMethod, type FieldChangeEvent, FieldEventType, type FieldOptions, type FieldState, FieldType, type FieldValidationResult, type FieldsValidationResult, type FlintNConfig, type FlintNExpressButtons, type FlintNExpressButtonsOptions, type FlintNField, type FlintNFieldInternalCallbacks, type FlintNFields, type FlintNFieldsConfig, type FlintNFieldsOptions, type FlintNPayment, type FlintNPaymentOptions, type FormFields, type FormPlaceholders, type FormStyles, type GooglePayConfig, type GooglePayToken, type PayPalConfig, type PaymentAttempt, PaymentAttemptResult, type PaymentError, PaymentMethod, type PaymentResult, type PaymentUI, PaymentUIEvent, type SessionConfig, type SubmitBillingAddress, type SubmitOptions, type TAuthorizedStatus, type TCheckoutFormVariant, type TCheckoutView, type TEventType, type TExpressMethod, type TFieldEventType, type TFieldType, type TPaymentAttemptResult, type TPaymentMethod, type TPaymentUIEvent, type WalletAuthorizeHandlers, buildIframeSrc, createFlintNExpressButtons, createFlintNField, createFlintNFields, createFlintNPayment, createIframeElement, deriveApiUrl, isAttemptEvent, isUIEvent, parseOrigin, sanitizeToken, validateConfig };