Beta testing stripe plugin

Hey! I'm trying to follow these: https://www.better-auth.com/docs/plugins/stripe instructions to get the stripe plugin working, but I get stuck at the db migration step, here's the error I'm getting:
npx @better-auth/cli generate
2025-03-02T08:26:29.329Z ERROR [Better Auth]: [#better-auth]: Couldn't read your auth config. Error: Neither apiKey nor config.authenticator provided
at Stripe._setAuthenticator (file:///home/dd0k/prog/site/node_modules/stripe/esm/stripe.core.js:163:23)
at new Stripe (file:///home/dd0k/prog/site/node_modules/stripe/esm/stripe.core.js:99:14)
at /home/dd0k/prog/site/lib/auth.ts:7:22
at async Function.import (/home/dd0k/.npm/_npx/167ca1f116d365e6/node_modules/jiti/dist/jiti.cjs:1:199772)
at async resolveConfig (file:///home/dd0k/.npm/_npx/167ca1f116d365e6/node_modules/c12/dist/shared/c12.PQMoYrit.mjs:346:18)
at async loadConfig (file:///home/dd0k/.npm/_npx/167ca1f116d365e6/node_modules/c12/dist/shared/c12.PQMoYrit.mjs:146:23)
at async getConfig (file:///home/dd0k/.npm/_npx/167ca1f116d365e6/node_modules/@better-auth/cli/dist/index.mjs:234:30)
at async Command.generateAction (file:///home/dd0k/.npm/_npx/167ca1f116d365e6/node_modules/@better-auth/cli/dist/index.mjs:643:18)
npx @better-auth/cli generate
2025-03-02T08:26:29.329Z ERROR [Better Auth]: [#better-auth]: Couldn't read your auth config. Error: Neither apiKey nor config.authenticator provided
at Stripe._setAuthenticator (file:///home/dd0k/prog/site/node_modules/stripe/esm/stripe.core.js:163:23)
at new Stripe (file:///home/dd0k/prog/site/node_modules/stripe/esm/stripe.core.js:99:14)
at /home/dd0k/prog/site/lib/auth.ts:7:22
at async Function.import (/home/dd0k/.npm/_npx/167ca1f116d365e6/node_modules/jiti/dist/jiti.cjs:1:199772)
at async resolveConfig (file:///home/dd0k/.npm/_npx/167ca1f116d365e6/node_modules/c12/dist/shared/c12.PQMoYrit.mjs:346:18)
at async loadConfig (file:///home/dd0k/.npm/_npx/167ca1f116d365e6/node_modules/c12/dist/shared/c12.PQMoYrit.mjs:146:23)
at async getConfig (file:///home/dd0k/.npm/_npx/167ca1f116d365e6/node_modules/@better-auth/cli/dist/index.mjs:234:30)
at async Command.generateAction (file:///home/dd0k/.npm/_npx/167ca1f116d365e6/node_modules/@better-auth/cli/dist/index.mjs:643:18)
I'm using prisma connected to a neon db, any help is appreciated!
Stripe | Better Auth
Stripe plugin for Better Auth to manage subscriptions and payments.
11 Replies
Vexoa
Vexoa2d ago
GitHub
stripe plugin doesnt generate customer table with the drizzle adapt...
Is this suited for github? Yes, this is suited for github To Reproduce did not generate to customer table Current vs. Expected behavior to get the schema spesified here: https://www.better-auth.com...
Vexoa
Vexoa2d ago
go there and look at the code i provided its due to env variables missing
yam0960
yam09602d ago
did it worked for you with drizzle adapter?
Vexoa
Vexoa2d ago
Yeah it did
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')
});
take that
dD0K
dD0KOP2d ago
The code you have in your Auth.ts is very similar to the code I have
Vexoa
Vexoa2d ago
u got the env variables set?
dD0K
dD0KOP2d ago
I have the env variables for stripe webhook secret In my .env.local
Vexoa
Vexoa2d ago
STRIPE_WEBHOOK_SECRET is required too
dD0K
dD0KOP2d ago
Um, yeah, I have stripe webhook secret ^
Vexoa
Vexoa2d ago
oh no clue then
dD0K
dD0KOP2d ago
import { betterAuth } from "better-auth";
import { prismaAdapter } from "better-auth/adapters/prisma";
import { PrismaClient } from "@prisma/client";

import { stripe } from "@better-auth/stripe";
import Stripe from "stripe";
const stripeClient = new Stripe(process.env.STRIPE_SECRET_KEY as string);

const prisma = new PrismaClient();
export const auth = betterAuth({
database: prismaAdapter(prisma, {
provider: "postgresql",
}),
socialProviders: {
github: {
clientId: process.env.AUTH_GITHUB_ID as string,
clientSecret: process.env.AUTH_GITHUB_SECRET as string,
},
google: {
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
},
},
plugins: [
stripe({
stripeClient,
stripeWebhookSecret: process.env.STRIPE_WEBHOOK_SECRET!,
createCustomerOnSignUp: true,
subscription: {
enabled: true,
plans: [
{
name: "basic",
priceId: "price_1QxY9oQeJndFgkfkUFjAEnH4",
},
],
},
}),
],
});
import { betterAuth } from "better-auth";
import { prismaAdapter } from "better-auth/adapters/prisma";
import { PrismaClient } from "@prisma/client";

import { stripe } from "@better-auth/stripe";
import Stripe from "stripe";
const stripeClient = new Stripe(process.env.STRIPE_SECRET_KEY as string);

const prisma = new PrismaClient();
export const auth = betterAuth({
database: prismaAdapter(prisma, {
provider: "postgresql",
}),
socialProviders: {
github: {
clientId: process.env.AUTH_GITHUB_ID as string,
clientSecret: process.env.AUTH_GITHUB_SECRET as string,
},
google: {
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
},
},
plugins: [
stripe({
stripeClient,
stripeWebhookSecret: process.env.STRIPE_WEBHOOK_SECRET!,
createCustomerOnSignUp: true,
subscription: {
enabled: true,
plans: [
{
name: "basic",
priceId: "price_1QxY9oQeJndFgkfkUFjAEnH4",
},
],
},
}),
],
});
all the env variables I'm using here exist if anyone else has this issue, for some reason my auth.ts file was looking for env variables in .env and not .env.local

Did you find this page helpful?