🐛 Fixed checkout sessions when using Offers
closes https://github.com/TryGhost/Team/issues/2195 The issue here is two-fold, and specific to using Offers so was not caught by any automated tests. First, we were incorrectly comparing the tier.id to the offer.tier.id - this is because the Tier objects id property is an instance of ObjectID rather than a string. Secondly we were passing through the cadence parameter from the request body, but when using Offers this is not including in the request, so we must pull the data off of the Offer object instead and pass that to the payments service.
This commit is contained in:
parent
3c71d07dfb
commit
1f300fb781
@ -1,5 +1,21 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Create Stripe Checkout Session Can create a checkout session when using offers 1: [body] 1`] = `
|
||||
Object {
|
||||
"url": "https://site.com",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Create Stripe Checkout Session Can create a checkout session when using offers 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-type": "application/json",
|
||||
"vary": "Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Create Stripe Checkout Session Does allow to create a checkout session if the customerEmail is not associated with a paid member 1: [body] 1`] = `
|
||||
Object {
|
||||
"url": "https://site.com",
|
||||
|
@ -55,6 +55,78 @@ describe('Create Stripe Checkout Session', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('Can create a checkout session when using offers', async function () {
|
||||
const {body: {tiers}} = await adminAgent.get('/tiers/?include=monthly_price&yearly_price');
|
||||
const paidTier = tiers.find(tier => tier.type === 'paid');
|
||||
const {body: {offers: [offer]}} = await adminAgent.post('/offers/').body({
|
||||
offers: [{
|
||||
name: 'Test Offer',
|
||||
code: 'test-offer',
|
||||
cadence: 'month',
|
||||
status: 'active',
|
||||
currency: 'usd',
|
||||
type: 'percent',
|
||||
amount: 20,
|
||||
duration: 'once',
|
||||
duration_in_months: null,
|
||||
display_title: 'Test Offer',
|
||||
display_description: null,
|
||||
tier: {
|
||||
id: paidTier.id
|
||||
}
|
||||
}]
|
||||
});
|
||||
|
||||
nock('https://api.stripe.com')
|
||||
.persist()
|
||||
.get(/v1\/.*/)
|
||||
.reply((uri, body) => {
|
||||
const [match, resource, id] = uri.match(/\/v1\/(\w+)\/(.+)\/?/) || [null];
|
||||
if (match) {
|
||||
if (resource === 'products') {
|
||||
return [200, {
|
||||
id: id,
|
||||
active: true
|
||||
}];
|
||||
}
|
||||
if (resource === 'prices') {
|
||||
return [200, {
|
||||
id: id,
|
||||
active: true,
|
||||
currency: 'usd',
|
||||
unit_amount: 500
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
return [500];
|
||||
});
|
||||
|
||||
nock('https://api.stripe.com')
|
||||
.persist()
|
||||
.post(/v1\/.*/)
|
||||
.reply((uri, body) => {
|
||||
if (uri === '/v1/checkout/sessions') {
|
||||
return [200, {id: 'cs_123', url: 'https://site.com'}];
|
||||
}
|
||||
|
||||
if (uri === '/v1/coupons') {
|
||||
return [200, {id: 'coupon_123', url: 'https://site.com'}];
|
||||
}
|
||||
|
||||
return [500];
|
||||
});
|
||||
|
||||
await membersAgent.post('/api/create-stripe-checkout-session/')
|
||||
.body({
|
||||
customerEmail: 'free@test.com',
|
||||
offerId: offer.id
|
||||
})
|
||||
.expectStatus(200)
|
||||
.matchBodySnapshot()
|
||||
.matchHeaderSnapshot();
|
||||
});
|
||||
|
||||
it('Does allow to create a checkout session if the customerEmail is not associated with a paid member', async function () {
|
||||
const {body: {tiers}} = await adminAgent.get('/tiers/?include=monthly_price&yearly_price');
|
||||
|
||||
|
@ -142,7 +142,7 @@ module.exports = class RouterController {
|
||||
async createCheckoutSession(req, res) {
|
||||
let ghostPriceId = req.body.priceId;
|
||||
const tierId = req.body.tierId;
|
||||
const cadence = req.body.cadence;
|
||||
let cadence = req.body.cadence;
|
||||
const identity = req.body.identity;
|
||||
const offerId = req.body.offerId;
|
||||
const metadata = req.body.metadata ?? {};
|
||||
@ -185,6 +185,7 @@ module.exports = class RouterController {
|
||||
if (offerId) {
|
||||
offer = await this._offersAPI.getOffer({id: offerId});
|
||||
tier = await this._tiersService.api.read(offer.tier.id);
|
||||
cadence = offer.cadence;
|
||||
} else {
|
||||
offer = null;
|
||||
tier = await this._tiersService.api.read(tierId);
|
||||
|
@ -67,7 +67,7 @@ class PaymentsService {
|
||||
let coupon = null;
|
||||
let trialDays = null;
|
||||
if (offer) {
|
||||
if (offer.tier.id !== tier.id) {
|
||||
if (!tier.id.equals(offer.tier.id)) {
|
||||
throw new BadRequestError({
|
||||
message: 'This Offer is not valid for the Tier'
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user