From 4f22fb93c2d302a8bcf2e6ff507068fe7fee02a1 Mon Sep 17 00:00:00 2001 From: Paulo Vaz Date: Thu, 5 Mar 2026 12:24:13 +0100 Subject: [PATCH 1/3] feat: conditionally show payment sheet on click This change should allow the consumer application to conditionally show the payment sheet depending on the returned value of a Promise. If the click handler returns a promise, then its value is checked. If it is true then the payment sheet is displayed after the promise resolves. If the promise returns false then nothing happens. If the click handler does not return a promise, its return does not influence the behavior. In other words, the behavior is the same as before. --- src/lib/button-manager.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/lib/button-manager.ts b/src/lib/button-manager.ts index 5cc2a0b..4e5d08c 100644 --- a/src/lib/button-manager.ts +++ b/src/lib/button-manager.ts @@ -34,7 +34,7 @@ export interface Config { onCancel?: (reason: google.payments.api.PaymentsError) => void; onError?: (error: Error | google.payments.api.PaymentsError) => void; onReadyToPayChange?: (result: ReadyToPayChangeResponse) => void; - onClick?: (event: Event) => void; + onClick?: (event: Event) => void | Promise; buttonType?: google.payments.api.ButtonType; buttonColor?: google.payments.api.ButtonColor; buttonRadius?: number; @@ -270,9 +270,9 @@ export class ButtonManager { try { readyToPay = await this.client.isReadyToPay(this.createIsReadyToPayRequest(this.config)); showButton = - (readyToPay.result && !this.config.existingPaymentMethodRequired) - || (readyToPay.result && readyToPay.paymentMethodPresent && this.config.existingPaymentMethodRequired) - || false; + (readyToPay.result && !this.config.existingPaymentMethodRequired) || + (readyToPay.result && readyToPay.paymentMethodPresent && this.config.existingPaymentMethodRequired) || + false; } catch (err) { if (this.config.onError) { this.config.onError(err as Error); @@ -333,11 +333,17 @@ export class ButtonManager { const request = this.createLoadPaymentDataRequest(config); try { + let shouldProceed: boolean | null = null; + if (config.onClick) { - config.onClick(event); + const onClickResult = await config.onClick(event); + + if (typeof onClickResult === 'boolean') { + shouldProceed = onClickResult; + } } - if (event.defaultPrevented) { + if (event.defaultPrevented || shouldProceed === false) { return; } From d668cd0fa3d5e3487e5dbb30052d24acab0499aa Mon Sep 17 00:00:00 2001 From: Paulo Vaz Date: Thu, 5 Mar 2026 12:29:12 +0100 Subject: [PATCH 2/3] docs: update docs with new click handler functionality --- src/button-angular/README.md | 1 + src/button-element/README.md | 1 + src/button-react/README.md | 1 + 3 files changed, 3 insertions(+) diff --git a/src/button-angular/README.md b/src/button-angular/README.md index fb0bdd5..1590c14 100644 --- a/src/button-angular/README.md +++ b/src/button-angular/README.md @@ -184,6 +184,7 @@ integrating Google Pay into your website.

Invoked when the Google Pay button is clicked, before the payment sheet is displayed.

Display of the payment sheet can be prevented by calling event.preventDefault().

+

It is possible to return Promise with a boolean value from the click handler to delay showing the payment sheet or even prevent it, by returning false. Return true to let the regular behavior continue.

diff --git a/src/button-element/README.md b/src/button-element/README.md index 9197c2e..47a7413 100644 --- a/src/button-element/README.md +++ b/src/button-element/README.md @@ -285,6 +285,7 @@ integrating Google Pay into your website.

Invoked when the Google Pay button is clicked, before the payment sheet is displayed.

Display of the payment sheet can be prevented by calling event.preventDefault().

+

It is possible to return Promise with a boolean value from the click handler to delay showing the payment sheet or even prevent it, by returning false. Return true to let the regular behavior continue.

diff --git a/src/button-react/README.md b/src/button-react/README.md index 43cd8f6..8f574be 100644 --- a/src/button-react/README.md +++ b/src/button-react/README.md @@ -201,6 +201,7 @@ integrating Google Pay into your website.

Invoked when the Google Pay button is clicked, before the payment sheet is displayed.

Display of the payment sheet can be prevented by calling event.preventDefault().

+

It is possible to return Promise with a boolean value from the click handler to delay showing the payment sheet or even prevent it, by returning false. Return true to let the regular behavior continue.

From 4a8771b6f2a3f4be122ef115ef45f57fc020a048 Mon Sep 17 00:00:00 2001 From: Paulo Vaz Date: Thu, 5 Mar 2026 14:40:26 +0100 Subject: [PATCH 3/3] test: cover new click handler feature --- src/lib/button-manager.test.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/lib/button-manager.test.ts b/src/lib/button-manager.test.ts index b411d72..0f1b2cb 100644 --- a/src/lib/button-manager.test.ts +++ b/src/lib/button-manager.test.ts @@ -799,4 +799,30 @@ describe('Events', () => { expect(loadPaymentDataSpy).not.toBeCalled(); }); + + it('does not call onLoadPaymentData when onClick returns a Promise with false', async () => { + manager.configure({ + ...defaults, + onClick: _ => Promise.resolve(false), + onLoadPaymentData: loadPaymentDataSpy, + }); + + const event = new Event('click', { cancelable: true }); + await manager.handleClick(event); + + expect(loadPaymentDataSpy).not.toBeCalled(); + }); + + it('calls onLoadPaymentData when onClick returns a Promise with true', async () => { + manager.configure({ + ...defaults, + onClick: _ => Promise.resolve(true), + onLoadPaymentData: loadPaymentDataSpy, + }); + + const event = new Event('click', { cancelable: true }); + await manager.handleClick(event); + + expect(loadPaymentDataSpy).toBeCalled(); + }); });