refactor(stripe): rename subscription webhook variables for clarity

This commit is contained in:
Taesu
2026-04-26 18:50:49 +09:00
parent 5d24a7478b
commit 373a9588a7
+76 -61
View File
@@ -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<Subscription>({
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<Subscription>({
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<Subscription>({
@@ -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<Subscription>({
const subscriptionUpdated = await ctx.context.adapter.update<Subscription>({
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<Subscription>({
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 {