onClick fires when the shopper taps a wallet button, before the native payment sheet opens. Use it to validate external state (cart totals, inventory, contact details) and either let the sheet open or cancel.
Emitted by applePay, googlePay, and checkout (when a wallet tab inside Checkout is tapped). Every other element omits the key from its event map; subscribing on a non-wallet element is a TypeScript error and a runtime no-op (with a console warning).
For analytics or telemetry on non-wallet elements, use onFocus, onBlur, or onChange.
Payload
Wallet elements:
Checkout:
Control flow
The gate mirrors the DOM preventDefault convention:
- No
preventDefault() call: the sheet opens immediately, in the same task as the click. Best for fire-and-forget telemetry.
preventDefault() then resolve(): the sheet opens. Both calls can land synchronously, or resolve() can fire from a later microtask or promise (subject to the Apple Pay constraint below).
preventDefault() then reject(): the sheet does not open. onError does not fire; a deliberate cancellation is not a failure. If you want UI feedback for the shopper, render it yourself.
Calling resolve() or reject() more than once is a no-op after the first decision. Calling either before preventDefault() is also a no-op.
Example (Apple Pay standalone)
Apple Pay synchronous constraint
Safari validates that the call that opens the Apple Pay sheet runs in the same synchronous task as the originating click. If preventDefault() is followed by an await (or any other deferred work) before resolve() lands, Safari invalidates the user gesture and the sheet fails to open. No error, no callback.
Apple Pay handlers that need to gate must do so synchronously: read pre-validated state from a local variable rather than awaiting a network call. Google Pay does not have this restriction.
This is a browser-level rule, not an SDK limitation.
Handler throws
If your handler throws synchronously, the gate is treated as reject(error) and onError additionally fires with code: 'unknown'. This applies whether or not preventDefault() was called first, so a bug in your handler never silently opens the sheet.
Checkout: branch on paymentMethod
When a wallet tab is tapped inside Checkout, the payload carries a paymentMethod discriminator so a single handler can branch:
Card and bank inside Checkout are intentionally absent from the paymentMethod discriminator. Card submission flows through the internal submit button; bank has no programmatically blockable default action distinct from submit(). For pre-submit gating that applies to card or bank, run validation at the top of your onSubmit handler and return early.
See also
Last modified on July 17, 2026