mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-27 22:49:56 -05:00
Stored offer_id in subscriptions (#389)
refs https://github.com/TryGhost/Team/issues/1519 - Added offer repository dependency to member repository (offerAPI didn't work because it creates a new transaction that resulted in a deadlock during tests) - Store the offer id from the Stripe subscription metadata in the subscription (only if the discount is still active) - Also added the offer id to the metadata for a Stripe coupon, this will make adding and removing coupons a bit more foolproof - Prefer the usage of the offer metadata from a coupon if it is present - When no discount is applied to a subscription, it always sets the offer id to null, even when the metadata still contains the offer - The offer_id remains stored when a subscription is canceled/expired
This commit is contained in:
parent
db02d61e4b
commit
f74b00fea6
3 changed files with 30 additions and 6 deletions
|
@ -92,7 +92,8 @@ module.exports = function MembersAPI({
|
|||
MemberProductEvent,
|
||||
OfferRedemption,
|
||||
StripeCustomer,
|
||||
StripeCustomerSubscription
|
||||
StripeCustomerSubscription,
|
||||
offerRepository: offersAPI.repository
|
||||
});
|
||||
|
||||
const eventRepository = new EventRepository({
|
||||
|
|
|
@ -33,11 +33,13 @@ module.exports = class MemberRepository {
|
|||
* @param {any} deps.MemberProductEvent
|
||||
* @param {any} deps.StripeCustomer
|
||||
* @param {any} deps.StripeCustomerSubscription
|
||||
* @param {any} deps.productRepository
|
||||
* @param {any} deps.newslettersService
|
||||
* @param {any} deps.labsService
|
||||
* @param {any} deps.OfferRedemption
|
||||
* @param {import('../../services/stripe-api')} deps.stripeAPIService
|
||||
* @param {any} deps.labsService
|
||||
* @param {any} deps.productRepository
|
||||
* @param {any} deps.offerRepository
|
||||
* @param {ITokenService} deps.tokenService
|
||||
* @param {any} deps.newslettersService
|
||||
*/
|
||||
constructor({
|
||||
Member,
|
||||
|
@ -53,6 +55,7 @@ module.exports = class MemberRepository {
|
|||
stripeAPIService,
|
||||
labsService,
|
||||
productRepository,
|
||||
offerRepository,
|
||||
tokenService,
|
||||
newslettersService
|
||||
}) {
|
||||
|
@ -67,6 +70,7 @@ module.exports = class MemberRepository {
|
|||
this._StripeCustomerSubscription = StripeCustomerSubscription;
|
||||
this._stripeAPIService = stripeAPIService;
|
||||
this._productRepository = productRepository;
|
||||
this._offerRepository = offerRepository;
|
||||
this.tokenService = tokenService;
|
||||
this._newslettersService = newslettersService;
|
||||
this._labsService = labsService;
|
||||
|
@ -698,6 +702,17 @@ module.exports = class MemberRepository {
|
|||
logging.error(e);
|
||||
}
|
||||
|
||||
let offerId = subscription.discount && (subscription.discount.coupon.metadata.offer || subscription.metadata.offer) ? (subscription.discount.coupon.metadata.offer ? subscription.discount.coupon.metadata.offer : subscription.metadata.offer) : null;
|
||||
|
||||
if (offerId) {
|
||||
// Validate the offer id from the metadata
|
||||
const offer = await this._offerRepository.getById(offerId, {transacting: options.transacting});
|
||||
if (!offer) {
|
||||
logging.error(`Received an invalid offer id (${offerId}) in the metadata of a subscription - ${subscription.id}.`);
|
||||
offerId = null;
|
||||
}
|
||||
}
|
||||
|
||||
const subscriptionData = {
|
||||
customer_id: subscription.customer,
|
||||
subscription_id: subscription.id,
|
||||
|
@ -723,8 +738,12 @@ module.exports = class MemberRepository {
|
|||
status: subscription.status,
|
||||
canceled: subscription.cancel_at_period_end,
|
||||
discount: subscription.discount
|
||||
})
|
||||
}),
|
||||
// We try to use the offer_id that was stored in Stripe coupon and fallback to the one stored in the subscription
|
||||
// This allows us to catch the offer_id from discounts (created by Ghost) that were applied via the Stripe dashboard
|
||||
offer_id: offerId
|
||||
};
|
||||
|
||||
let eventData = {};
|
||||
if (model) {
|
||||
const updated = await this._StripeCustomerSubscription.edit(subscriptionData, {
|
||||
|
|
|
@ -48,7 +48,11 @@ class PaymentsService {
|
|||
/** @type {import('stripe').Stripe.CouponCreateParams} */
|
||||
const couponData = {
|
||||
name: offer.name,
|
||||
duration: offer.duration
|
||||
duration: offer.duration,
|
||||
// Note that the metadata is not present for older coupons
|
||||
metadata: {
|
||||
offer: offer.id
|
||||
}
|
||||
};
|
||||
|
||||
if (offer.duration === 'repeating') {
|
||||
|
|
Loading…
Add table
Reference in a new issue