Stripe Customer Portal #882

Closed
opened 2026-03-13 08:08:41 -05:00 by GiteaMirror · 3 comments
Owner

Originally created by @joeychrys on GitHub (Mar 20, 2025).

Is this suited for github?

  • Yes, this is suited for github

Hey, I think it would be nice to have a way for a user to access the stripe portal directly.

Describe the solution you'd like

Something like the following would work. I've already tested it. I'll create a PR for it in a bit.

customerPortal: createAuthEndpoint(
			"/subscription/portal",
			{
				method: "POST",
				body: z.object({
					returnUrl: z.string().default("/"),
				}),
				use: [
					sessionMiddleware,
					originCheck((ctx) => ctx.body.returnUrl),
				],
			},
			async (ctx) => {
				const { user } = ctx.context.session;
				
				if (!user.stripeCustomerId) {
					throw new APIError("BAD_REQUEST", {
						message: "No Stripe customer found for this user",
					});
				}

				try {
					const { url } = await client.billingPortal.sessions.create({
						customer: user.stripeCustomerId,
						return_url: getUrl(ctx, ctx.body.returnUrl),
					});

					return ctx.json({
						url,
						redirect: true,
					});
				} catch (error) {
					ctx.context.logger.error("Error creating portal session", error);
					throw new APIError("INTERNAL_SERVER_ERROR", {
						message: "Failed to create customer portal session",
					});
				}
			},
		),

Describe alternatives you've considered

You could manually create the portal but it would be somewhat inconvenient.

Additional context

No response

Originally created by @joeychrys on GitHub (Mar 20, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### Is your feature request related to a problem? Please describe. Hey, I think it would be nice to have a way for a user to access the stripe portal directly. ### Describe the solution you'd like Something like the following would work. I've already tested it. I'll create a PR for it in a bit. ``` customerPortal: createAuthEndpoint( "/subscription/portal", { method: "POST", body: z.object({ returnUrl: z.string().default("/"), }), use: [ sessionMiddleware, originCheck((ctx) => ctx.body.returnUrl), ], }, async (ctx) => { const { user } = ctx.context.session; if (!user.stripeCustomerId) { throw new APIError("BAD_REQUEST", { message: "No Stripe customer found for this user", }); } try { const { url } = await client.billingPortal.sessions.create({ customer: user.stripeCustomerId, return_url: getUrl(ctx, ctx.body.returnUrl), }); return ctx.json({ url, redirect: true, }); } catch (error) { ctx.context.logger.error("Error creating portal session", error); throw new APIError("INTERNAL_SERVER_ERROR", { message: "Failed to create customer portal session", }); } }, ), ``` ### Describe alternatives you've considered You could manually create the portal but it would be somewhat inconvenient. ### Additional context _No response_
Author
Owner

@mazeincoding commented on GitHub (May 1, 2025):

+1 for this

I see you already made a PR though - gonna check it out

@mazeincoding commented on GitHub (May 1, 2025): +1 for this I see you already made a PR though - gonna check it out
Author
Owner

@joacohoyos commented on GitHub (Jul 25, 2025):

Any update on this getting merged any time soon?

@joacohoyos commented on GitHub (Jul 25, 2025): Any update on this getting merged any time soon?
Author
Owner

@Bekacru commented on GitHub (Oct 6, 2025):

I think this should already avalible. Feel free to tag me if not

@Bekacru commented on GitHub (Oct 6, 2025): I think this should already avalible. Feel free to tag me if not
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#882