mirror of
https://github.com/LukeHagar/better-auth.git
synced 2025-12-07 20:37:44 +00:00
fix(stripe): update subscription webhook handling should use customer id as a fallback
This commit is contained in:
@@ -20,6 +20,7 @@ import { nextCookies } from "better-auth/next-js";
|
||||
import { passkey } from "better-auth/plugins/passkey";
|
||||
import { stripe } from "@better-auth/stripe";
|
||||
import { Stripe } from "stripe";
|
||||
import Database from "better-sqlite3";
|
||||
|
||||
const from = process.env.BETTER_AUTH_EMAIL || "delivered@resend.dev";
|
||||
const to = process.env.TEST_EMAIL || "";
|
||||
@@ -50,10 +51,7 @@ const STARTER_PRICE_ID = {
|
||||
|
||||
export const auth = betterAuth({
|
||||
appName: "Better Auth Demo",
|
||||
database: {
|
||||
dialect,
|
||||
type: process.env.USE_MYSQL ? "mysql" : "sqlite",
|
||||
},
|
||||
database: new Database("stripe-1.db"),
|
||||
emailVerification: {
|
||||
async sendVerificationEmail({ user, url }) {
|
||||
const res = await resend.emails.send({
|
||||
|
||||
@@ -93,19 +93,32 @@ export async function onSubscriptionUpdated(
|
||||
const subscriptionUpdated = event.data.object as Stripe.Subscription;
|
||||
const priceId = subscriptionUpdated.items.data[0].price.id;
|
||||
const plan = await getPlanByPriceId(options, priceId);
|
||||
const stripeId = subscriptionUpdated.id;
|
||||
const subscription = await ctx.context.adapter.findOne<Subscription>({
|
||||
|
||||
const referenceId = subscriptionUpdated.metadata?.referenceId;
|
||||
const subscriptionId = subscriptionUpdated.id;
|
||||
const customerId = subscriptionUpdated.customer.toString();
|
||||
let subscription = await ctx.context.adapter.findOne<Subscription>({
|
||||
model: "subscription",
|
||||
where: [
|
||||
{
|
||||
field: "stripeSubscriptionId",
|
||||
value: stripeId,
|
||||
},
|
||||
],
|
||||
where: referenceId
|
||||
? [{ field: "referenceId", value: referenceId }]
|
||||
: subscriptionId
|
||||
? [{ field: "stripeSubscriptionId", value: subscriptionId }]
|
||||
: [],
|
||||
});
|
||||
if (!subscription) {
|
||||
const subs = await ctx.context.adapter.findMany<Subscription>({
|
||||
model: "subscription",
|
||||
where: [{ field: "stripeCustomerId", value: customerId }],
|
||||
});
|
||||
if (subs.length > 1) {
|
||||
logger.warn(
|
||||
`Stripe webhook error: Multiple subscriptions found for customerId: ${customerId} and no referenceId or subscriptionId is provided`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
subscription = subs[0];
|
||||
}
|
||||
|
||||
const seats = subscriptionUpdated.items.data[0].quantity;
|
||||
await ctx.context.adapter.update({
|
||||
model: "subscription",
|
||||
@@ -125,8 +138,8 @@ export async function onSubscriptionUpdated(
|
||||
},
|
||||
where: [
|
||||
{
|
||||
field: "stripeSubscriptionId",
|
||||
value: subscriptionUpdated.id,
|
||||
field: "referenceId",
|
||||
value: subscription.referenceId,
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -170,7 +183,7 @@ export async function onSubscriptionUpdated(
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
logger.error(`Stripe webhook failed. Error: ${error.message}`);
|
||||
logger.error(`Stripe webhook failed. Error: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,6 +230,6 @@ export async function onSubscriptionDeleted(
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
logger.error(`Stripe webhook failed. Error: ${error.message}`);
|
||||
logger.error(`Stripe webhook failed. Error: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,7 +366,6 @@ export const stripe = <O extends StripeOptions>(options: O) => {
|
||||
},
|
||||
],
|
||||
});
|
||||
console.log({ subscription });
|
||||
if (
|
||||
!subscription ||
|
||||
subscription.cancelAtPeriodEnd ||
|
||||
@@ -382,7 +381,6 @@ export const stripe = <O extends StripeOptions>(options: O) => {
|
||||
const currentSubscription = stripeSubscription.data.find(
|
||||
(sub) => sub.id === subscription.stripeSubscriptionId,
|
||||
);
|
||||
console.log({ currentSubscription });
|
||||
if (currentSubscription?.cancel_at_period_end === true) {
|
||||
await ctx.context.adapter.update({
|
||||
model: "subscription",
|
||||
|
||||
@@ -592,7 +592,6 @@ describe("stripe", async () => {
|
||||
|
||||
mockStripeForEvents.webhooks.constructEvent.mockReturnValue(updateEvent);
|
||||
await eventTestAuth.handler(updateRequest);
|
||||
|
||||
expect(onSubscriptionUpdate).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
event: expect.any(Object),
|
||||
|
||||
Reference in New Issue
Block a user