🐛 Fixed updating payment method when beta flag is on (#20171)

refs https://linear.app/tryghost/issue/ONC-20
refs https://linear.app/tryghost/issue/ENG-867

- when using dynamic payment methods in Stripe, we need to provide a
currency. Stripe uses that parameter to determine which payment methods
to render
- docs: https://docs.stripe.com/api/checkout/sessions/create
This commit is contained in:
Sag 2024-05-08 20:56:17 +02:00 committed by GitHub
parent 9bf5a61d99
commit 60ac3c735b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 60 additions and 10 deletions

View File

@ -129,10 +129,14 @@ module.exports = class RouterController {
customer = await this._stripeAPIService.getCustomer(subscription.get('customer_id'));
}
const defaultTier = await this._tiersService.api.readDefaultTier();
const currency = defaultTier?.currency?.toLowerCase() || 'usd';
const session = await this._stripeAPIService.createCheckoutSetupSession(customer, {
successUrl: req.body.successUrl,
cancelUrl: req.body.cancelUrl,
subscription_id: req.body.subscription_id
subscription_id: req.body.subscription_id,
currency
});
const publicKey = this._stripeAPIService.getPublicKey();
const sessionInfo = {

View File

@ -556,7 +556,9 @@ module.exports = class StripeAPI {
/**
* @param {ICustomer} customer
* @param {object} options
*
* @param {string} options.successUrl
* @param {string} options.cancelUrl
* @param {string} options.currency - 3-letter ISO code in lowercase, e.g. `usd`
* @returns {Promise<import('stripe').Stripe.Checkout.Session>}
*/
async createCheckoutSetupSession(customer, options) {
@ -571,7 +573,11 @@ module.exports = class StripeAPI {
metadata: {
customer_id: customer.id
}
}
},
// Note: this is required for dynamic payment methods
// https://docs.stripe.com/api/checkout/sessions/create#create_checkout_session-currency
currency: this.labs.isSet('additionalPaymentMethods') ? options.currency : undefined
});
return session;

View File

@ -61,13 +61,6 @@ describe('StripeAPI', function () {
should.exist(mockStripe.checkout.sessions.create.firstCall.firstArg.cancel_url);
});
it('createCheckoutSetupSession sends success_url and cancel_url', async function () {
await api.createCheckoutSetupSession('priceId', {});
should.exist(mockStripe.checkout.sessions.create.firstCall.firstArg.success_url);
should.exist(mockStripe.checkout.sessions.create.firstCall.firstArg.cancel_url);
});
it('sets valid trialDays', async function () {
await api.createCheckoutSession('priceId', null, {
trialDays: 12
@ -162,6 +155,53 @@ describe('StripeAPI', function () {
});
});
describe('createCheckoutSetupSession', function () {
beforeEach(function () {
mockStripe = {
checkout: {
sessions: {
create: sinon.stub().resolves()
}
}
};
sinon.stub(mockLabs, 'isSet');
const mockStripeConstructor = sinon.stub().returns(mockStripe);
StripeAPI.__set__('Stripe', mockStripeConstructor);
api.configure({
checkoutSessionSuccessUrl: '/success',
checkoutSessionCancelUrl: '/cancel',
checkoutSetupSessionSuccessUrl: '/setup-success',
checkoutSetupSessionCancelUrl: '/setup-cancel',
secretKey: ''
});
});
afterEach(function () {
sinon.restore();
});
it('createCheckoutSetupSession sends success_url and cancel_url', async function () {
await api.createCheckoutSetupSession('priceId', {});
should.exist(mockStripe.checkout.sessions.create.firstCall.firstArg.success_url);
should.exist(mockStripe.checkout.sessions.create.firstCall.firstArg.cancel_url);
});
it('createCheckoutSetupSession does not send currency if additionalPaymentMethods flag is off', async function () {
mockLabs.isSet.withArgs('additionalPaymentMethods').returns(false);
await api.createCheckoutSetupSession('priceId', {currency: 'usd'});
should.not.exist(mockStripe.checkout.sessions.create.firstCall.firstArg.currency);
});
it('createCheckoutSetupSession sends currency if additionalPaymentMethods flag is on', async function () {
mockLabs.isSet.withArgs('additionalPaymentMethods').returns(true);
await api.createCheckoutSetupSession('priceId', {currency: 'usd'});
should.equal(mockStripe.checkout.sessions.create.firstCall.firstArg.currency, 'usd');
});
});
describe('getCustomerIdByEmail', function () {
describe('when no customer is found', function () {
beforeEach(function () {