Skip to content

Commit 1c16655

Browse files
committed
fix(stripe): update subscription webhook handling should use customer id as a fallback
1 parent 25de4b5 commit 1c16655

File tree

4 files changed

+28
-20
lines changed

4 files changed

+28
-20
lines changed

demo/nextjs/lib/auth.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { nextCookies } from "better-auth/next-js";
2020
import { passkey } from "better-auth/plugins/passkey";
2121
import { stripe } from "@better-auth/stripe";
2222
import { Stripe } from "stripe";
23+
import Database from "better-sqlite3";
2324

2425
const from = process.env.BETTER_AUTH_EMAIL || "delivered@resend.dev";
2526
const to = process.env.TEST_EMAIL || "";
@@ -50,10 +51,7 @@ const STARTER_PRICE_ID = {
5051

5152
export const auth = betterAuth({
5253
appName: "Better Auth Demo",
53-
database: {
54-
dialect,
55-
type: process.env.USE_MYSQL ? "mysql" : "sqlite",
56-
},
54+
database: new Database("stripe-1.db"),
5755
emailVerification: {
5856
async sendVerificationEmail({ user, url }) {
5957
const res = await resend.emails.send({

packages/stripe/src/hooks.ts

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -93,19 +93,32 @@ export async function onSubscriptionUpdated(
9393
const subscriptionUpdated = event.data.object as Stripe.Subscription;
9494
const priceId = subscriptionUpdated.items.data[0].price.id;
9595
const plan = await getPlanByPriceId(options, priceId);
96-
const stripeId = subscriptionUpdated.id;
97-
const subscription = await ctx.context.adapter.findOne<Subscription>({
96+
97+
const referenceId = subscriptionUpdated.metadata?.referenceId;
98+
const subscriptionId = subscriptionUpdated.id;
99+
const customerId = subscriptionUpdated.customer.toString();
100+
let subscription = await ctx.context.adapter.findOne<Subscription>({
98101
model: "subscription",
99-
where: [
100-
{
101-
field: "stripeSubscriptionId",
102-
value: stripeId,
103-
},
104-
],
102+
where: referenceId
103+
? [{ field: "referenceId", value: referenceId }]
104+
: subscriptionId
105+
? [{ field: "stripeSubscriptionId", value: subscriptionId }]
106+
: [],
105107
});
106108
if (!subscription) {
107-
return;
109+
const subs = await ctx.context.adapter.findMany<Subscription>({
110+
model: "subscription",
111+
where: [{ field: "stripeCustomerId", value: customerId }],
112+
});
113+
if (subs.length > 1) {
114+
logger.warn(
115+
`Stripe webhook error: Multiple subscriptions found for customerId: ${customerId} and no referenceId or subscriptionId is provided`,
116+
);
117+
return;
118+
}
119+
subscription = subs[0];
108120
}
121+
109122
const seats = subscriptionUpdated.items.data[0].quantity;
110123
await ctx.context.adapter.update({
111124
model: "subscription",
@@ -125,8 +138,8 @@ export async function onSubscriptionUpdated(
125138
},
126139
where: [
127140
{
128-
field: "stripeSubscriptionId",
129-
value: subscriptionUpdated.id,
141+
field: "referenceId",
142+
value: subscription.referenceId,
130143
},
131144
],
132145
});
@@ -170,7 +183,7 @@ export async function onSubscriptionUpdated(
170183
}
171184
}
172185
} catch (error: any) {
173-
logger.error(`Stripe webhook failed. Error: ${error.message}`);
186+
logger.error(`Stripe webhook failed. Error: ${error}`);
174187
}
175188
}
176189

@@ -217,6 +230,6 @@ export async function onSubscriptionDeleted(
217230
}
218231
}
219232
} catch (error: any) {
220-
logger.error(`Stripe webhook failed. Error: ${error.message}`);
233+
logger.error(`Stripe webhook failed. Error: ${error}`);
221234
}
222235
}

packages/stripe/src/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,6 @@ export const stripe = <O extends StripeOptions>(options: O) => {
366366
},
367367
],
368368
});
369-
console.log({ subscription });
370369
if (
371370
!subscription ||
372371
subscription.cancelAtPeriodEnd ||
@@ -382,7 +381,6 @@ export const stripe = <O extends StripeOptions>(options: O) => {
382381
const currentSubscription = stripeSubscription.data.find(
383382
(sub) => sub.id === subscription.stripeSubscriptionId,
384383
);
385-
console.log({ currentSubscription });
386384
if (currentSubscription?.cancel_at_period_end === true) {
387385
await ctx.context.adapter.update({
388386
model: "subscription",

packages/stripe/src/stripe.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,6 @@ describe("stripe", async () => {
592592

593593
mockStripeForEvents.webhooks.constructEvent.mockReturnValue(updateEvent);
594594
await eventTestAuth.handler(updateRequest);
595-
596595
expect(onSubscriptionUpdate).toHaveBeenCalledWith(
597596
expect.objectContaining({
598597
event: expect.any(Object),

0 commit comments

Comments
 (0)