mirror of
https://github.com/better-auth/better-auth.git
synced 2026-10-19 23:53:17 -05:00
refactor(stripe): rename subscription webhook variables for clarity
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user