mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-24 19:33:02 +03:00
Wired up the payment service to create stripe checkout sessions
refs https://github.com/TryGhost/Team/issues/2078
This commit is contained in:
parent
31610f9b94
commit
25d8d694a0
@ -13,6 +13,7 @@ const SingleUseTokenProvider = require('./SingleUseTokenProvider');
|
||||
const urlUtils = require('../../../shared/url-utils');
|
||||
const labsService = require('../../../shared/labs');
|
||||
const offersService = require('../offers');
|
||||
const tiersService = require('../tiers');
|
||||
const newslettersService = require('../newsletters');
|
||||
const memberAttributionService = require('../member-attribution');
|
||||
|
||||
@ -198,6 +199,7 @@ function createApiInstance(config) {
|
||||
MemberFeedback: models.MemberFeedback
|
||||
},
|
||||
stripeAPIService: stripeService.api,
|
||||
tiersService: tiersService,
|
||||
offersAPI: offersService.api,
|
||||
labsService: labsService,
|
||||
newslettersService: newslettersService,
|
||||
|
@ -744,14 +744,14 @@ Object {
|
||||
"id": "sub_123",
|
||||
"offer": null,
|
||||
"plan": Object {
|
||||
"amount": 5000,
|
||||
"amount": 500,
|
||||
"currency": "USD",
|
||||
"id": "173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730b12",
|
||||
"interval": "month",
|
||||
"nickname": "month",
|
||||
},
|
||||
"price": Object {
|
||||
"amount": 5000,
|
||||
"amount": 500,
|
||||
"currency": "USD",
|
||||
"id": "173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730b12",
|
||||
"interval": "month",
|
||||
@ -782,7 +782,7 @@ exports[`Members API Can add a subscription 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "http://127.0.0.1:2369",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "2510",
|
||||
"content-length": "2508",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Version, Origin, Accept-Encoding",
|
||||
@ -842,14 +842,14 @@ Object {
|
||||
"id": "sub_123",
|
||||
"offer": null,
|
||||
"plan": Object {
|
||||
"amount": 5000,
|
||||
"amount": 500,
|
||||
"currency": "USD",
|
||||
"id": "173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730b12",
|
||||
"interval": "month",
|
||||
"nickname": "month",
|
||||
},
|
||||
"price": Object {
|
||||
"amount": 5000,
|
||||
"amount": 500,
|
||||
"currency": "USD",
|
||||
"id": "173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730b12",
|
||||
"interval": "month",
|
||||
@ -880,7 +880,7 @@ exports[`Members API Can add a subscription 4: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "http://127.0.0.1:2369",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "2510",
|
||||
"content-length": "2508",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Version, Origin, Accept-Encoding",
|
||||
@ -2125,14 +2125,14 @@ Object {
|
||||
"id": "sub_K1cBgJt6sCMu5n",
|
||||
"offer": null,
|
||||
"plan": Object {
|
||||
"amount": 5000,
|
||||
"amount": 500,
|
||||
"currency": "USD",
|
||||
"id": "173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730b12",
|
||||
"interval": "month",
|
||||
"nickname": "month",
|
||||
},
|
||||
"price": Object {
|
||||
"amount": 5000,
|
||||
"amount": 500,
|
||||
"currency": "USD",
|
||||
"id": "173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730b12",
|
||||
"interval": "month",
|
||||
@ -2163,7 +2163,7 @@ exports[`Members API Can edit a subscription 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "http://127.0.0.1:2369",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "2377",
|
||||
"content-length": "2375",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Version, Origin, Accept-Encoding",
|
||||
@ -2223,14 +2223,14 @@ Object {
|
||||
"id": "sub_K1cBgJt6sCMu5n",
|
||||
"offer": null,
|
||||
"plan": Object {
|
||||
"amount": 5000,
|
||||
"amount": 500,
|
||||
"currency": "USD",
|
||||
"id": "173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730b12",
|
||||
"interval": "month",
|
||||
"nickname": "month",
|
||||
},
|
||||
"price": Object {
|
||||
"amount": 5000,
|
||||
"amount": 500,
|
||||
"currency": "USD",
|
||||
"id": "173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730b12",
|
||||
"interval": "month",
|
||||
@ -2261,7 +2261,7 @@ exports[`Members API Can edit a subscription 4: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "http://127.0.0.1:2369",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "2379",
|
||||
"content-length": "2377",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Version, Origin, Accept-Encoding",
|
||||
|
@ -2,8 +2,7 @@
|
||||
|
||||
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 {
|
||||
"publicKey": "pk_test_for_stripe",
|
||||
"sessionId": "cs_123",
|
||||
"url": "https://site.com",
|
||||
}
|
||||
`;
|
||||
|
||||
@ -100,8 +99,7 @@ Object {
|
||||
|
||||
exports[`Create Stripe Checkout Session Member attribution Does pass post attribution source to session metadata 1: [body] 1`] = `
|
||||
Object {
|
||||
"publicKey": "pk_test_for_stripe",
|
||||
"sessionId": "cs_123",
|
||||
"url": "https://site.com",
|
||||
}
|
||||
`;
|
||||
|
||||
@ -117,8 +115,7 @@ Object {
|
||||
|
||||
exports[`Create Stripe Checkout Session Member attribution Does pass url attribution source to session metadata 1: [body] 1`] = `
|
||||
Object {
|
||||
"publicKey": "pk_test_for_stripe",
|
||||
"sessionId": "cs_123",
|
||||
"url": "https://site.com",
|
||||
}
|
||||
`;
|
||||
|
||||
@ -134,8 +131,7 @@ Object {
|
||||
|
||||
exports[`Create Stripe Checkout Session Member attribution Ignores attribution_* values in metadata 1: [body] 1`] = `
|
||||
Object {
|
||||
"publicKey": "pk_test_for_stripe",
|
||||
"sessionId": "cs_123",
|
||||
"url": "https://site.com",
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -60,12 +60,37 @@ describe('Create Stripe Checkout Session', function () {
|
||||
|
||||
const paidTier = tiers.find(tier => tier.type === 'paid');
|
||||
|
||||
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'}];
|
||||
return [200, {id: 'cs_123', url: 'https://site.com'}];
|
||||
}
|
||||
|
||||
return [500];
|
||||
@ -92,6 +117,31 @@ describe('Create Stripe Checkout Session', function () {
|
||||
|
||||
const paidTier = tiers.find(tier => tier.type === 'paid');
|
||||
|
||||
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];
|
||||
});
|
||||
|
||||
const scope = nock('https://api.stripe.com')
|
||||
.persist()
|
||||
.post(/v1\/.*/)
|
||||
@ -101,10 +151,11 @@ describe('Create Stripe Checkout Session', function () {
|
||||
should(parsed.get('metadata[attribution_url]')).eql('/test');
|
||||
should(parsed.get('metadata[attribution_type]')).eql('url');
|
||||
should(parsed.get('metadata[attribution_id]')).be.null();
|
||||
return [200, {id: 'cs_123'}];
|
||||
|
||||
return [200, {id: 'cs_123', url: 'https://site.com'}];
|
||||
}
|
||||
|
||||
throw new Error('Should not get called');
|
||||
return [500];
|
||||
});
|
||||
|
||||
await membersAgent.post('/api/create-stripe-checkout-session/')
|
||||
@ -136,6 +187,31 @@ describe('Create Stripe Checkout Session', function () {
|
||||
|
||||
const paidTier = tiers.find(tier => tier.type === 'paid');
|
||||
|
||||
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];
|
||||
});
|
||||
|
||||
const scope = nock('https://api.stripe.com')
|
||||
.persist()
|
||||
.post(/v1\/.*/)
|
||||
@ -145,10 +221,11 @@ describe('Create Stripe Checkout Session', function () {
|
||||
should(parsed.get('metadata[attribution_url]')).eql(url);
|
||||
should(parsed.get('metadata[attribution_type]')).eql('post');
|
||||
should(parsed.get('metadata[attribution_id]')).eql(post.id);
|
||||
return [200, {id: 'cs_123'}];
|
||||
|
||||
return [200, {id: 'cs_123', url: 'https://site.com'}];
|
||||
}
|
||||
|
||||
throw new Error('Should not get called');
|
||||
return [500];
|
||||
});
|
||||
|
||||
await membersAgent.post('/api/create-stripe-checkout-session/')
|
||||
@ -177,6 +254,31 @@ describe('Create Stripe Checkout Session', function () {
|
||||
|
||||
const paidTier = tiers.find(tier => tier.type === 'paid');
|
||||
|
||||
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];
|
||||
});
|
||||
|
||||
const scope = nock('https://api.stripe.com')
|
||||
.persist()
|
||||
.post(/v1\/.*/)
|
||||
@ -186,10 +288,11 @@ describe('Create Stripe Checkout Session', function () {
|
||||
should(parsed.get('metadata[attribution_url]')).be.null();
|
||||
should(parsed.get('metadata[attribution_type]')).be.null();
|
||||
should(parsed.get('metadata[attribution_id]')).be.null();
|
||||
return [200, {id: 'cs_123'}];
|
||||
|
||||
return [200, {id: 'cs_123', url: 'https://site.com'}];
|
||||
}
|
||||
|
||||
throw new Error('Should not get called');
|
||||
return [500];
|
||||
});
|
||||
|
||||
await membersAgent.post('/api/create-stripe-checkout-session/')
|
||||
|
@ -588,7 +588,7 @@ DataGenerator.Content = {
|
||||
active: true,
|
||||
nickname: 'Monthly',
|
||||
currency: 'USD',
|
||||
amount: 5000,
|
||||
amount: 500,
|
||||
type: 'recurring',
|
||||
interval: 'month'
|
||||
},
|
||||
@ -624,6 +624,17 @@ DataGenerator.Content = {
|
||||
amount: 15000,
|
||||
type: 'recurring',
|
||||
interval: 'year'
|
||||
},
|
||||
{
|
||||
id: ObjectId().toHexString(),
|
||||
stripe_price_id: '173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730b13',
|
||||
stripe_product_id: '109c85c734fb9992e7bc30a26af66c22f5c94d8dc62e0a33cb797be902c06b2d',
|
||||
active: true,
|
||||
nickname: 'Yearly',
|
||||
currency: 'USD',
|
||||
amount: 5000,
|
||||
type: 'recurring',
|
||||
interval: 'year'
|
||||
}
|
||||
],
|
||||
stripe_products: [
|
||||
@ -1674,7 +1685,8 @@ DataGenerator.forKnex = (function () {
|
||||
createBasic(DataGenerator.Content.stripe_prices[0]),
|
||||
createBasic(DataGenerator.Content.stripe_prices[1]),
|
||||
createBasic(DataGenerator.Content.stripe_prices[2]),
|
||||
createBasic(DataGenerator.Content.stripe_prices[3])
|
||||
createBasic(DataGenerator.Content.stripe_prices[3]),
|
||||
createBasic(DataGenerator.Content.stripe_prices[4])
|
||||
];
|
||||
|
||||
const stripe_customer_subscriptions = [
|
||||
|
@ -61,6 +61,7 @@ module.exports = function MembersAPI({
|
||||
Comment,
|
||||
MemberFeedback
|
||||
},
|
||||
tiersService,
|
||||
stripeAPIService,
|
||||
offersAPI,
|
||||
labsService,
|
||||
@ -169,7 +170,7 @@ module.exports = function MembersAPI({
|
||||
const routerController = new RouterController({
|
||||
offersAPI,
|
||||
paymentsService,
|
||||
productRepository,
|
||||
tiersService,
|
||||
memberRepository,
|
||||
StripePrice,
|
||||
allowSelfSignup,
|
||||
|
@ -1,7 +1,7 @@
|
||||
const tpl = require('@tryghost/tpl');
|
||||
const logging = require('@tryghost/logging');
|
||||
const _ = require('lodash');
|
||||
const {BadRequestError, NoPermissionError, NotFoundError, UnauthorizedError} = require('@tryghost/errors');
|
||||
const {BadRequestError, NoPermissionError, UnauthorizedError} = require('@tryghost/errors');
|
||||
const errors = require('@tryghost/errors');
|
||||
|
||||
const messages = {
|
||||
@ -24,7 +24,6 @@ module.exports = class RouterController {
|
||||
* @param {object} deps
|
||||
* @param {any} deps.offersAPI
|
||||
* @param {any} deps.paymentsService
|
||||
* @param {any} deps.productRepository
|
||||
* @param {any} deps.memberRepository
|
||||
* @param {any} deps.StripePrice
|
||||
* @param {() => boolean} deps.allowSelfSignup
|
||||
@ -38,7 +37,7 @@ module.exports = class RouterController {
|
||||
constructor({
|
||||
offersAPI,
|
||||
paymentsService,
|
||||
productRepository,
|
||||
tiersService,
|
||||
memberRepository,
|
||||
StripePrice,
|
||||
allowSelfSignup,
|
||||
@ -51,7 +50,7 @@ module.exports = class RouterController {
|
||||
}) {
|
||||
this._offersAPI = offersAPI;
|
||||
this._paymentsService = paymentsService;
|
||||
this._productRepository = productRepository;
|
||||
this._tiersService = tiersService;
|
||||
this._memberRepository = memberRepository;
|
||||
this._StripePrice = StripePrice;
|
||||
this._allowSelfSignup = allowSelfSignup;
|
||||
@ -178,32 +177,45 @@ module.exports = class RouterController {
|
||||
});
|
||||
}
|
||||
|
||||
let couponId = null;
|
||||
let trialDays;
|
||||
let tier;
|
||||
let offer;
|
||||
let member;
|
||||
let options = {};
|
||||
|
||||
if (offerId) {
|
||||
const offer = await this._offersAPI.getOffer({id: offerId});
|
||||
const tier = (await this._productRepository.get(offer.tier)).toJSON();
|
||||
offer = await this._offersAPI.getOffer({id: offerId});
|
||||
tier = await this._tiersService.api.read(offer.tier.id);
|
||||
} else {
|
||||
offer = null;
|
||||
tier = await this._tiersService.api.read(tierId);
|
||||
}
|
||||
|
||||
if (offer.status === 'archived') {
|
||||
throw new NoPermissionError({
|
||||
message: tpl(messages.offerArchived)
|
||||
});
|
||||
}
|
||||
if (tier.status === 'archived') {
|
||||
throw new NoPermissionError({
|
||||
message: tpl(messages.tierArchived)
|
||||
});
|
||||
}
|
||||
|
||||
if (offer.cadence === 'month') {
|
||||
ghostPriceId = tier.monthly_price_id;
|
||||
} else {
|
||||
ghostPriceId = tier.yearly_price_id;
|
||||
if (identity) {
|
||||
try {
|
||||
const claims = await this._tokenService.decodeToken(identity);
|
||||
const email = claims && claims.sub;
|
||||
if (email) {
|
||||
member = await this._memberRepository.get({
|
||||
email
|
||||
}, {
|
||||
withRelated: ['stripeCustomers', 'products']
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
throw new UnauthorizedError({err});
|
||||
}
|
||||
// Free trial offers don't have a stripe coupon
|
||||
if (offer.type === 'trial') {
|
||||
trialDays = offer.amount;
|
||||
} else {
|
||||
const coupon = await this._paymentsService.getCouponForOffer(offerId);
|
||||
couponId = coupon.id;
|
||||
}
|
||||
|
||||
metadata.offer = offer.id;
|
||||
} else if (req.body.customerEmail) {
|
||||
member = await this._memberRepository.get({
|
||||
email: req.body.customerEmail
|
||||
}, {
|
||||
withRelated: ['stripeCustomers', 'products']
|
||||
});
|
||||
}
|
||||
|
||||
// Don't allow to set the source manually
|
||||
@ -245,106 +257,25 @@ module.exports = class RouterController {
|
||||
}
|
||||
}
|
||||
|
||||
if (!ghostPriceId) {
|
||||
const tier = await this._productRepository.get({id: tierId});
|
||||
if (tier) {
|
||||
if (cadence === 'month') {
|
||||
ghostPriceId = tier.get('monthly_price_id');
|
||||
} else {
|
||||
ghostPriceId = tier.get('yearly_price_id');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const price = await this._StripePrice.findOne({
|
||||
id: ghostPriceId
|
||||
});
|
||||
|
||||
if (!price) {
|
||||
throw new NotFoundError({
|
||||
message: tpl(messages.notFound)
|
||||
});
|
||||
}
|
||||
|
||||
const priceId = price.get('stripe_price_id');
|
||||
|
||||
const product = await this._productRepository.get({stripe_price_id: priceId});
|
||||
|
||||
if (this.labsService.isSet('freeTrial') && !trialDays) {
|
||||
trialDays = product.get('trial_days');
|
||||
}
|
||||
|
||||
if (product.get('active') !== true) {
|
||||
throw new NoPermissionError({
|
||||
message: tpl(messages.tierArchived)
|
||||
});
|
||||
}
|
||||
|
||||
let member = null;
|
||||
if (identity) {
|
||||
try {
|
||||
const claims = await this._tokenService.decodeToken(identity);
|
||||
const email = claims && claims.sub;
|
||||
if (email) {
|
||||
member = await this._memberRepository.get({email}, {withRelated: ['stripeCustomers', 'products']});
|
||||
}
|
||||
} catch (err) {
|
||||
throw new UnauthorizedError({err});
|
||||
}
|
||||
} else if (req.body.customerEmail) {
|
||||
member = await this._memberRepository.get({email: req.body.customerEmail}, {withRelated: ['stripeCustomers', 'products']});
|
||||
}
|
||||
|
||||
let successUrl = req.body.successUrl;
|
||||
let cancelUrl = req.body.cancelUrl;
|
||||
options.successUrl = req.body.successUrl;
|
||||
options.cancelUrl = req.body.cancelUrl;
|
||||
|
||||
if (!member && req.body.customerEmail && !req.body.successUrl) {
|
||||
const memberExistsForCustomer = await this._memberRepository.get({email: req.body.customerEmail});
|
||||
if (!memberExistsForCustomer) {
|
||||
successUrl = await this._magicLinkService.getMagicLink({
|
||||
tokenData: {
|
||||
email: req.body.customerEmail,
|
||||
attribution: {
|
||||
id: metadata.attribution_id ?? null,
|
||||
type: metadata.attribution_type ?? null,
|
||||
url: metadata.attribution_url ?? null
|
||||
}
|
||||
},
|
||||
type: 'signup'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!member) {
|
||||
const customer = null;
|
||||
const session = await this._stripeAPIService.createCheckoutSession(priceId, customer, {
|
||||
coupon: couponId,
|
||||
successUrl,
|
||||
cancelUrl,
|
||||
trialDays,
|
||||
customerEmail: req.body.customerEmail,
|
||||
metadata: metadata
|
||||
options.successUrl = await this._magicLinkService.getMagicLink({
|
||||
tokenData: {
|
||||
email: req.body.customerEmail,
|
||||
attribution: {
|
||||
id: metadata.attribution_id ?? null,
|
||||
type: metadata.attribution_type ?? null,
|
||||
url: metadata.attribution_url ?? null
|
||||
}
|
||||
},
|
||||
type: 'signup'
|
||||
});
|
||||
const publicKey = this._stripeAPIService.getPublicKey();
|
||||
|
||||
const sessionInfo = {
|
||||
publicKey,
|
||||
sessionId: session.id
|
||||
};
|
||||
|
||||
res.writeHead(200, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
|
||||
return res.end(JSON.stringify(sessionInfo));
|
||||
}
|
||||
|
||||
let restrictCheckout = false;
|
||||
if (!this.labsService.isSet('compExpiring')) {
|
||||
restrictCheckout = member.related('products').length !== 0;
|
||||
} else {
|
||||
restrictCheckout = member.get('status') === 'paid';
|
||||
}
|
||||
const restrictCheckout = member?.get('status') === 'paid';
|
||||
|
||||
if (restrictCheckout) {
|
||||
if (!identity && req.body.customerEmail) {
|
||||
try {
|
||||
@ -359,44 +290,20 @@ module.exports = class RouterController {
|
||||
});
|
||||
}
|
||||
|
||||
let stripeCustomer;
|
||||
|
||||
for (const customer of member.related('stripeCustomers').models) {
|
||||
try {
|
||||
const fetchedCustomer = await this._stripeAPIService.getCustomer(customer.get('customer_id'));
|
||||
if (!fetchedCustomer.deleted) {
|
||||
stripeCustomer = fetchedCustomer;
|
||||
break;
|
||||
}
|
||||
} catch (err) {
|
||||
logging.info('Ignoring error for fetching customer for checkout');
|
||||
}
|
||||
}
|
||||
|
||||
if (!stripeCustomer) {
|
||||
stripeCustomer = await this._stripeAPIService.createCustomer({email: member.get('email')});
|
||||
}
|
||||
|
||||
try {
|
||||
const session = await this._stripeAPIService.createCheckoutSession(priceId, stripeCustomer, {
|
||||
coupon: couponId,
|
||||
successUrl,
|
||||
cancelUrl,
|
||||
trialDays,
|
||||
metadata: metadata
|
||||
const paymentLink = await this._paymentsService.getPaymentLink({
|
||||
tier,
|
||||
cadence,
|
||||
offer,
|
||||
member,
|
||||
metadata,
|
||||
options
|
||||
});
|
||||
const publicKey = this._stripeAPIService.getPublicKey();
|
||||
|
||||
const sessionInfo = {
|
||||
publicKey,
|
||||
sessionId: session.id
|
||||
};
|
||||
|
||||
res.writeHead(200, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
|
||||
return res.end(JSON.stringify(sessionInfo));
|
||||
return res.end(JSON.stringify({url: paymentLink}));
|
||||
} catch (err) {
|
||||
throw new BadRequestError({
|
||||
err,
|
||||
@ -451,7 +358,7 @@ module.exports = class RouterController {
|
||||
tokenData.attribution = await this._memberAttributionService.getAttribution(req.body.urlHistory);
|
||||
|
||||
await this._sendEmailWithMagicLink({email, tokenData, requestedType: emailType, referrer: referer});
|
||||
|
||||
|
||||
res.writeHead(201);
|
||||
return res.end('Created.');
|
||||
}
|
||||
@ -464,7 +371,7 @@ module.exports = class RouterController {
|
||||
res.writeHead(201);
|
||||
return res.end('Created.');
|
||||
}
|
||||
|
||||
|
||||
throw new errors.BadRequestError({
|
||||
message: this._allowSelfSignup() ? tpl(messages.memberNotFoundSignUp) : tpl(messages.memberNotFound)
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user