mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
Updated setComplimentary to work with new system
closes https://github.com/TryGhost/Team/issues/650 Despite the fact we're getting rid of the concept of Complimentary, we must maintain backwards compatibility for the `comped` flag in the Admin API & the importer. This flag is handled via the `setComplimentary` method, which has been updated to work with the new system.
This commit is contained in:
parent
cdd52917fd
commit
a3f7f3d1a0
1 changed files with 77 additions and 47 deletions
|
@ -11,7 +11,6 @@ module.exports = class MemberRepository {
|
||||||
* @param {any} deps.StripeCustomerSubscription
|
* @param {any} deps.StripeCustomerSubscription
|
||||||
* @param {any} deps.productRepository
|
* @param {any} deps.productRepository
|
||||||
* @param {import('../../services/stripe-api')} deps.stripeAPIService
|
* @param {import('../../services/stripe-api')} deps.stripeAPIService
|
||||||
* @param {import('../../services/stripe-plans')} deps.stripePlansService
|
|
||||||
* @param {any} deps.logger
|
* @param {any} deps.logger
|
||||||
*/
|
*/
|
||||||
constructor({
|
constructor({
|
||||||
|
@ -23,7 +22,6 @@ module.exports = class MemberRepository {
|
||||||
StripeCustomer,
|
StripeCustomer,
|
||||||
StripeCustomerSubscription,
|
StripeCustomerSubscription,
|
||||||
stripeAPIService,
|
stripeAPIService,
|
||||||
stripePlansService,
|
|
||||||
productRepository,
|
productRepository,
|
||||||
logger
|
logger
|
||||||
}) {
|
}) {
|
||||||
|
@ -35,7 +33,6 @@ module.exports = class MemberRepository {
|
||||||
this._StripeCustomer = StripeCustomer;
|
this._StripeCustomer = StripeCustomer;
|
||||||
this._StripeCustomerSubscription = StripeCustomerSubscription;
|
this._StripeCustomerSubscription = StripeCustomerSubscription;
|
||||||
this._stripeAPIService = stripeAPIService;
|
this._stripeAPIService = stripeAPIService;
|
||||||
this._stripePlansService = stripePlansService;
|
|
||||||
this._productRepository = productRepository;
|
this._productRepository = productRepository;
|
||||||
this._logging = logger;
|
this._logging = logger;
|
||||||
}
|
}
|
||||||
|
@ -613,40 +610,64 @@ module.exports = class MemberRepository {
|
||||||
return this.isActiveSubscriptionStatus(subscription.get('status'));
|
return this.isActiveSubscriptionStatus(subscription.get('status'));
|
||||||
});
|
});
|
||||||
|
|
||||||
// NOTE: Because we allow for multiple Complimentary plans, need to take into account currently availalbe
|
const productPage = await this._productRepository.list({limit: 1, withRelated: ['stripePrices'], ...options});
|
||||||
// plan currencies so that we don't end up giving a member complimentary subscription in wrong currency.
|
|
||||||
// Giving member a subscription in different currency would prevent them from resubscribing with a regular
|
const defaultProduct = productPage && productPage.data && productPage.data[0] && productPage.data[0].toJSON();
|
||||||
// plan if Complimentary is cancelled (ref. https://stripe.com/docs/billing/customer#currency)
|
|
||||||
let complimentaryCurrency = this._stripePlansService.getPlans().find(plan => plan.interval === 'month').currency.toLowerCase();
|
if (!defaultProduct) {
|
||||||
|
throw new Error('Could not find default product');
|
||||||
|
}
|
||||||
|
|
||||||
|
const zeroValuePrices = defaultProduct.stripePrices.filter((price) => {
|
||||||
|
return price.amount === 0;
|
||||||
|
});
|
||||||
|
|
||||||
if (activeSubscriptions.length) {
|
if (activeSubscriptions.length) {
|
||||||
complimentaryCurrency = activeSubscriptions[0].get('plan_currency').toLowerCase();
|
for (const subscription of activeSubscriptions) {
|
||||||
|
const price = await subscription.related('stripePrice').fetch(options);
|
||||||
|
|
||||||
|
let zeroValuePrice = zeroValuePrices.find((p) => {
|
||||||
|
return p.currency.toLowerCase() === price.get('currency').toLowerCase();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!zeroValuePrice) {
|
||||||
|
const product = (await this._productRepository.update({
|
||||||
|
id: defaultProduct.id,
|
||||||
|
name: defaultProduct.name,
|
||||||
|
description: defaultProduct.description,
|
||||||
|
stripe_prices: [{
|
||||||
|
nickname: 'Complimentary',
|
||||||
|
currency: price.get('currency'),
|
||||||
|
type: 'recurring',
|
||||||
|
interval: 'year',
|
||||||
|
amount: 0
|
||||||
|
}]
|
||||||
|
}, options)).toJSON();
|
||||||
|
zeroValuePrice = product.stripePrices.find((price) => {
|
||||||
|
return price.currency.toLowerCase() === subscription.get('currency').toLowerCase() && price.amount === 0;
|
||||||
|
});
|
||||||
|
zeroValuePrices.push(zeroValuePrice);
|
||||||
}
|
}
|
||||||
|
|
||||||
const complimentaryPlan = this._stripePlansService.getComplimentaryPlan(complimentaryCurrency);
|
const stripeSubscription = await this._stripeAPIService.getSubscription(
|
||||||
|
subscription.get('subscription_id')
|
||||||
|
);
|
||||||
|
|
||||||
if (!complimentaryPlan) {
|
const subscriptionItem = stripeSubscription.items.data[0];
|
||||||
throw new Error('Could not find Complimentary plan');
|
|
||||||
|
const updatedSubscription = await this._stripeAPIService.updateSubscriptionItemPrice(
|
||||||
|
stripeSubscription.id,
|
||||||
|
subscriptionItem.id,
|
||||||
|
zeroValuePrice.stripe_price_id
|
||||||
|
);
|
||||||
|
|
||||||
|
await this.linkSubscription({
|
||||||
|
id: member.id,
|
||||||
|
subscription: updatedSubscription
|
||||||
|
}, options);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
let stripeCustomer;
|
const stripeCustomer = await this._stripeAPIService.createCustomer({
|
||||||
|
|
||||||
await member.related('stripeCustomers').fetch(options);
|
|
||||||
|
|
||||||
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) {
|
|
||||||
console.log('Ignoring error for fetching customer for checkout');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!stripeCustomer) {
|
|
||||||
stripeCustomer = await this._stripeAPIService.createCustomer({
|
|
||||||
email: member.get('email')
|
email: member.get('email')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -656,28 +677,37 @@ module.exports = class MemberRepository {
|
||||||
email: stripeCustomer.email,
|
email: stripeCustomer.email,
|
||||||
name: stripeCustomer.name
|
name: stripeCustomer.name
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
|
let zeroValuePrice = zeroValuePrices[0];
|
||||||
|
|
||||||
|
if (!zeroValuePrice) {
|
||||||
|
const product = (await this._productRepository.update({
|
||||||
|
id: defaultProduct.id,
|
||||||
|
name: defaultProduct.name,
|
||||||
|
description: defaultProduct.description,
|
||||||
|
stripe_prices: [{
|
||||||
|
nickname: 'Complimentary',
|
||||||
|
currency: 'USD',
|
||||||
|
type: 'recurring',
|
||||||
|
interval: 'year',
|
||||||
|
amount: 0
|
||||||
|
}]
|
||||||
|
}, options)).toJSON();
|
||||||
|
zeroValuePrice = product.stripePrices.find((price) => {
|
||||||
|
return price.currency.toLowerCase() === 'usd' && price.amount === 0;
|
||||||
|
});
|
||||||
|
zeroValuePrices.push(zeroValuePrice);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!activeSubscriptions.length) {
|
const subscription = await this._stripeAPIService.createSubscription(
|
||||||
const subscription = await this._stripeAPIService.createSubscription(stripeCustomer.id, complimentaryPlan.id);
|
stripeCustomer.id,
|
||||||
|
zeroValuePrice.stripe_price_id
|
||||||
|
);
|
||||||
|
|
||||||
await this.linkSubscription({
|
await this.linkSubscription({
|
||||||
id: member.id,
|
id: member.id,
|
||||||
subscription
|
subscription
|
||||||
}, options);
|
}, options);
|
||||||
} else {
|
|
||||||
// NOTE: we should only ever have 1 active subscription, but just in case there is more update is done on all of them
|
|
||||||
for (const subscription of activeSubscriptions) {
|
|
||||||
const updatedSubscription = await this._stripeAPIService.changeSubscriptionPlan(
|
|
||||||
subscription.get('subscription_id'),
|
|
||||||
complimentaryPlan.id
|
|
||||||
);
|
|
||||||
|
|
||||||
await this.linkSubscription({
|
|
||||||
id: member.id,
|
|
||||||
subscription: updatedSubscription
|
|
||||||
}, options);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue