Skip to content

Commit 06c7152

Browse files
committed
🐛 Fixed Stripe webhooks for subdirectory setups
no-issue - Added breaking test for webhook url including subdirectory - Previously the webhook handler URL was generated incorrectly when running Ghost on a subdirectory, appending the path to the root of the host, this fix ensures that the subdirectory is included before the path.
1 parent 832ecad commit 06c7152

File tree

2 files changed

+44
-3
lines changed

2 files changed

+44
-3
lines changed

core/server/services/members/config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ class MembersConfigProvider {
133133
getStripeUrlConfig() {
134134
const siteUrl = this._urlUtils.getSiteUrl();
135135

136-
const webhookHandlerUrl = new URL('/members/webhooks/stripe', siteUrl);
136+
const webhookHandlerUrl = new URL('members/webhooks/stripe/', siteUrl);
137137

138138
const checkoutSuccessUrl = new URL(siteUrl);
139139
checkoutSuccessUrl.searchParams.set('stripe', 'success');

test/unit/services/members/config_spec.js

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const should = require('should');
2+
const UrlUtils = require('@tryghost/url-utils');
23
const MembersConfigProvider = require('../../../../core/server/services/members/config');
3-
const urlUtils = require('../../../../core/shared/url-utils');
44
const sinon = require('sinon');
55

66
/**
@@ -19,7 +19,6 @@ function createConfigMock({stripeDirectValue}) {
1919
* @param {boolean} options.setDirect - Whether the "direct" keys should be set
2020
* @param {boolean} options.setConnect - Whether the connect_integration keys should be set
2121
*/
22-
2322
function createSettingsMock({setDirect, setConnect}) {
2423
const getStub = sinon.stub();
2524

@@ -51,10 +50,29 @@ function createSettingsMock({setDirect, setConnect}) {
5150
};
5251
}
5352

53+
function createUrlUtilsMock({url = 'http://domain.tld/subdir', adminUrl = 'http://sub.domain.tld'} = {}) {
54+
return new UrlUtils({
55+
url,
56+
adminUrl,
57+
apiVersions: {
58+
all: ['v3'],
59+
v3: {
60+
admin: 'v3/admin',
61+
content: 'v3/content'
62+
}
63+
},
64+
defaultApiVersion: 'v3',
65+
slugs: ['ghost', 'rss', 'amp'],
66+
redirectCacheMaxAge: 31536000,
67+
baseApiPath: '/ghost/api'
68+
});
69+
}
70+
5471
describe('Members - config', function () {
5572
it('Uses direct keys when stripeDirect is true, regardles of which keys exist', function () {
5673
const config = createConfigMock({stripeDirectValue: true});
5774
const settingsCache = createSettingsMock({setDirect: true, setConnect: Math.random() < 0.5});
75+
const urlUtils = createUrlUtilsMock();
5876

5977
const membersConfig = new MembersConfigProvider({
6078
config,
@@ -73,6 +91,7 @@ describe('Members - config', function () {
7391
it('Does not use connect keys if stripeDirect is true, and the direct keys do not exist', function () {
7492
const config = createConfigMock({stripeDirectValue: true});
7593
const settingsCache = createSettingsMock({setDirect: false, setConnect: true});
94+
const urlUtils = createUrlUtilsMock();
7695

7796
const membersConfig = new MembersConfigProvider({
7897
config,
@@ -90,6 +109,7 @@ describe('Members - config', function () {
90109
it('Uses connect keys when stripeDirect is false, and the connect keys exist', function () {
91110
const config = createConfigMock({stripeDirectValue: false});
92111
const settingsCache = createSettingsMock({setDirect: true, setConnect: true});
112+
const urlUtils = createUrlUtilsMock();
93113

94114
const membersConfig = new MembersConfigProvider({
95115
config,
@@ -108,6 +128,7 @@ describe('Members - config', function () {
108128
it('Uses direct keys when stripeDirect is false, but the connect keys do not exist', function () {
109129
const config = createConfigMock({stripeDirectValue: false});
110130
const settingsCache = createSettingsMock({setDirect: true, setConnect: false});
131+
const urlUtils = createUrlUtilsMock();
111132

112133
const membersConfig = new MembersConfigProvider({
113134
config,
@@ -122,4 +143,24 @@ describe('Members - config', function () {
122143
should.equal(paymentConfig.publicKey, 'direct_publishable');
123144
should.equal(paymentConfig.secretKey, 'direct_secret');
124145
});
146+
147+
it('Includes the subdirectory in the webhookHandlerUrl', function () {
148+
const config = createConfigMock({stripeDirectValue: false});
149+
const settingsCache = createSettingsMock({setDirect: true, setConnect: false});
150+
const urlUtils = createUrlUtilsMock({
151+
url: 'http://site.com/subdir'
152+
});
153+
154+
const membersConfig = new MembersConfigProvider({
155+
config,
156+
settingsCache,
157+
urlUtils,
158+
ghostVersion: {original: 'v7357'},
159+
logging: console
160+
});
161+
162+
const paymentConfig = membersConfig.getStripePaymentConfig();
163+
164+
should.equal(paymentConfig.webhookHandlerUrl, 'http://site.com/subdir/members/webhooks/stripe/');
165+
});
125166
});

0 commit comments

Comments
 (0)