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.

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(); + }); }); 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; }