mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-28 21:33:24 +03:00
🐛 Fixed broken redemption count for offers (#15954)
refs https://github.com/TryGhost/Team/issues/2369
- offer id was not getting attached to stripe checkout metadata, causing the checkout event to not store any offer information for a subscription. This got changed in a prev refactor [here](25d8d694a0 (diff-b7dfcd660902a2a20dff7da5e886d8e10234bda4ba78228255afc8d4a8e78cf6L206)
)
- cleans up offer id handling for checkout session event
This commit is contained in:
parent
55b0f564ba
commit
8bdad78377
@ -186,6 +186,9 @@ module.exports = class RouterController {
|
||||
offer = await this._offersAPI.getOffer({id: offerId});
|
||||
tier = await this._tiersService.api.read(offer.tier.id);
|
||||
cadence = offer.cadence;
|
||||
// Attach offer information to stripe metadata for free trial offers
|
||||
// free trial offers don't have associated stripe coupons
|
||||
metadata.offer = offer.id;
|
||||
} else {
|
||||
offer = null;
|
||||
tier = await this._tiersService.api.read(tierId);
|
||||
|
@ -1033,7 +1033,7 @@ module.exports = class MemberRepository {
|
||||
tierId: ghostProduct?.get('id'),
|
||||
memberId: member.id,
|
||||
subscriptionId: subscriptionModel.get('id'),
|
||||
offerId: data.offerId,
|
||||
offerId: offerId,
|
||||
attribution: data.attribution,
|
||||
batchId: options.batch_id
|
||||
});
|
||||
|
93
ghost/members-api/test/unit/lib/controllers/router.test.js
Normal file
93
ghost/members-api/test/unit/lib/controllers/router.test.js
Normal file
@ -0,0 +1,93 @@
|
||||
const sinon = require('sinon');
|
||||
const RouterController = require('../../../../lib/controllers/router');
|
||||
|
||||
describe('RouterController', function () {
|
||||
describe('createCheckoutSession', function (){
|
||||
let offersAPI;
|
||||
let paymentsService;
|
||||
let tiersService;
|
||||
let stripeAPIService;
|
||||
let labsService;
|
||||
let getPaymentLinkSpy;
|
||||
|
||||
beforeEach(async function () {
|
||||
getPaymentLinkSpy = sinon.spy();
|
||||
|
||||
tiersService = {
|
||||
api: {
|
||||
read: sinon.stub().resolves({
|
||||
id: 'tier_123'
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
paymentsService = {
|
||||
getPaymentLink: getPaymentLinkSpy
|
||||
};
|
||||
|
||||
offersAPI = {
|
||||
getOffer: sinon.stub().resolves({
|
||||
id: 'offer_123',
|
||||
tier: {
|
||||
id: 'tier_123'
|
||||
}
|
||||
}),
|
||||
findOne: sinon.stub().resolves({
|
||||
related: () => {
|
||||
return {
|
||||
query: sinon.stub().returns({
|
||||
fetchOne: sinon.stub().resolves({})
|
||||
}),
|
||||
toJSON: sinon.stub().returns([]),
|
||||
fetch: sinon.stub().resolves({
|
||||
toJSON: sinon.stub().returns({})
|
||||
})
|
||||
};
|
||||
},
|
||||
toJSON: sinon.stub().returns({})
|
||||
}),
|
||||
edit: sinon.stub().resolves({
|
||||
attributes: {},
|
||||
_previousAttributes: {}
|
||||
})
|
||||
};
|
||||
|
||||
stripeAPIService = {
|
||||
configured: true
|
||||
};
|
||||
labsService = {
|
||||
isSet: sinon.stub().returns(true)
|
||||
};
|
||||
});
|
||||
|
||||
it('passes offer metadata to payment link method', async function (){
|
||||
const routerController = new RouterController({
|
||||
tiersService,
|
||||
paymentsService,
|
||||
offersAPI,
|
||||
stripeAPIService,
|
||||
labsService
|
||||
});
|
||||
|
||||
await routerController.createCheckoutSession({
|
||||
body: {
|
||||
offerId: 'offer_123'
|
||||
}
|
||||
}, {
|
||||
writeHead: () => {},
|
||||
end: () => {}
|
||||
});
|
||||
|
||||
getPaymentLinkSpy.calledOnce.should.be.true();
|
||||
|
||||
// Payment link is called with the offer id in metadata
|
||||
getPaymentLinkSpy.calledWith(sinon.match({
|
||||
metadata: {offer: 'offer_123'}
|
||||
})).should.be.true();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sinon.restore();
|
||||
});
|
||||
});
|
||||
});
|
@ -141,6 +141,7 @@ describe('MemberRepository', function () {
|
||||
let MemberProductEvent;
|
||||
let stripeAPIService;
|
||||
let productRepository;
|
||||
let offerRepository;
|
||||
let labsService;
|
||||
let subscriptionData;
|
||||
|
||||
@ -221,6 +222,12 @@ describe('MemberRepository', function () {
|
||||
labsService = {
|
||||
isSet: sinon.stub().returns(true)
|
||||
};
|
||||
|
||||
offerRepository = {
|
||||
getById: sinon.stub().resolves({
|
||||
id: 'offer_123'
|
||||
})
|
||||
};
|
||||
});
|
||||
|
||||
it('dispatches paid subscription event', async function (){
|
||||
@ -250,6 +257,42 @@ describe('MemberRepository', function () {
|
||||
notifySpy.calledOnce.should.be.true();
|
||||
});
|
||||
|
||||
it('attaches offer information to subscription event', async function (){
|
||||
const repo = new MemberRepository({
|
||||
stripeAPIService,
|
||||
StripeCustomerSubscription,
|
||||
MemberPaidSubscriptionEvent,
|
||||
MemberProductEvent,
|
||||
productRepository,
|
||||
offerRepository,
|
||||
labsService,
|
||||
Member
|
||||
});
|
||||
|
||||
sinon.stub(repo, 'getSubscriptionByStripeID').resolves(null);
|
||||
|
||||
DomainEvents.subscribe(SubscriptionCreatedEvent, notifySpy);
|
||||
|
||||
await repo.linkSubscription({
|
||||
id: 'member_id_123',
|
||||
subscription: subscriptionData,
|
||||
offerId: 'offer_123'
|
||||
}, {
|
||||
transacting: {
|
||||
executionPromise: Promise.resolve()
|
||||
},
|
||||
context: {}
|
||||
});
|
||||
|
||||
notifySpy.calledOnce.should.be.true();
|
||||
notifySpy.calledWith(sinon.match((event) => {
|
||||
if (event.data.offerId === 'offer_123') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})).should.be.true();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sinon.restore();
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user