BA
Better Auth•2d ago
Vexoa

Stripe Plugin | Webhook Event Failure

Upon testing extensively, it appears the cancellation functionality of the plugin doesn't work at all.
2025-03-02 01:54:13 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1Qy1jMFPuZ6ftAZV4fTCVBhl]
2025-03-02 01:54:13 --> customer.subscription.deleted [evt_1Qy1jMFPuZ6ftAZVi3u38WYV]
2025-03-02 01:54:13 <-- [400] POST http://localhost:3000/api/auth/stripe/webhook [evt_1Qy1jMFPuZ6ftAZVi3u38WYV]
2025-03-02 01:54:13 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1Qy1jMFPuZ6ftAZV4fTCVBhl]
2025-03-02 01:54:13 --> customer.subscription.deleted [evt_1Qy1jMFPuZ6ftAZVi3u38WYV]
2025-03-02 01:54:13 <-- [400] POST http://localhost:3000/api/auth/stripe/webhook [evt_1Qy1jMFPuZ6ftAZVi3u38WYV]
No description
No description
97 Replies
Vexoa
VexoaOP•2d ago
It states that its a 200 request in the actual code, but doesn't set the active status back to no sub Another isuse, none of the hooks for
subscription: {
// ... other options
onSubscriptionComplete: async ({ event, subscription, stripeSubscription, plan }) => {
// Called when a subscription is successfully created
await sendWelcomeEmail(subscription.referenceId, plan.name);
},
onSubscriptionUpdate: async ({ event, subscription }) => {
// Called when a subscription is updated
console.log(`Subscription ${subscription.id} updated`);
},
onSubscriptionCancel: async ({ event, subscription, stripeSubscription, cancellationDetails }) => {
// Called when a subscription is canceled
await sendCancellationEmail(subscription.referenceId);
},
onSubscriptionDeleted: async ({ event, subscription, stripeSubscription }) => {
// Called when a subscription is deleted
console.log(`Subscription ${subscription.id} deleted`);
}
}
subscription: {
// ... other options
onSubscriptionComplete: async ({ event, subscription, stripeSubscription, plan }) => {
// Called when a subscription is successfully created
await sendWelcomeEmail(subscription.referenceId, plan.name);
},
onSubscriptionUpdate: async ({ event, subscription }) => {
// Called when a subscription is updated
console.log(`Subscription ${subscription.id} updated`);
},
onSubscriptionCancel: async ({ event, subscription, stripeSubscription, cancellationDetails }) => {
// Called when a subscription is canceled
await sendCancellationEmail(subscription.referenceId);
},
onSubscriptionDeleted: async ({ event, subscription, stripeSubscription }) => {
// Called when a subscription is deleted
console.log(`Subscription ${subscription.id} deleted`);
}
}
works
Vexoa
VexoaOP•2d ago
No description
Vexoa
VexoaOP•2d ago
No description
Vexoa
VexoaOP•2d ago
I've tried multiple things and its still not working
3hamerti
3hamerti•2d ago
This is happening to me too
bekacru
bekacru•2d ago
can you guys try 1.2.1-beta.4
3hamerti
3hamerti•2d ago
I tested it and it still doesn't work
bekacru
bekacru•2d ago
what exactly doesn't work?
3hamerti
3hamerti•2d ago
I cancel the subscription, I receive the webhook (200) but the database does not update and the subscription remains active
bekacru
bekacru•2d ago
1.2.1-beta.5 👀
3hamerti
3hamerti•2d ago
Something went wrong with the typing
No description
3hamerti
3hamerti•2d ago
I forgot to update best-auth/stripe to 1.2.1-beta.5
3hamerti
3hamerti•2d ago
However, I still sign and then cancel and do not update the database
No description
No description
bekacru
bekacru•2d ago
when you cancel a sub, it won't be automatically cancelled until the billing period end.
3hamerti
3hamerti•2d ago
I understand, but when the subscription ends, does Stripe send a webhook?
bekacru
bekacru•2d ago
yeah actually it should have set cancel_at_period_end let me take a look
3hamerti
3hamerti•2d ago
ok
Vexoa
VexoaOP•2d ago
Does this support instant sub cancelling on stripe? I will test it now
2025-03-02T09:42:57.174Z ERROR [Better Auth]: Stripe webhook failed. Error: Stripe: Argument "subscription_exposed_id" must be a string, but got: undefined (on API request to `GET /v1/subscriptions/{subscription_exposed_id}`)
2025-03-02T09:42:57.174Z ERROR [Better Auth]: Stripe webhook failed. Error: Stripe: Argument "subscription_exposed_id" must be a string, but got: undefined (on API request to `GET /v1/subscriptions/{subscription_exposed_id}`)
That was beta v5, testing v6 now
2025-03-02T09:42:57.174Z ERROR [Better Auth]: Stripe webhook failed. Error: Stripe: Argument "subscription_exposed_id" must be a string, but got: undefined (on API request to `GET /v1/subscriptions/{subscription_exposed_id}`)
2025-03-02T09:42:57.174Z ERROR [Better Auth]: Stripe webhook failed. Error: Stripe: Argument "subscription_exposed_id" must be a string, but got: undefined (on API request to `GET /v1/subscriptions/{subscription_exposed_id}`)
This is the current status of the problems, checking if i need to update schema once done that, will let oyu know if it works Same issue, when triggering it from the stripe dashboard to cancel It deosn't work at all @bekacru am i doing anything wrong here? also another bug with the beta versio admin plugin requires as any to not throw type errors going to fix it myself and push it to the github repo saves you going backc and fourth If this helps:
Vexoa
VexoaOP•2d ago
Vexoa
VexoaOP•2d ago
the event that is failing
bekacru
bekacru•2d ago
try the last release should fix the stripe issues
Vexoa
VexoaOP•2d ago
Alright, is there any major breaking changes and do i have to resubscribe to test
bekacru
bekacru•2d ago
no just fixes
Vexoa
VexoaOP•2d ago
Alright, so i can just resend the event through stripe and it should work or do i need to resub
bekacru
bekacru•2d ago
yeah it should work without resub
Vexoa
VexoaOP•2d ago
Testing now give me 2 minutes found another bug its creating 2 customers on register now but im testing subs now and its also making 2 subs
Vexoa
VexoaOP•2d ago
No description
No description
bekacru
bekacru•2d ago
hmm? so when you signup 2 customers are being created?
Vexoa
VexoaOP•2d ago
Yeah i can add you to my repo so you can test it out yourself if you want I only need to update better-auth right? nothing else
bekacru
bekacru•2d ago
no it's fine. but check that you're not doing something 2 times
Vexoa
VexoaOP•2d ago
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
setGeneralError(null)

try {
// Validate form data with Zod
const validatedData = registerSchema.parse(formData)

// Use authClient to sign up
const { firstName, lastName, email, password } = validatedData

const { data, error } = await authClient.signUp.email({
email,
password,
name: `${firstName} ${lastName}`,
callbackURL: "/dashboard",
}, {
onRequest: () => {
setIsLoading(true)
},
onSuccess: () => {
// Redirect will be handled by the auth client
console.log("Registration successful")
router.push("/dashboard")
},
onError: (ctx) => {
setGeneralError(ctx.error.message)
}
})

if (error) {
throw error
}

} catch (error) {
if (error instanceof z.ZodError) {
// Convert Zod errors to a more usable format
const fieldErrors: Partial<Record<keyof RegisterFormData, string>> = {}
error.errors.forEach(err => {
const field = err.path[0] as keyof RegisterFormData
fieldErrors[field] = err.message
})
setErrors(fieldErrors)
} else if (error instanceof Error) {
// Handle other errors
setGeneralError(error.message)
} else {
// Fallback error message
setGeneralError("An unknown error occurred")
}
} finally {
setIsLoading(false)
}
}

const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
setGeneralError(null)

try {
// Validate form data with Zod
const validatedData = registerSchema.parse(formData)

// Use authClient to sign up
const { firstName, lastName, email, password } = validatedData

const { data, error } = await authClient.signUp.email({
email,
password,
name: `${firstName} ${lastName}`,
callbackURL: "/dashboard",
}, {
onRequest: () => {
setIsLoading(true)
},
onSuccess: () => {
// Redirect will be handled by the auth client
console.log("Registration successful")
router.push("/dashboard")
},
onError: (ctx) => {
setGeneralError(ctx.error.message)
}
})

if (error) {
throw error
}

} catch (error) {
if (error instanceof z.ZodError) {
// Convert Zod errors to a more usable format
const fieldErrors: Partial<Record<keyof RegisterFormData, string>> = {}
error.errors.forEach(err => {
const field = err.path[0] as keyof RegisterFormData
fieldErrors[field] = err.message
})
setErrors(fieldErrors)
} else if (error instanceof Error) {
// Handle other errors
setGeneralError(error.message)
} else {
// Fallback error message
setGeneralError("An unknown error occurred")
}
} finally {
setIsLoading(false)
}
}

bekacru
bekacru•2d ago
customers are created through hooks. Unless the hook is called 2 times, it can't happen.
Vexoa
VexoaOP•2d ago
this is my register form shouldn't be called twice
Vexoa
VexoaOP•2d ago
No description
Vexoa
VexoaOP•2d ago
console shows only 1 register event was called
bekacru
bekacru•2d ago
for sign up there is no event that's handled by better auth it jsut updates stripeCustomerId field make sure you're on v1.2.1-beta.7 pnpm i [email protected]
Vexoa
VexoaOP•2d ago
No description
Vexoa
VexoaOP•2d ago
im on beta 7 I installed it the minute you released it So the way im doing it is wrong? I'm unsure why its throwing 2 customers into the mix I deleted it manually in stripe + db to make sure that didnt break it
bekacru
bekacru•2d ago
wait, what is customer?
Vexoa
VexoaOP•2d ago
in the stripe dash it made 2 customers
bekacru
bekacru•2d ago
there should only be user table and stripeCustomerId oh
Vexoa
VexoaOP•2d ago
new database schema?
bekacru
bekacru•2d ago
no. if you had tried better auth before 1.2 release we used to have a customer table. never mind.
Vexoa
VexoaOP•2d ago
import { pgTable, text, timestamp, boolean, integer } from "drizzle-orm/pg-core"

export const user = pgTable("user", {
id: text("id").primaryKey(),
name: text('name').notNull(),
email: text('email').notNull().unique(),
emailVerified: boolean('email_verified').notNull(),
image: text('image'),
createdAt: timestamp('created_at').notNull(),
updatedAt: timestamp('updated_at').notNull(),
role: text('role'),
banned: boolean('banned'),
banReason: text('ban_reason'),
banExpires: timestamp('ban_expires'),
stripeCustomerId: text('stripe_customer_id')
});

export const session = pgTable("session", {
id: text("id").primaryKey(),
expiresAt: timestamp('expires_at').notNull(),
token: text('token').notNull().unique(),
createdAt: timestamp('created_at').notNull(),
updatedAt: timestamp('updated_at').notNull(),
ipAddress: text('ip_address'),
userAgent: text('user_agent'),
userId: text('user_id').notNull().references(()=> user.id, { onDelete: 'cascade' }),
impersonatedBy: text('impersonated_by')
});

export const account = pgTable("account", {
id: text("id").primaryKey(),
accountId: text('account_id').notNull(),
providerId: text('provider_id').notNull(),
userId: text('user_id').notNull().references(()=> user.id, { onDelete: 'cascade' }),
accessToken: text('access_token'),
refreshToken: text('refresh_token'),
idToken: text('id_token'),
accessTokenExpiresAt: timestamp('access_token_expires_at'),
refreshTokenExpiresAt: timestamp('refresh_token_expires_at'),
scope: text('scope'),
password: text('password'),
createdAt: timestamp('created_at').notNull(),
updatedAt: timestamp('updated_at').notNull()
});

export const verification = pgTable("verification", {
id: text("id").primaryKey(),
identifier: text('identifier').notNull(),
value: text('value').notNull(),
expiresAt: timestamp('expires_at').notNull(),
createdAt: timestamp('created_at'),
updatedAt: timestamp('updated_at')
});

export const subscription = pgTable("subscription", {
id: text("id").primaryKey(),
plan: text('plan').notNull(),
referenceId: text('reference_id').notNull(),
stripeCustomerId: text('stripe_customer_id'),
stripeSubscriptionId: text('stripe_subscription_id'),
status: text('status'),
periodStart: timestamp('period_start'),
periodEnd: timestamp('period_end'),
cancelAtPeriodEnd: boolean('cancel_at_period_end'),
seats: integer('seats')
});
import { pgTable, text, timestamp, boolean, integer } from "drizzle-orm/pg-core"

export const user = pgTable("user", {
id: text("id").primaryKey(),
name: text('name').notNull(),
email: text('email').notNull().unique(),
emailVerified: boolean('email_verified').notNull(),
image: text('image'),
createdAt: timestamp('created_at').notNull(),
updatedAt: timestamp('updated_at').notNull(),
role: text('role'),
banned: boolean('banned'),
banReason: text('ban_reason'),
banExpires: timestamp('ban_expires'),
stripeCustomerId: text('stripe_customer_id')
});

export const session = pgTable("session", {
id: text("id").primaryKey(),
expiresAt: timestamp('expires_at').notNull(),
token: text('token').notNull().unique(),
createdAt: timestamp('created_at').notNull(),
updatedAt: timestamp('updated_at').notNull(),
ipAddress: text('ip_address'),
userAgent: text('user_agent'),
userId: text('user_id').notNull().references(()=> user.id, { onDelete: 'cascade' }),
impersonatedBy: text('impersonated_by')
});

export const account = pgTable("account", {
id: text("id").primaryKey(),
accountId: text('account_id').notNull(),
providerId: text('provider_id').notNull(),
userId: text('user_id').notNull().references(()=> user.id, { onDelete: 'cascade' }),
accessToken: text('access_token'),
refreshToken: text('refresh_token'),
idToken: text('id_token'),
accessTokenExpiresAt: timestamp('access_token_expires_at'),
refreshTokenExpiresAt: timestamp('refresh_token_expires_at'),
scope: text('scope'),
password: text('password'),
createdAt: timestamp('created_at').notNull(),
updatedAt: timestamp('updated_at').notNull()
});

export const verification = pgTable("verification", {
id: text("id").primaryKey(),
identifier: text('identifier').notNull(),
value: text('value').notNull(),
expiresAt: timestamp('expires_at').notNull(),
createdAt: timestamp('created_at'),
updatedAt: timestamp('updated_at')
});

export const subscription = pgTable("subscription", {
id: text("id").primaryKey(),
plan: text('plan').notNull(),
referenceId: text('reference_id').notNull(),
stripeCustomerId: text('stripe_customer_id'),
stripeSubscriptionId: text('stripe_subscription_id'),
status: text('status'),
periodStart: timestamp('period_start'),
periodEnd: timestamp('period_end'),
cancelAtPeriodEnd: boolean('cancel_at_period_end'),
seats: integer('seats')
});
this is the schema i have
bekacru
bekacru•2d ago
this is correct
Vexoa
VexoaOP•2d ago
Yeah im unsure why its not working then You know when you're testing, are you using the stripe dash or using the function to cancel it? as im doing it in the dash to instantly end the sub
bekacru
bekacru•2d ago
both should work
Vexoa
VexoaOP•2d ago
Yeah doesn't work for me, let me make a quick test page as my subs page is like 700 lines with the design
bekacru
bekacru•2d ago
wait the customer creation should work
Vexoa
VexoaOP•2d ago
I'll completely restart everything fresh install of db and let you know
bekacru
bekacru•2d ago
okay thanks!
Vexoa
VexoaOP•2d ago
No worries, about to have it back up with all fresh stuff gonna use a different email to register too
Vexoa
VexoaOP•2d ago
so a reboot fixed the 2 customer being made issue, im now subscribed
No description
Vexoa
VexoaOP•2d ago
Ahh nvm found an issue
Vexoa
VexoaOP•2d ago
No description
Vexoa
VexoaOP•2d ago
I just subscribed and its done this
Vexoa
VexoaOP•2d ago
No description
Vexoa
VexoaOP•2d ago
So when subscribing, its not using the already made customer to make the subscription and also changing the name + making a new customer upon cancelling still has a ton of issues
bekacru
bekacru•2d ago
so after the first customer is created it should update user.stripeCustomerId check that for me.
Vexoa
VexoaOP•2d ago
it made a new customer and set the customer id as that instead of using the already made one on first registration
bekacru
bekacru•2d ago
on first registration, it'll always make a new cutsomer and updates stripeCustomerId
Vexoa
VexoaOP•2d ago
yeah i deleted all customers and then made a new user and it made another one with a completely different name
✓ Compiled /dashboard/settings/billing in 461ms (1901 modules)
GET /dashboard/settings/billing 200 in 537ms
POST /api/auth/stripe/webhook 200 in 10ms
POST /api/auth/subscription/upgrade 200 in 1209ms
POST /api/auth/stripe/webhook 200 in 14ms
POST /api/auth/stripe/webhook 200 in 8ms
POST /api/auth/stripe/webhook 200 in 7ms
POST /api/auth/stripe/webhook 200 in 7ms
POST /api/auth/stripe/webhook 200 in 7ms
POST /api/auth/stripe/webhook 200 in 32ms
POST /api/auth/stripe/webhook 200 in 7ms
POST /api/auth/stripe/webhook 200 in 593ms
POST /api/auth/stripe/webhook 200 in 14ms
POST /api/auth/stripe/webhook 200 in 12ms
POST /api/auth/stripe/webhook 200 in 21ms
POST /api/auth/stripe/webhook 200 in 22ms
POST /api/auth/stripe/webhook 200 in 25ms
POST /api/auth/stripe/webhook 200 in 27ms
GET /api/auth/subscription/success?callbackURL=http%3A%2F%2Flocalhost%3A3000%2Fdashboard%2Fsettings%2Fbilling%3Fsuccess%3Dtrue&reference=NccK44i7GLQJfrIfnOTgqYJh6ANdcpsB 302 in 38ms
GET /api/auth/get-session 200 in 15ms
GET /dashboard/settings/billing?success=true 200 in 172ms
GET /api/auth/get-session 200 in 68ms
GET /api/auth/get-session 200 in 8ms
GET /api/auth/subscription/list 200 in 45ms
GET /api/auth/subscription/list 200 in 74ms
2025-03-02T10:55:28.963Z ERROR [Better Auth]: Stripe webhook failed. Error: Stripe: Argument "subscription_exposed_id" must be a string, but got: undefined (on API request to `GET /v1/subscriptions/{subscription_exposed_id}`)
POST /api/auth/stripe/webhook 400 in 20ms
POST /api/auth/stripe/webhook 200 in 15ms
POST /api/auth/stripe/webhook 200 in 16ms
POST /api/auth/stripe/webhook 200 in 13ms
✓ Compiled /dashboard/settings/billing in 461ms (1901 modules)
GET /dashboard/settings/billing 200 in 537ms
POST /api/auth/stripe/webhook 200 in 10ms
POST /api/auth/subscription/upgrade 200 in 1209ms
POST /api/auth/stripe/webhook 200 in 14ms
POST /api/auth/stripe/webhook 200 in 8ms
POST /api/auth/stripe/webhook 200 in 7ms
POST /api/auth/stripe/webhook 200 in 7ms
POST /api/auth/stripe/webhook 200 in 7ms
POST /api/auth/stripe/webhook 200 in 32ms
POST /api/auth/stripe/webhook 200 in 7ms
POST /api/auth/stripe/webhook 200 in 593ms
POST /api/auth/stripe/webhook 200 in 14ms
POST /api/auth/stripe/webhook 200 in 12ms
POST /api/auth/stripe/webhook 200 in 21ms
POST /api/auth/stripe/webhook 200 in 22ms
POST /api/auth/stripe/webhook 200 in 25ms
POST /api/auth/stripe/webhook 200 in 27ms
GET /api/auth/subscription/success?callbackURL=http%3A%2F%2Flocalhost%3A3000%2Fdashboard%2Fsettings%2Fbilling%3Fsuccess%3Dtrue&reference=NccK44i7GLQJfrIfnOTgqYJh6ANdcpsB 302 in 38ms
GET /api/auth/get-session 200 in 15ms
GET /dashboard/settings/billing?success=true 200 in 172ms
GET /api/auth/get-session 200 in 68ms
GET /api/auth/get-session 200 in 8ms
GET /api/auth/subscription/list 200 in 45ms
GET /api/auth/subscription/list 200 in 74ms
2025-03-02T10:55:28.963Z ERROR [Better Auth]: Stripe webhook failed. Error: Stripe: Argument "subscription_exposed_id" must be a string, but got: undefined (on API request to `GET /v1/subscriptions/{subscription_exposed_id}`)
POST /api/auth/stripe/webhook 400 in 20ms
POST /api/auth/stripe/webhook 200 in 15ms
POST /api/auth/stripe/webhook 200 in 16ms
POST /api/auth/stripe/webhook 200 in 13ms
these are all the requests made
2025-03-02 10:53:56 --> customer.created [evt_1QyA9hFPuZ6ftAZVf1a01MdR]
2025-03-02 10:53:57 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyA9hFPuZ6ftAZVf1a01MdR]
2025-03-02 10:54:08 --> customer.created [evt_1QyA9uFPuZ6ftAZVqhmN58Cj]
2025-03-02 10:54:08 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyA9uFPuZ6ftAZVqhmN58Cj]
2025-03-02 10:54:19 --> charge.succeeded [evt_3QyAA1FPuZ6ftAZV0zLu17Ud]
2025-03-02 10:54:19 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_3QyAA1FPuZ6ftAZV0zLu17Ud]
2025-03-02 10:54:19 --> payment_method.attached [evt_1QyAA4FPuZ6ftAZVdIDVsnir]
2025-03-02 10:54:19 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA4FPuZ6ftAZVdIDVsnir]
2025-03-02 10:54:19 --> customer.updated [evt_1QyAA4FPuZ6ftAZVHZVSOi2q]
2025-03-02 10:54:19 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA4FPuZ6ftAZVHZVSOi2q]
2025-03-02 10:54:19 --> customer.updated [evt_1QyAA4FPuZ6ftAZVJFCUQipA]
2025-03-02 10:54:19 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA4FPuZ6ftAZVJFCUQipA]
2025-03-02 10:54:19 --> customer.subscription.created [evt_1QyAA4FPuZ6ftAZVREw3hVtq]
2025-03-02 10:54:19 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA4FPuZ6ftAZVREw3hVtq]
2025-03-02 10:54:19 --> checkout.session.completed [evt_1QyAA4FPuZ6ftAZVLgYC4Wd2]
2025-03-02 10:54:19 --> customer.subscription.updated [evt_1QyAA4FPuZ6ftAZVfHNCED0G]
2025-03-02 10:54:19 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA4FPuZ6ftAZVfHNCED0G]
2025-03-02 10:54:19 --> payment_intent.succeeded [evt_3QyAA1FPuZ6ftAZV0zshaem4]
2025-03-02 10:54:20 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_3QyAA1FPuZ6ftAZV0zshaem4]
2025-03-02 10:54:20 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA4FPuZ6ftAZVLgYC4Wd2]
2025-03-02 10:54:20 --> payment_intent.created [evt_3QyAA1FPuZ6ftAZV0UjbF6mz]
2025-03-02 10:54:20 --> invoice.created [evt_1QyAA5FPuZ6ftAZVsJWR6BTM]
2025-03-02 10:54:20 --> invoice.payment_succeeded [evt_1QyAA5FPuZ6ftAZVPCzSel3a]
2025-03-02 10:54:20 --> invoice.finalized [evt_1QyAA5FPuZ6ftAZV0WUE8J1a]
2025-03-02 10:54:20 --> invoice.updated [evt_1QyAA5FPuZ6ftAZVfOAqmdHe]
2025-03-02 10:54:20 --> invoice.paid [evt_1QyAA5FPuZ6ftAZVCQ9NhNCu]
2025-03-02 10:54:20 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_3QyAA1FPuZ6ftAZV0UjbF6mz]
2025-03-02 10:54:20 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA5FPuZ6ftAZVsJWR6BTM]
2025-03-02 10:54:20 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA5FPuZ6ftAZVPCzSel3a]
2025-03-02 10:54:20 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA5FPuZ6ftAZV0WUE8J1a]
2025-03-02 10:54:20 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA5FPuZ6ftAZVfOAqmdHe]
2025-03-02 10:54:20 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA5FPuZ6ftAZVCQ9NhNCu]
2025-03-02 10:55:28 --> customer.subscription.deleted [evt_1QyABCFPuZ6ftAZVuEbBoVDf]
2025-03-02 10:55:28 <-- [400] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyABCFPuZ6ftAZVuEbBoVDf]
[Sun, 02 Mar 2025 10:57:07 GMT] ERROR websocket.Client.writePump: Error when writing ping message: websocket: close sent
2025-03-02 10:58:46 --> customer.deleted [evt_1QyAENFPuZ6ftAZVHOpUCcCV]
2025-03-02 10:58:46 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAENFPuZ6ftAZVHOpUCcCV]
2025-03-02 10:58:51 --> customer.deleted [evt_1QyAESFPuZ6ftAZVO1QFCcsL]
2025-03-02 10:58:51 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAESFPuZ6ftAZVO1QFCcsL]
2025-03-02 10:58:53 --> customer.deleted [evt_1QyAEUFPuZ6ftAZVsZZa97kl]
2025-03-02 10:58:53 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAEUFPuZ6ftAZVsZZa97kl]
2025-03-02 10:53:56 --> customer.created [evt_1QyA9hFPuZ6ftAZVf1a01MdR]
2025-03-02 10:53:57 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyA9hFPuZ6ftAZVf1a01MdR]
2025-03-02 10:54:08 --> customer.created [evt_1QyA9uFPuZ6ftAZVqhmN58Cj]
2025-03-02 10:54:08 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyA9uFPuZ6ftAZVqhmN58Cj]
2025-03-02 10:54:19 --> charge.succeeded [evt_3QyAA1FPuZ6ftAZV0zLu17Ud]
2025-03-02 10:54:19 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_3QyAA1FPuZ6ftAZV0zLu17Ud]
2025-03-02 10:54:19 --> payment_method.attached [evt_1QyAA4FPuZ6ftAZVdIDVsnir]
2025-03-02 10:54:19 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA4FPuZ6ftAZVdIDVsnir]
2025-03-02 10:54:19 --> customer.updated [evt_1QyAA4FPuZ6ftAZVHZVSOi2q]
2025-03-02 10:54:19 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA4FPuZ6ftAZVHZVSOi2q]
2025-03-02 10:54:19 --> customer.updated [evt_1QyAA4FPuZ6ftAZVJFCUQipA]
2025-03-02 10:54:19 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA4FPuZ6ftAZVJFCUQipA]
2025-03-02 10:54:19 --> customer.subscription.created [evt_1QyAA4FPuZ6ftAZVREw3hVtq]
2025-03-02 10:54:19 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA4FPuZ6ftAZVREw3hVtq]
2025-03-02 10:54:19 --> checkout.session.completed [evt_1QyAA4FPuZ6ftAZVLgYC4Wd2]
2025-03-02 10:54:19 --> customer.subscription.updated [evt_1QyAA4FPuZ6ftAZVfHNCED0G]
2025-03-02 10:54:19 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA4FPuZ6ftAZVfHNCED0G]
2025-03-02 10:54:19 --> payment_intent.succeeded [evt_3QyAA1FPuZ6ftAZV0zshaem4]
2025-03-02 10:54:20 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_3QyAA1FPuZ6ftAZV0zshaem4]
2025-03-02 10:54:20 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA4FPuZ6ftAZVLgYC4Wd2]
2025-03-02 10:54:20 --> payment_intent.created [evt_3QyAA1FPuZ6ftAZV0UjbF6mz]
2025-03-02 10:54:20 --> invoice.created [evt_1QyAA5FPuZ6ftAZVsJWR6BTM]
2025-03-02 10:54:20 --> invoice.payment_succeeded [evt_1QyAA5FPuZ6ftAZVPCzSel3a]
2025-03-02 10:54:20 --> invoice.finalized [evt_1QyAA5FPuZ6ftAZV0WUE8J1a]
2025-03-02 10:54:20 --> invoice.updated [evt_1QyAA5FPuZ6ftAZVfOAqmdHe]
2025-03-02 10:54:20 --> invoice.paid [evt_1QyAA5FPuZ6ftAZVCQ9NhNCu]
2025-03-02 10:54:20 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_3QyAA1FPuZ6ftAZV0UjbF6mz]
2025-03-02 10:54:20 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA5FPuZ6ftAZVsJWR6BTM]
2025-03-02 10:54:20 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA5FPuZ6ftAZVPCzSel3a]
2025-03-02 10:54:20 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA5FPuZ6ftAZV0WUE8J1a]
2025-03-02 10:54:20 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA5FPuZ6ftAZVfOAqmdHe]
2025-03-02 10:54:20 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAA5FPuZ6ftAZVCQ9NhNCu]
2025-03-02 10:55:28 --> customer.subscription.deleted [evt_1QyABCFPuZ6ftAZVuEbBoVDf]
2025-03-02 10:55:28 <-- [400] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyABCFPuZ6ftAZVuEbBoVDf]
[Sun, 02 Mar 2025 10:57:07 GMT] ERROR websocket.Client.writePump: Error when writing ping message: websocket: close sent
2025-03-02 10:58:46 --> customer.deleted [evt_1QyAENFPuZ6ftAZVHOpUCcCV]
2025-03-02 10:58:46 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAENFPuZ6ftAZVHOpUCcCV]
2025-03-02 10:58:51 --> customer.deleted [evt_1QyAESFPuZ6ftAZVO1QFCcsL]
2025-03-02 10:58:51 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAESFPuZ6ftAZVO1QFCcsL]
2025-03-02 10:58:53 --> customer.deleted [evt_1QyAEUFPuZ6ftAZVsZZa97kl]
2025-03-02 10:58:53 <-- [200] POST http://localhost:3000/api/auth/stripe/webhook [evt_1QyAEUFPuZ6ftAZVsZZa97kl]
and then we have the stipr webhooks
bekacru
bekacru•2d ago
I think we're missing each other somewhere - whenever a user is created, if customerOnSignUp is enabled, it'll always create a customer on stripe and whenever you try to upgrade a sub, if the user doesn't have stripeCustomerId yet it'll also create a new customer. there should be no reason 2 customers would be created for one user, if they are already assigned stripeCustomerId in your db
Vexoa
VexoaOP•2d ago
I'm aware, i have the customeronsignup enabled and I'll make a new user to show you
bekacru
bekacru•2d ago
wait tell me the behavior, what happens when you register as a new user?
Vexoa
VexoaOP•2d ago
So upon registering a new user
Vexoa
VexoaOP•2d ago
No description
Vexoa
VexoaOP•2d ago
It sets the stripe customer id
Vexoa
VexoaOP•2d ago
No description
Vexoa
VexoaOP•2d ago
In the stripe dashboard as you can see only 2 customers rn
bekacru
bekacru•2d ago
so this is correct, right?
Vexoa
VexoaOP•2d ago
yeah now, let me sub to show you what happens
Vexoa
VexoaOP•2d ago
As you can see no subscirption rn
No description
Vexoa
VexoaOP•2d ago
No description
Vexoa
VexoaOP•2d ago
Now im subscribed
No description
Vexoa
VexoaOP•2d ago
POST /api/auth/subscription/upgrade 200 in 845ms
POST /api/auth/stripe/webhook 200 in 9ms
POST /api/auth/stripe/webhook 200 in 250ms
POST /api/auth/stripe/webhook 200 in 8ms
POST /api/auth/stripe/webhook 200 in 8ms
POST /api/auth/stripe/webhook 200 in 10ms
POST /api/auth/stripe/webhook 200 in 31ms
POST /api/auth/stripe/webhook 200 in 9ms
POST /api/auth/stripe/webhook 200 in 8ms
POST /api/auth/stripe/webhook 200 in 8ms
POST /api/auth/stripe/webhook 200 in 8ms
POST /api/auth/stripe/webhook 200 in 8ms
POST /api/auth/stripe/webhook 200 in 12ms
POST /api/auth/stripe/webhook 200 in 9ms
POST /api/auth/stripe/webhook 200 in 6ms
GET /api/auth/subscription/success?callbackURL=http%3A%2F%2Flocalhost%3A3000%2Fdashboard%2Fsettings%2Fbilling%3Fsuccess%3Dtrue&reference=CTSKrOaZdVGJ6TmtQjFwOmarKgpxtIGT 302 in 34ms
GET /api/auth/get-session 200 in 8ms
GET /dashboard/settings/billing?success=true 200 in 184ms
GET /api/auth/get-session 200 in 14ms
GET /api/auth/get-session 200 in 40ms
GET /api/auth/subscription/list 200 in 43ms
GET /api/auth/subscription/list 200 in 29ms
POST /api/auth/subscription/upgrade 200 in 845ms
POST /api/auth/stripe/webhook 200 in 9ms
POST /api/auth/stripe/webhook 200 in 250ms
POST /api/auth/stripe/webhook 200 in 8ms
POST /api/auth/stripe/webhook 200 in 8ms
POST /api/auth/stripe/webhook 200 in 10ms
POST /api/auth/stripe/webhook 200 in 31ms
POST /api/auth/stripe/webhook 200 in 9ms
POST /api/auth/stripe/webhook 200 in 8ms
POST /api/auth/stripe/webhook 200 in 8ms
POST /api/auth/stripe/webhook 200 in 8ms
POST /api/auth/stripe/webhook 200 in 8ms
POST /api/auth/stripe/webhook 200 in 12ms
POST /api/auth/stripe/webhook 200 in 9ms
POST /api/auth/stripe/webhook 200 in 6ms
GET /api/auth/subscription/success?callbackURL=http%3A%2F%2Flocalhost%3A3000%2Fdashboard%2Fsettings%2Fbilling%3Fsuccess%3Dtrue&reference=CTSKrOaZdVGJ6TmtQjFwOmarKgpxtIGT 302 in 34ms
GET /api/auth/get-session 200 in 8ms
GET /dashboard/settings/billing?success=true 200 in 184ms
GET /api/auth/get-session 200 in 14ms
GET /api/auth/get-session 200 in 40ms
GET /api/auth/subscription/list 200 in 43ms
GET /api/auth/subscription/list 200 in 29ms
This time it didnt' create 2 users now im canceling in the UI
Vexoa
VexoaOP•2d ago
No description
Vexoa
VexoaOP•2d ago
No description
Vexoa
VexoaOP•2d ago
No description
Vexoa
VexoaOP•2d ago
POST /api/auth/subscription/cancel 200 in 542ms
GET /api/auth/subscription/list 200 in 52ms
POST /api/auth/stripe/webhook 200 in 9ms
POST /api/auth/stripe/webhook 200 in 53ms
POST /api/auth/stripe/webhook 200 in 39ms
GET /api/auth/get-session 200 in 14ms
GET /dashboard/settings/billing?canceled=success 200 in 86ms
GET /api/auth/get-session 200 in 13ms
GET /api/auth/get-session 200 in 42ms
GET /api/auth/subscription/list 200 in 41ms
GET /api/auth/subscription/list 200 in 45ms
POST /api/auth/subscription/cancel 200 in 542ms
GET /api/auth/subscription/list 200 in 52ms
POST /api/auth/stripe/webhook 200 in 9ms
POST /api/auth/stripe/webhook 200 in 53ms
POST /api/auth/stripe/webhook 200 in 39ms
GET /api/auth/get-session 200 in 14ms
GET /dashboard/settings/billing?canceled=success 200 in 86ms
GET /api/auth/get-session 200 in 13ms
GET /api/auth/get-session 200 in 42ms
GET /api/auth/subscription/list 200 in 41ms
GET /api/auth/subscription/list 200 in 45ms
Vexoa
VexoaOP•2d ago
No description
Vexoa
VexoaOP•2d ago
So now you can see its still active now let me cancel it in the stripe dash
Vexoa
VexoaOP•2d ago
No description
Vexoa
VexoaOP•2d ago
No description
Vexoa
VexoaOP•2d ago
No description
Vexoa
VexoaOP•2d ago
GET /api/auth/get-session 200 in 8ms
GET /dashboard/settings/billing?success=true 200 in 184ms
GET /api/auth/get-session 200 in 14ms
GET /api/auth/get-session 200 in 40ms
GET /api/auth/subscription/list 200 in 43ms
GET /api/auth/subscription/list 200 in 29ms
POST /api/auth/subscription/cancel 200 in 542ms
GET /api/auth/subscription/list 200 in 52ms
POST /api/auth/stripe/webhook 200 in 9ms
POST /api/auth/stripe/webhook 200 in 53ms
POST /api/auth/stripe/webhook 200 in 39ms
GET /api/auth/get-session 200 in 14ms
GET /dashboard/settings/billing?canceled=success 200 in 86ms
GET /api/auth/get-session 200 in 13ms
GET /api/auth/get-session 200 in 42ms
GET /api/auth/subscription/list 200 in 41ms
GET /api/auth/subscription/list 200 in 45ms
2025-03-02T11:10:18.019Z ERROR [Better Auth]: Stripe webhook failed. Error: Stripe: Argument "subscription_exposed_id" must be a string, but got: undefined (on API request to `GET /v1/subscriptions/{subscription_exposed_id}`)
POST /api/auth/stripe/webhook 400 in 18ms
GET /api/auth/get-session 200 in 8ms
GET /dashboard/settings/billing?success=true 200 in 184ms
GET /api/auth/get-session 200 in 14ms
GET /api/auth/get-session 200 in 40ms
GET /api/auth/subscription/list 200 in 43ms
GET /api/auth/subscription/list 200 in 29ms
POST /api/auth/subscription/cancel 200 in 542ms
GET /api/auth/subscription/list 200 in 52ms
POST /api/auth/stripe/webhook 200 in 9ms
POST /api/auth/stripe/webhook 200 in 53ms
POST /api/auth/stripe/webhook 200 in 39ms
GET /api/auth/get-session 200 in 14ms
GET /dashboard/settings/billing?canceled=success 200 in 86ms
GET /api/auth/get-session 200 in 13ms
GET /api/auth/get-session 200 in 42ms
GET /api/auth/subscription/list 200 in 41ms
GET /api/auth/subscription/list 200 in 45ms
2025-03-02T11:10:18.019Z ERROR [Better Auth]: Stripe webhook failed. Error: Stripe: Argument "subscription_exposed_id" must be a string, but got: undefined (on API request to `GET /v1/subscriptions/{subscription_exposed_id}`)
POST /api/auth/stripe/webhook 400 in 18ms
and boom same error
bekacru
bekacru•2d ago
oh I think the issue is with immediate cancel let me check that
Vexoa
VexoaOP•2d ago
Thanks a lot The thing is I want immediate cancel support, as i want support for that so support agents can instantly cut their sub off you need the event data for instant cancel?
bekacru
bekacru•2d ago
should be fixed now
Vexoa
VexoaOP•2d ago
will test it Nope @bekacru
2025-03-02T12:49:46.668Z ERROR [Better Auth]: Stripe webhook failed. Error: Stripe: Argument "subscription_exposed_id" must be a string, but got: undefined (on API request to `GET /v1/subscriptions/{subscription_exposed_id}`)
POST /api/auth/stripe/webhook 400 in 12ms
2025-03-02T12:49:46.668Z ERROR [Better Auth]: Stripe webhook failed. Error: Stripe: Argument "subscription_exposed_id" must be a string, but got: undefined (on API request to `GET /v1/subscriptions/{subscription_exposed_id}`)
POST /api/auth/stripe/webhook 400 in 12ms
bekacru
bekacru•2d ago
is this on subscription.delete event?
Vexoa
VexoaOP•2d ago
doesn't tell me, testing clearing all cache etc see if it works
bekacru
bekacru•2d ago
check from the stripe cli webhook logs
Vexoa
VexoaOP•2d ago
GET /api/auth/subscription/list 200 in 64ms
2025-03-02T13:15:49.205Z ERROR [Better Auth]: Stripe webhook failed. Error: Stripe: Argument "subscription_exposed_id" must be a string, but got: undefined (on API request to `GET /v1/subscriptions/{subscription_exposed_id}`)
POST /api/auth/stripe/webhook 400 in 23ms
GET /api/auth/subscription/list 200 in 64ms
2025-03-02T13:15:49.205Z ERROR [Better Auth]: Stripe webhook failed. Error: Stripe: Argument "subscription_exposed_id" must be a string, but got: undefined (on API request to `GET /v1/subscriptions/{subscription_exposed_id}`)
POST /api/auth/stripe/webhook 400 in 23ms
just says this lmao Makes no sense as it says HTTP status code 200 on stripe's end but in the db no status changes r made etc want access to my repo to see if i done anything wrong? invited you to the repo I found out another problem too
2025-03-02T13:21:18.146Z ERROR [Better Auth]: Stripe webhook failed. Error: Stripe: Argument "subscription_exposed_id" must be a string, but got: undefined (on API request to `GET /v1/subscriptions/{subscription_exposed_id}`)
POST /api/auth/stripe/webhook 400 in 16ms
2025-03-02T13:21:18.146Z ERROR [Better Auth]: Stripe webhook failed. Error: Stripe: Argument "subscription_exposed_id" must be a string, but got: undefined (on API request to `GET /v1/subscriptions/{subscription_exposed_id}`)
POST /api/auth/stripe/webhook 400 in 16ms
this is the prolbem but in the onSubscriptionDeleted its not console logging at all
onSubscriptionComplete: async ({ event, subscription, stripeSubscription, plan }) => {
// Called when a subscription is successfully created
console.log(`Subscription ${subscription.id} created, event: ${event}`);
},
onSubscriptionUpdate: async ({ event, subscription }) => {
// Called when a subscription is updated
console.log(`Subscription ${subscription.id} updated, event: ${event}`);
},
onSubscriptionCancel: async ({ event, subscription, stripeSubscription, cancellationDetails }) => {
// Called when a subscription is canceled
console.log(`Subscription ${subscription.id} canceled, event: ${event}, cancellationDetails: ${cancellationDetails}, stripeSubscription: ${stripeSubscription}`);
// await sendCancellationEmail(subscription.referenceId);
},
onSubscriptionDeleted: async ({ event, subscription, stripeSubscription }) => {
// Called when a subscription is deleted
console.log(`Subscription ${subscription.id} deleted, event: ${event}, stripeSubscription: ${stripeSubscription}`);
},
onSubscriptionComplete: async ({ event, subscription, stripeSubscription, plan }) => {
// Called when a subscription is successfully created
console.log(`Subscription ${subscription.id} created, event: ${event}`);
},
onSubscriptionUpdate: async ({ event, subscription }) => {
// Called when a subscription is updated
console.log(`Subscription ${subscription.id} updated, event: ${event}`);
},
onSubscriptionCancel: async ({ event, subscription, stripeSubscription, cancellationDetails }) => {
// Called when a subscription is canceled
console.log(`Subscription ${subscription.id} canceled, event: ${event}, cancellationDetails: ${cancellationDetails}, stripeSubscription: ${stripeSubscription}`);
// await sendCancellationEmail(subscription.referenceId);
},
onSubscriptionDeleted: async ({ event, subscription, stripeSubscription }) => {
// Called when a subscription is deleted
console.log(`Subscription ${subscription.id} deleted, event: ${event}, stripeSubscription: ${stripeSubscription}`);
},
Vexoa
VexoaOP•2d ago
No description
bekacru
bekacru•2d ago
so the issue is the onSubscriptionDeleted hook isn't being called?
Vexoa
VexoaOP•2d ago
Yeah it should be I cant even tell cuz its literally not giving me enough info i gave u the repo to test it Yeah latest version has the same issues:
2025-03-02T17:18:47.591Z ERROR [Better Auth]: Stripe webhook failed. Error: Stripe: Argument "subscription_exposed_id" must be a string, but got: undefined (on API request to `GET /v1/subscriptions/{subscription_exposed_id}`)
2025-03-02T17:18:47.591Z ERROR [Better Auth]: Stripe webhook failed. Error: Stripe: Argument "subscription_exposed_id" must be a string, but got: undefined (on API request to `GET /v1/subscriptions/{subscription_exposed_id}`)
Also:
onSubscriptionDeleted: async ({ event, subscription, stripeSubscription }) => {
// Called when a subscription is deleted
console.log(`Subscription ${subscription.id} deleted`);
}
onSubscriptionDeleted: async ({ event, subscription, stripeSubscription }) => {
// Called when a subscription is deleted
console.log(`Subscription ${subscription.id} deleted`);
}
This doesn't work at all

Did you find this page helpful?