declare const CloverElementType: { readonly CARD: "CARD"; readonly NUMBER: "CARD_NUMBER"; readonly DATE: "CARD_DATE"; readonly CVV: "CARD_CVV"; readonly POSTAL_CODE: "CARD_POSTAL_CODE"; readonly STREET_ADDRESS: "CARD_STREET_ADDRESS"; readonly NAME: "CARD_NAME"; readonly EMAIL_ADDRESS: "CARD_EMAIL_ADDRESS"; readonly PHONE_NUMBER: "CARD_PHONE_NUMBER"; readonly PAYMENT_REQUEST_BUTTON: "PAYMENT_REQUEST_BUTTON"; }; type CloverElementType = (typeof CloverElementType)[keyof typeof CloverElementType]; /** * SDK-internal identifier for each rendered field. One-to-one with the Clover * element types except `CARD` (composite — we don't use it). */ type FieldKey = 'cardNumber' | 'cardDate' | 'cardCvv' | 'cardPostalCode' | 'cardName' | 'cardEmail' | 'paymentRequestButton'; /** Maps the SDK's FieldKey to Clover's element type. */ declare const FIELD_KEY_TO_CLOVER_TYPE: Record; /** * CSS properties Clover supports inside its iframe ``. Curated from * production usage in the WP plugin + Clover SDK behavior. Properties not * listed here are silently ignored by Clover; we don't pretend they work. */ interface CloverCssProperties { color?: string; fontFamily?: string; fontSize?: string; fontWeight?: string | number; lineHeight?: string | number; letterSpacing?: string; textAlign?: 'left' | 'right' | 'center' | 'inherit' | 'initial'; textIndent?: string; padding?: string; margin?: string; height?: string; width?: string; border?: string; borderRadius?: string; background?: string; backgroundColor?: string; } /** * Element-scoped selectors Clover honors. Each is the lower-kebab form of the * Clover element type (`CARD_EMAIL_ADDRESS` → `card-email-address`). Using a * shortened form (e.g. `card-email`) is silently ignored — Clover does not * warn, the style just never applies. Discovery captured 2026-05-18. */ type CloverElementSelector = 'card-number' | 'card-date' | 'card-cvv' | 'card-postal-code' | 'card-name' | 'card-email-address' | 'card-phone-number' | 'card-street-address'; /** * Placeholder pseudo-classes Clover honors. The vendor-prefixed forms are * required by older Clover versions; modern `::placeholder` is also accepted. * Production code in the WP plugin sets all four prefixed variants. */ type PlaceholderPseudo = '::placeholder' | '::-webkit-input-placeholder' | '::-moz-placeholder' | ':-ms-input-placeholder' | ':-moz-placeholder'; /** * Every selector key Clover's `elements.create(type, styles)` accepts. The * SDK exports this union so consumers get autocomplete and typo safety on * a previously-untyped JSON payload. * * - `'input'` — applies to the input in every element * - `''` — global placeholder rule * - `'card- input'` — per-element input rule * - `'card- input'` — per-element placeholder rule */ type CloverStyleSelector = 'input' | PlaceholderPseudo | CloverElementSelector | `${CloverElementSelector} input` | `${CloverElementSelector} input${PlaceholderPseudo}`; /** * Strongly-typed styles object for `clover.elements().create()`. Replaces * `type CloverElementStyles = object`. * * Most consumers should NOT construct this directly — pass a higher-level * `theme` on `PaymentFieldsConfig` and let `compileTheme()` emit the JSON. */ type CloverElementStyles = Partial>; /** * High-level theme config. The SDK compiles this into a `CloverElementStyles` * JSON object internally — most apps never need to touch the raw selectors. */ interface CloverFieldTheme { readonly fontFamily?: string; readonly fontSize?: string; readonly textColor?: string; readonly placeholderColor?: string; /** * Height of the input inside each Clover iframe. Must match (or slightly * exceed) the host wrapper's height so the entire wrapper is clickable. * Defaults to `'46px'` to match `.wcp-pf__field` in the SDK stylesheet. */ readonly inputHeight?: string; /** Extra style overrides merged on top of the theme-emitted defaults. */ readonly overrides?: CloverElementStyles; } interface CloverGlobal { new (pakms: string): CloverInstance; } interface CloverInstance { apiKey?: string; merchantId?: string; locale?: string; options?: CloverOptions; elements: () => CloverElements; createToken: () => Promise; } interface CloverOptions { locale?: string; merchantId?: string; showSecurePayments?: boolean; showPrivacyPolicy?: boolean; } interface CloverElements { create: (elementType: CloverElementType, styles: CloverElementStyles | CloverPaymentRequestData) => CloverElement; } interface CloverElement { mount: (selector: string) => void; addEventListener: (type: CloverElementEvent, listener: (event: Event) => void) => void; } type CloverElementEvent = 'change' | 'blur' | 'paymentMethodStart' | 'paymentMethod' | 'paymentMethodEnd'; interface CloverIframeTokenizationResponse extends Event { token?: string; errors?: Partial>; card?: { exp_month: string; exp_year: string; first6: string; last4: string; brand: string; address_zip?: string; }; } /** Shape passed to `elements.create(PAYMENT_REQUEST_BUTTON, paymentReqData)`. */ interface CloverPaymentRequestData { readonly paymentReqData: { readonly total: { readonly label: string; readonly currency: string; readonly amount: number; }; readonly options?: { readonly button?: { readonly buttonType?: 'short' | 'long'; }; }; }; } interface Clover3DSGlobal { new (config: { merchantUuid: string; }): ThreeDSUtil; } interface ThreeDSUtil { getBrowserInfo: () => ThreeDsBrowserInfo; perform3DSFingerPrinting: (args: { threeDSServerTransID: string; threeDSMethodUrl: string; methodNotificationUrl: string; }) => void; perform3DSChallenge: (args: { messageVersion: string; acsTransID: string; acsUrl: string; threeDSServerTransID: string; }) => void; } type ThreeDsBrowserInfo = Record; /** * Lifecycle states the SDK transitions through. See the lifecycle preview at * `design-previews/06-states.html` for what the customer sees in each state. */ type PaymentFieldsState = 'idle' | 'gpay_opening' | 'gpay_ready' | 'gpay_cancelled' | 'tokenizing' | 'submitting' | 'threeds_method' | 'threeds_challenge' | 'finalizing' | 'done' | 'error'; /** * Per-field validation state. Two error fields — `error` is the raw signal * from Clover, `displayedError` is what the UI should actually render. They * diverge for the deferred-error UX rule: while the user is mid-typing, raw * `error` may report "incomplete card", but we don't surface it until they * blur once. After first blur, the two stay in sync. See README → Events & * Validation, and the comment block at the top of `validation-machine.ts`. */ interface FieldValidationState { /** Clover-reported: user has interacted with the field. */ readonly touched: boolean; /** Clover-reported: raw error message, fires on every `change` event. */ readonly error?: string; /** SDK-derived: user has blurred this field at least once. */ readonly hasBlurred: boolean; /** SDK-derived: at least one `change` event has been observed for this field. */ readonly hadChangeEver: boolean; /** SDK-derived: the error to render. Undefined until first blur (deferred-error rule). */ readonly displayedError?: string; } interface ValidationSnapshot { /** Per-field touched + error state. Only fields actually mounted appear. */ readonly fields: { readonly [K in FieldKey]?: FieldValidationState; }; /** True when all required fields are valid (no errors, all touched). */ readonly canSubmit: boolean; } interface PaymentFieldsSnapshot { readonly state: PaymentFieldsState; readonly validation: ValidationSnapshot; /** Set when state is 'error' or after a recoverable failure. */ readonly error?: PaymentFieldsError; /** Set after successful tokenization (either path). */ readonly result?: TokenizationResult; /** Set during the 3DS flow. */ readonly threeDs?: ThreeDsInterim; } interface PaymentFieldsError { readonly code: PaymentFieldsErrorCode; readonly message: string; readonly cause?: unknown; } type PaymentFieldsErrorCode = 'clover_load_failed' | 'clover_3ds_load_failed' | 'not_mounted' | 'rate_limited' | 'tokenization_failed' | 'gpay_unavailable' | 'threeds_prerequisites_missing' | 'threeds_timeout' | 'threeds_finalize_failed' | 'unknown'; interface TokenizationResult { /** 'card' = manual entry tokenized via `clover.createToken()`. 'google_pay' = captured from `PAYMENT_REQUEST_BUTTON` paymentMethod event. */ readonly source: 'card' | 'google_pay'; readonly token: string; readonly card: { readonly brand: string; readonly last4: string; readonly expMonth?: string; readonly expYear?: string; readonly first6?: string; readonly addressZip?: string; }; /** 3DS browser fingerprint, collected when 3DS is enabled. */ readonly browserInfo?: ThreeDsBrowserInfo; } interface ThreeDsInterim { readonly state: 'method_required' | 'challenge_required'; readonly chargeId: string; readonly fields: ThreeDsInterimFields; } interface ThreeDsInterimFields { readonly acsUrl?: string; readonly acsTransactionId?: string; readonly methodUrl?: string; readonly methodNotificationUrl?: string; readonly threeDsServerTransactionId?: string; /** Clover varies the field name between `threeds_protocol_version` and `message_version`. The SDK normalizes to this. */ readonly protocolVersion?: string; } type ThreeDsResult = { readonly kind: 'success'; readonly redirect?: string; readonly data?: unknown; } | { readonly kind: 'escalation'; readonly next: ThreeDsInterim; } | { readonly kind: 'failure'; readonly message: string; }; interface PaymentFieldsConfig { readonly pakmsKey: string; readonly merchantId: string; readonly locale: string; readonly cartTotal: number; readonly currency: string; readonly country?: string; readonly cloverSdkUrl: string; readonly clover3DSSdkUrl?: string; readonly features?: PaymentFieldsFeatures; readonly endpoints?: PaymentFieldsEndpoints; readonly theme?: CloverFieldTheme; readonly onTokenized?: (result: TokenizationResult) => void; readonly onThreeDsRequired?: (interim: ThreeDsInterim) => void; readonly onError?: (error: PaymentFieldsError) => void; } interface PaymentFieldsFeatures { readonly googlePay?: boolean; readonly threeDSecure?: boolean; /** * Cardholder name + email field visibility. * - `'auto'` (default) — visible when 3DSecure is enabled * - `'always'` — visible always * - `'hidden'` — never rendered */ readonly cardholderFields?: 'auto' | 'always' | 'hidden'; readonly savedCredentials?: SavedCredential | readonly SavedCredential[]; } interface PaymentFieldsEndpoints { /** Host's POST URL for 3DS finalization (e.g., WC's `/wp-json/.../3ds/finalize`). */ readonly threeDsFinalize?: string; /** Returns headers (nonce, auth, etc.) for the finalize POST. Called per-request. */ readonly headers?: HeadersProvider; } type HeadersProvider = () => Record | Promise>; interface SavedCredential { readonly token: string; readonly last4: string; readonly brand: string; } interface MountTargets { readonly cardNumber: string; readonly cardDate: string; readonly cardCvv: string; readonly cardPostalCode: string; readonly cardName?: string; readonly cardEmail?: string; readonly paymentRequestButton?: string; } type PaymentFieldsListener = (snapshot: PaymentFieldsSnapshot) => void; type Unsubscribe = () => void; declare class PaymentFieldsMachine { /** The config the machine was constructed with. Read-only after construction. */ readonly config: PaymentFieldsConfig; private readonly listeners; private readonly rateLimiter; private snapshot; private mounted; private destroyed; private clover; private threeDsUtil; private registry; private validation; private capturedGpayToken; constructor(config: PaymentFieldsConfig); /** Subscribe to snapshot updates. The listener is called immediately with the current snapshot. */ subscribe(listener: PaymentFieldsListener): Unsubscribe; getSnapshot(): PaymentFieldsSnapshot; /** * Load the Clover SDK(s), create the elements, mount them to the host's DOM * targets, and wire validation + GPay event handlers. Idempotent — calling * again is a no-op. */ mount(targets: MountTargets): Promise; /** * Return a tokenization result the host can POST to the API. * * Two paths: * - **GPay**: if we're in `gpay_ready`, return the already-captured token immediately (no second prompt). * - **Manual card**: call `clover.createToken()`, rate-limited. * * Throws on rate-limit, invalid card, missing token, or unmounted state. */ tokenize(): Promise; /** * Drive the 3DS flow given an interim payload from the host's API response. * Handles method/challenge dispatch, the `executePatch` callback, the * finalize POST, and escalation (method ↔ challenge) internally. * * @param options.extraBody Host-specific fields merged into the finalize POST body. * E.g., WC passes `{ order_id, order_key, nonce }` so the WP REST endpoint * can find and update the order. Keeps WC-specific concerns out of the SDK. */ runThreeDs(interim: ThreeDsInterim, options?: { readonly extraBody?: Record; }): Promise; /** * Restore the form to idle, discarding any captured GPay token. Used by the * "Use card details instead" link on the GPay-ready state. */ resetToIdle(): void; destroy(): void; private shouldShowCardholderFields; private buildPaymentRequestData; private wireGpayEvents; private update; private emitError; } interface ElementRegistryOptions { readonly clover: CloverInstance; readonly styles: CloverElementStyles; /** Required when creating the `paymentRequestButton` field. */ readonly paymentRequestData?: CloverPaymentRequestData; } declare class ElementRegistry { private readonly elements; private readonly options; private destroyed; constructor(options: ElementRegistryOptions); /** * Create a Clover element for each key. Skips keys already created. * GPay button creation can throw on devices without PaymentRequest support — * caught + logged + skipped, never breaks the rest of the form. */ create(keys: readonly FieldKey[]): this; /** * Mount each created element at its target CSS selector. Skips fields whose * target is missing or whose host div doesn't exist in the DOM yet. */ mount(targets: MountTargets): this; get(key: FieldKey): CloverElement | undefined; entries(): IterableIterator<[FieldKey, CloverElement]>; destroy(): void; private mountIfTargeted; private assertAlive; } declare class ValidationMachine { private readonly state; private readonly required; private readonly listeners; constructor(requiredFields: readonly FieldKey[]); /** Wire up the validation machine to a set of Clover elements. */ attach(elements: Map): void; /** * Overlay tokenize-time errors onto per-field `displayedError`. Used when * `clover.createToken()` returns errors at submit time — we route them * back to the firing fields instead of joining them into a generic banner. * * For each field that errored we also set `hasBlurred = true`, so the * existing live-error-clearing rule kicks in: as soon as the user edits the * field, the next `change` event recomputes `displayedError` from Clover's * current state and clears the submit error. * * The Clover-side empty-vs-valid ambiguity for `CARD_NAME` / `CARD_EMAIL_ADDRESS` * means createToken may or may not emit errors for those fields when empty; * we surface whatever Clover reports and leave the rest as-is. */ setSubmitErrors(errors: Partial>): void; subscribe(listener: (snapshot: ValidationSnapshot) => void): Unsubscribe; getSnapshot(): ValidationSnapshot; private onCloverEvent; private computeCanSubmit; private emit; } interface ThreeDsMachineOptions { readonly util: ThreeDSUtil; readonly finalizeUrl: string; readonly headers?: HeadersProvider; /** Extra fields the host needs in the finalize body (order_id, order_key, nonce). */ readonly extraBody?: Record; readonly methodTimeoutMs?: number; readonly challengeTimeoutMs?: number; } declare class ThreeDsMachine { private readonly options; private cancelled; constructor(options: ThreeDsMachineOptions); cancel(): void; /** * Run a single 3DS interim payload to a terminal result. For escalation * (method completes → Clover wants challenge, or vice versa), the result * is returned with `kind: 'escalation'`; the caller (PaymentFieldsMachine) * re-enters the loop with the next interim. */ run(interim: ThreeDsInterim): Promise; private runMethod; private runChallenge; private awaitExecutePatch; private finalize; private styleChallengeContainer; } interface RateLimiter { /** Returns true if a call is allowed (and consumes a slot); false if rate-limited. */ check(): boolean; } interface CreateRateLimiterOptions { readonly windowMs?: number; readonly maxCalls?: number; } declare function createRateLimiter(options?: CreateRateLimiterOptions): RateLimiter; interface TokenizeOptions { readonly rateLimiter?: RateLimiter; } declare function tokenize(clover: CloverInstance, options?: TokenizeOptions): Promise; declare function loadClover(url: string): Promise; declare function loadClover3DS(url: string): Promise; declare function getBrowserInfo(util: ThreeDSUtil | undefined | null): ThreeDsBrowserInfo | undefined; declare function compileTheme(theme?: CloverFieldTheme): CloverElementStyles; interface FinalizeRequest { readonly url: string; readonly headers?: HeadersProvider; readonly body: Record; } interface FinalizeResponseEnvelope { readonly ok: boolean; readonly data: FinalizeResponseData | null; } interface FinalizeResponseData { readonly success?: boolean; readonly redirect?: string; readonly message?: string; /** When Clover escalates the flow, the host returns the next interim payload here. */ readonly weeconnectpay_threeds_interim?: ThreeDsInterimRaw; } /** Wire shape from Clover / the host before normalization to ThreeDsInterim. */ interface ThreeDsInterimRaw { readonly state: 'method_required' | 'challenge_required'; readonly charge_id: string | null; readonly threeds: { readonly acs_url?: string; readonly acs_transaction_id?: string; readonly method_url?: string; readonly method_notification_url?: string; readonly threeds_server_transaction_id?: string; readonly threeds_protocol_version?: string; /** Older Clover docs used `message_version` — both supported. */ readonly message_version?: string; }; } declare function postFinalize(request: FinalizeRequest): Promise; /** * Normalize the wire shape into the SDK's `ThreeDsInterim`. Returns null when * required fields (charge_id) are missing — the caller should treat as a * failure rather than entering a malformed state. */ declare function parseInterim(raw: ThreeDsInterimRaw): ThreeDsInterim | null; declare const __SDK_VERSION__ = "0.1.0"; export { type Clover3DSGlobal, type CloverCssProperties, type CloverElement, type CloverElementEvent, type CloverElementStyles, CloverElementType, type CloverElements, type CloverFieldTheme, type CloverGlobal, type CloverIframeTokenizationResponse, type CloverInstance, type CloverOptions, type CloverPaymentRequestData, type CloverStyleSelector, type CreateRateLimiterOptions, ElementRegistry, type ElementRegistryOptions, FIELD_KEY_TO_CLOVER_TYPE, type FieldKey, type FieldValidationState, type FinalizeRequest, type FinalizeResponseData, type FinalizeResponseEnvelope, type HeadersProvider, type MountTargets, type PaymentFieldsConfig, type PaymentFieldsEndpoints, type PaymentFieldsError, type PaymentFieldsErrorCode, type PaymentFieldsFeatures, type PaymentFieldsListener, PaymentFieldsMachine, type PaymentFieldsSnapshot, type PaymentFieldsState, type RateLimiter, type SavedCredential, type ThreeDSUtil, type ThreeDsBrowserInfo, type ThreeDsInterim, type ThreeDsInterimFields, type ThreeDsInterimRaw, ThreeDsMachine, type ThreeDsMachineOptions, type ThreeDsResult, type TokenizationResult, type TokenizeOptions, type Unsubscribe, ValidationMachine, type ValidationSnapshot, __SDK_VERSION__, compileTheme, createRateLimiter, getBrowserInfo, loadClover, loadClover3DS, parseInterim, postFinalize, tokenize };