Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/button-angular/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ integrating Google Pay into your website.
<td>
<p>Invoked when the Google Pay button is clicked, before the payment sheet is displayed.</p>
<p>Display of the payment sheet can be prevented by calling <code>event.preventDefault()</code>.</p>
<p>It is possible to return <code>Promise</code> with a <code>boolean</code> value from the click handler to delay showing the payment sheet or even prevent it, by returning <code>false</code>. Return <code>true</code> to let the regular behavior continue.</p>
</td>
</tr>
<tr>
Expand Down
1 change: 1 addition & 0 deletions src/button-element/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ integrating Google Pay into your website.
<td>
<p>Invoked when the Google Pay button is clicked, before the payment sheet is displayed.</p>
<p>Display of the payment sheet can be prevented by calling <code>event.preventDefault()</code>.</p>
<p>It is possible to return <code>Promise</code> with a <code>boolean</code> value from the click handler to delay showing the payment sheet or even prevent it, by returning <code>false</code>. Return <code>true</code> to let the regular behavior continue.</p>
</td>
</tr>
<tr>
Expand Down
1 change: 1 addition & 0 deletions src/button-react/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ integrating Google Pay into your website.
<td>
<p>Invoked when the Google Pay button is clicked, before the payment sheet is displayed.</p>
<p>Display of the payment sheet can be prevented by calling <code>event.preventDefault()</code>.</p>
<p>It is possible to return <code>Promise</code> with a <code>boolean</code> value from the click handler to delay showing the payment sheet or even prevent it, by returning <code>false</code>. Return <code>true</code> to let the regular behavior continue.</p>
</td>
</tr>
<tr>
Expand Down
26 changes: 26 additions & 0 deletions src/lib/button-manager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
});
18 changes: 12 additions & 6 deletions src/lib/button-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<boolean>;
buttonType?: google.payments.api.ButtonType;
buttonColor?: google.payments.api.ButtonColor;
buttonRadius?: number;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

Expand Down