Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(google pay): Add support for existingPaymentMethodRequired #849

Merged
merged 1 commit into from
Sep 7, 2023
Merged
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
10 changes: 9 additions & 1 deletion lib/recurly/google-pay/google-pay.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,15 @@ const getGoogleInfoFromMerchantInfo = ({ recurlyMerchantInfo, options }) => {
},
};

return { gatewayCode, environment, isReadyToPayRequest, paymentDataRequest };
return {
gatewayCode,
environment,
isReadyToPayRequest: {
...isReadyToPayRequest,
...(options.existingPaymentMethodRequired === true && { existingPaymentMethodRequired: true }),
},
paymentDataRequest,
};
};

const buildPaymentDataRequest = ({ recurly, options }) => {
Expand Down
4 changes: 2 additions & 2 deletions lib/recurly/google-pay/pay-with-google.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ const payWithGoogle = ({ paymentOptions, isReadyToPayRequest, paymentDataRequest
.catch(err => {
throw recurlyError('google-pay-init-error', { err });
})
.then(({ result: isReadyToPay }) => {
if (!isReadyToPay) {
.then(({ result: isReadyToPay, paymentMethodPresent }) => {
if (!isReadyToPay || paymentMethodPresent === false) {
throw recurlyError('google-pay-not-available');
}

Expand Down
70 changes: 54 additions & 16 deletions test/unit/google-pay/google-pay.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -545,27 +545,65 @@ describe(`Google Pay`, function () {
});

context('when cannot proceed with the pay-with-google', function () {
beforeEach(function () {
this.stubGoogleAPIOpts.isReadyToPay = Promise.resolve({ result: false });
this.stubRequestAndGoogleApi();
});
context('when the GooglePay is not available', function () {
beforeEach(function () {
this.stubGoogleAPIOpts.isReadyToPay = Promise.resolve({ result: false });
this.stubRequestAndGoogleApi();
});

it('emits the same error the pay-with-google throws', function (done) {
const result = googlePay(this.recurly, this.googlePayOpts);
it('emits the same error the pay-with-google throws', function (done) {
const result = googlePay(this.recurly, this.googlePayOpts);

result.on('error', (err) => assertDone(done, () => {
assert.ok(err);
assert.equal(err.code, 'google-pay-not-available');
assert.equal(err.message, 'Google Pay is not available');
}));
result.on('error', (err) => assertDone(done, () => {
assert.ok(err);
assert.equal(err.code, 'google-pay-not-available');
assert.equal(err.message, 'Google Pay is not available');
}));
});

it('do not emit any token nor the on ready event', function (done) {
const result = googlePay(this.recurly, this.googlePayOpts);

result.on('ready', () => done(new Error('expected to not emit a ready event')));
result.on('token', () => done(new Error('expected to not emit a token event')));
nextTick(done);
});
});

it('do not emit any token nor the on ready event', function (done) {
const result = googlePay(this.recurly, this.googlePayOpts);
context('when the GooglePay is available but does not support user cards', function () {
beforeEach(function () {
this.googlePayOpts.existingPaymentMethodRequired = true;
this.stubGoogleAPIOpts.isReadyToPay = Promise.resolve({ result: true, paymentMethodPresent: false });
this.stubRequestAndGoogleApi();
});

it('initiates pay-with-google with the expected Google Pay Configuration', function (done) {
googlePay(this.recurly, this.googlePayOpts);

nextTick(() => assertDone(done, () => {
assert.equal(window.google.payments.api.PaymentsClient.called, true);
const isReadyToPayRequest = window.google.payments.api.PaymentsClient.prototype.isReadyToPay.getCall(0).args[0];
assert.equal(isReadyToPayRequest.existingPaymentMethodRequired, true);
}));
});

it('emits the same error the pay-with-google throws', function (done) {
const result = googlePay(this.recurly, this.googlePayOpts);

result.on('error', (err) => assertDone(done, () => {
assert.ok(err);
assert.equal(err.code, 'google-pay-not-available');
assert.equal(err.message, 'Google Pay is not available');
}));
});

result.on('ready', () => done(new Error('expected to not emit a ready event')));
result.on('token', () => done(new Error('expected to not emit a token event')));
nextTick(done);
it('do not emit any token nor the on ready event', function (done) {
const result = googlePay(this.recurly, this.googlePayOpts);

result.on('ready', () => done(new Error('expected to not emit a ready event')));
result.on('token', () => done(new Error('expected to not emit a token event')));
nextTick(done);
});
});
});

Expand Down
7 changes: 7 additions & 0 deletions types/lib/google-pay/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ export type GooglePayOptions = {
[key: string]: any
};

/**
* If set to true, then the Google Pay button will not be rendered and an error will be emitted if the user
* is not eligible to pay with Google Pay.
* See https://developers.google.com/pay/api/web/reference/request-objects#IsReadyToPayRequest for more information.
*/
existingPaymentMethodRequired?: boolean;

/**
* Requires the user to accept providing the full billing address.
* @deprecated use billingAddressRequired
Expand Down
Loading