diff --git a/packages/stripe/src/hooks.ts b/packages/stripe/src/hooks.ts index 02a6f758d1..62796bf138 100644 --- a/packages/stripe/src/hooks.ts +++ b/packages/stripe/src/hooks.ts @@ -153,8 +153,8 @@ export async function onSubscriptionCreated( return; } - const subscriptionCreated = event.data.object as Stripe.Subscription; - const stripeCustomerId = subscriptionCreated.customer?.toString(); + const stripeSubscriptionCreated = event.data.object as Stripe.Subscription; + const stripeCustomerId = stripeSubscriptionCreated.customer?.toString(); if (!stripeCustomerId) { ctx.context.logger.warn( `Stripe webhook warning: customer.subscription.created event received without customer ID`, @@ -164,14 +164,19 @@ export async function onSubscriptionCreated( // Check if subscription already exists in database const { subscriptionId } = subscriptionMetadata.get( - subscriptionCreated.metadata, + stripeSubscriptionCreated.metadata, ); const existingSubscription = await ctx.context.adapter.findOne({ model: "subscription", where: subscriptionId ? [{ field: "id", value: subscriptionId }] - : [{ field: "stripeSubscriptionId", value: subscriptionCreated.id }], // Probably won't match since it's not set yet + : [ + { + field: "stripeSubscriptionId", + value: stripeSubscriptionCreated.id, + }, + ], // Probably won't match since it's not set yet }); if (existingSubscription) { ctx.context.logger.info( @@ -196,11 +201,11 @@ export async function onSubscriptionCreated( const resolved = await resolvePlanItem( options, - subscriptionCreated.items.data, + stripeSubscriptionCreated.items.data, ); if (!resolved) { ctx.context.logger.warn( - `Stripe webhook warning: Subscription ${subscriptionCreated.id} has no items matching a configured plan`, + `Stripe webhook warning: Subscription ${stripeSubscriptionCreated.id} has no items matching a configured plan`, ); return; } @@ -214,7 +219,7 @@ export async function onSubscriptionCreated( } const seats = resolveQuantity( - subscriptionCreated.items.data, + stripeSubscriptionCreated.items.data, subscriptionItem, plan.seatPriceId, ); @@ -222,10 +227,11 @@ export async function onSubscriptionCreated( const periodEnd = new Date(subscriptionItem.current_period_end * 1000); const trial = - subscriptionCreated.trial_start && subscriptionCreated.trial_end + stripeSubscriptionCreated.trial_start && + stripeSubscriptionCreated.trial_end ? { - trialStart: new Date(subscriptionCreated.trial_start * 1000), - trialEnd: new Date(subscriptionCreated.trial_end * 1000), + trialStart: new Date(stripeSubscriptionCreated.trial_start * 1000), + trialEnd: new Date(stripeSubscriptionCreated.trial_end * 1000), } : {}; @@ -237,8 +243,8 @@ export async function onSubscriptionCreated( ...(plan.limits ? { limits: plan.limits } : {}), referenceId, stripeCustomerId, - stripeSubscriptionId: subscriptionCreated.id, - status: subscriptionCreated.status, + stripeSubscriptionId: stripeSubscriptionCreated.id, + status: stripeSubscriptionCreated.status, plan: plan.name.toLowerCase(), periodStart, periodEnd, @@ -248,13 +254,13 @@ export async function onSubscriptionCreated( }); ctx.context.logger.info( - `Stripe webhook: Created subscription ${subscriptionCreated.id} for ${customerType} ${referenceId} from dashboard`, + `Stripe webhook: Created subscription ${stripeSubscriptionCreated.id} for ${customerType} ${referenceId} from dashboard`, ); await options.subscription.onSubscriptionCreated?.({ event, subscription: newSubscription, - stripeSubscription: subscriptionCreated, + stripeSubscription: stripeSubscriptionCreated, plan, }); } catch (error: any) { @@ -271,14 +277,14 @@ export async function onSubscriptionUpdated( if (!options.subscription?.enabled) { return; } - const subscriptionUpdated = event.data.object as Stripe.Subscription; + const stripeSubscriptionUpdated = event.data.object as Stripe.Subscription; const resolved = await resolvePlanItem( options, - subscriptionUpdated.items.data, + stripeSubscriptionUpdated.items.data, ); if (!resolved) { ctx.context.logger.warn( - `Stripe webhook warning: Subscription ${subscriptionUpdated.id} has no items matching a configured plan`, + `Stripe webhook warning: Subscription ${stripeSubscriptionUpdated.id} has no items matching a configured plan`, ); return; } @@ -286,14 +292,19 @@ export async function onSubscriptionUpdated( const { item: subscriptionItem, plan } = resolved; const { subscriptionId } = subscriptionMetadata.get( - subscriptionUpdated.metadata, + stripeSubscriptionUpdated.metadata, ); - const customerId = subscriptionUpdated.customer?.toString(); + const customerId = stripeSubscriptionUpdated.customer?.toString(); let subscription = await ctx.context.adapter.findOne({ model: "subscription", where: subscriptionId ? [{ field: "id", value: subscriptionId }] - : [{ field: "stripeSubscriptionId", value: subscriptionUpdated.id }], + : [ + { + field: "stripeSubscriptionId", + value: stripeSubscriptionUpdated.id, + }, + ], }); if (!subscription) { const subs = await ctx.context.adapter.findMany({ @@ -318,21 +329,22 @@ export async function onSubscriptionUpdated( const seats = plan ? resolveQuantity( - subscriptionUpdated.items.data, + stripeSubscriptionUpdated.items.data, subscriptionItem, plan.seatPriceId, ) : subscriptionItem.quantity; const trial = - subscriptionUpdated.trial_start && subscriptionUpdated.trial_end + stripeSubscriptionUpdated.trial_start && + stripeSubscriptionUpdated.trial_end ? { - trialStart: new Date(subscriptionUpdated.trial_start * 1000), - trialEnd: new Date(subscriptionUpdated.trial_end * 1000), + trialStart: new Date(stripeSubscriptionUpdated.trial_start * 1000), + trialEnd: new Date(stripeSubscriptionUpdated.trial_end * 1000), } : {}; - const updatedSubscription = await ctx.context.adapter.update({ + const subscriptionUpdated = await ctx.context.adapter.update({ model: "subscription", update: { ...trial, @@ -343,26 +355,26 @@ export async function onSubscriptionUpdated( } : {}), updatedAt: new Date(), - status: subscriptionUpdated.status, + status: stripeSubscriptionUpdated.status, periodStart: new Date(subscriptionItem.current_period_start * 1000), periodEnd: new Date(subscriptionItem.current_period_end * 1000), - cancelAtPeriodEnd: subscriptionUpdated.cancel_at_period_end, - cancelAt: subscriptionUpdated.cancel_at - ? new Date(subscriptionUpdated.cancel_at * 1000) + cancelAtPeriodEnd: stripeSubscriptionUpdated.cancel_at_period_end, + cancelAt: stripeSubscriptionUpdated.cancel_at + ? new Date(stripeSubscriptionUpdated.cancel_at * 1000) : null, - canceledAt: subscriptionUpdated.canceled_at - ? new Date(subscriptionUpdated.canceled_at * 1000) + canceledAt: stripeSubscriptionUpdated.canceled_at + ? new Date(stripeSubscriptionUpdated.canceled_at * 1000) : null, - endedAt: subscriptionUpdated.ended_at - ? new Date(subscriptionUpdated.ended_at * 1000) + endedAt: stripeSubscriptionUpdated.ended_at + ? new Date(stripeSubscriptionUpdated.ended_at * 1000) : null, seats, - stripeSubscriptionId: subscriptionUpdated.id, + stripeSubscriptionId: stripeSubscriptionUpdated.id, billingInterval: subscriptionItem.price.recurring?.interval, - stripeScheduleId: subscriptionUpdated.schedule - ? typeof subscriptionUpdated.schedule === "string" - ? subscriptionUpdated.schedule - : subscriptionUpdated.schedule.id + stripeScheduleId: stripeSubscriptionUpdated.schedule + ? typeof stripeSubscriptionUpdated.schedule === "string" + ? stripeSubscriptionUpdated.schedule + : stripeSubscriptionUpdated.schedule.id : null, }, where: [ @@ -373,7 +385,7 @@ export async function onSubscriptionUpdated( ], }); // Practically unreachable. A null here means the row was deleted between the read above and this update. - if (!updatedSubscription) { + if (!subscriptionUpdated) { ctx.context.logger.warn( `Stripe webhook warning: Subscription ${subscription.id} update returned no row (likely deleted concurrently), skipping callbacks`, ); @@ -381,33 +393,33 @@ export async function onSubscriptionUpdated( } const isNewCancellation = - subscriptionUpdated.status === "active" && - isStripePendingCancel(subscriptionUpdated) && + stripeSubscriptionUpdated.status === "active" && + isStripePendingCancel(stripeSubscriptionUpdated) && !isPendingCancel(subscription); if (isNewCancellation) { await options.subscription.onSubscriptionCancel?.({ event, - subscription: updatedSubscription, - stripeSubscription: subscriptionUpdated, + subscription: subscriptionUpdated, + stripeSubscription: stripeSubscriptionUpdated, cancellationDetails: - subscriptionUpdated.cancellation_details || undefined, + stripeSubscriptionUpdated.cancellation_details || undefined, }); } await options.subscription.onSubscriptionUpdate?.({ event, - subscription: updatedSubscription, - stripeSubscription: subscriptionUpdated, + subscription: subscriptionUpdated, + stripeSubscription: stripeSubscriptionUpdated, }); if (plan) { if ( - subscriptionUpdated.status === "active" && + stripeSubscriptionUpdated.status === "active" && subscription.status === "trialing" && plan.freeTrial?.onTrialEnd ) { await plan.freeTrial.onTrialEnd({ subscription }, ctx); } if ( - subscriptionUpdated.status === "incomplete_expired" && + stripeSubscriptionUpdated.status === "incomplete_expired" && subscription.status === "trialing" && plan.freeTrial?.onTrialExpired ) { @@ -428,8 +440,8 @@ export async function onSubscriptionDeleted( return; } try { - const subscriptionDeleted = event.data.object as Stripe.Subscription; - const subscriptionId = subscriptionDeleted.id; + const stripeSubscriptionDeleted = event.data.object as Stripe.Subscription; + const subscriptionId = stripeSubscriptionDeleted.id; const subscription = await ctx.context.adapter.findOne({ model: "subscription", where: [ @@ -441,10 +453,13 @@ export async function onSubscriptionDeleted( }); if (subscription) { const trial = - subscriptionDeleted.trial_start && subscriptionDeleted.trial_end + stripeSubscriptionDeleted.trial_start && + stripeSubscriptionDeleted.trial_end ? { - trialStart: new Date(subscriptionDeleted.trial_start * 1000), - trialEnd: new Date(subscriptionDeleted.trial_end * 1000), + trialStart: new Date( + stripeSubscriptionDeleted.trial_start * 1000, + ), + trialEnd: new Date(stripeSubscriptionDeleted.trial_end * 1000), } : {}; await ctx.context.adapter.update({ @@ -459,22 +474,22 @@ export async function onSubscriptionDeleted( ...trial, status: "canceled", updatedAt: new Date(), - cancelAtPeriodEnd: subscriptionDeleted.cancel_at_period_end, - cancelAt: subscriptionDeleted.cancel_at - ? new Date(subscriptionDeleted.cancel_at * 1000) + cancelAtPeriodEnd: stripeSubscriptionDeleted.cancel_at_period_end, + cancelAt: stripeSubscriptionDeleted.cancel_at + ? new Date(stripeSubscriptionDeleted.cancel_at * 1000) : null, - canceledAt: subscriptionDeleted.canceled_at - ? new Date(subscriptionDeleted.canceled_at * 1000) + canceledAt: stripeSubscriptionDeleted.canceled_at + ? new Date(stripeSubscriptionDeleted.canceled_at * 1000) : null, - endedAt: subscriptionDeleted.ended_at - ? new Date(subscriptionDeleted.ended_at * 1000) + endedAt: stripeSubscriptionDeleted.ended_at + ? new Date(stripeSubscriptionDeleted.ended_at * 1000) : null, stripeScheduleId: null, }, }); await options.subscription.onSubscriptionDeleted?.({ event, - stripeSubscription: subscriptionDeleted, + stripeSubscription: stripeSubscriptionDeleted, subscription, }); } else {