feat: add free tier Stripe subscription

This commit is contained in:
David Nguyen
2023-09-18 22:33:07 +10:00
parent 9dcab76cd5
commit 773566f193
13 changed files with 298 additions and 58 deletions

View File

@ -0,0 +1,19 @@
import { stripe } from '@documenso/lib/server-only/stripe';
export const getStripeCustomerByEmail = async (email: string) => {
const foundStripeCustomers = await stripe.customers.list({
email,
});
return foundStripeCustomers.data[0] ?? null;
};
export const getStripeCustomerById = async (stripeCustomerId: string) => {
try {
const stripeCustomer = await stripe.customers.retrieve(stripeCustomerId);
return !stripeCustomer.deleted ? stripeCustomer : null;
} catch {
return null;
}
};

View File

@ -0,0 +1,17 @@
/*
Warnings:
- A unique constraint covering the columns `[userId]` on the table `Subscription` will be added. If there are existing duplicate values, this will fail.
- Made the column `customerId` on table `Subscription` required. This step will fail if there are existing NULL values in that column.
*/
DELETE FROM "Subscription"
WHERE "customerId" IS NULL;
-- AlterTable
ALTER TABLE "Subscription" ADD COLUMN "cancelAtPeriodEnd" BOOLEAN NOT NULL DEFAULT false,
ALTER COLUMN "customerId" SET NOT NULL;
-- CreateIndex
CREATE UNIQUE INDEX "Subscription_userId_key" ON "Subscription"("userId");

View File

@ -41,15 +41,16 @@ enum SubscriptionStatus {
}
model Subscription {
id Int @id @default(autoincrement())
status SubscriptionStatus @default(INACTIVE)
planId String?
priceId String?
customerId String?
periodEnd DateTime?
userId Int
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
id Int @id @default(autoincrement())
status SubscriptionStatus @default(INACTIVE)
planId String?
priceId String?
customerId String
periodEnd DateTime?
userId Int @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
cancelAtPeriodEnd Boolean @default(false)
User User @relation(fields: [userId], references: [id], onDelete: Cascade)

View File

@ -9,6 +9,7 @@ declare namespace NodeJS {
NEXT_PUBLIC_STRIPE_COMMUNITY_PLAN_MONTHLY_PRICE_ID: string;
NEXT_PUBLIC_STRIPE_COMMUNITY_PLAN_YEARLY_PRICE_ID: string;
NEXT_PUBLIC_STRIPE_FREE_PLAN_ID?: string;
NEXT_PRIVATE_STRIPE_API_KEY: string;
NEXT_PRIVATE_STRIPE_WEBHOOK_SECRET: string;

View File

@ -56,14 +56,14 @@ export interface ButtonProps
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
({ className, variant, size, asChild = false, loading, ...props }, ref) => {
if (asChild) {
return (
<Slot className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />
);
}
const showLoader = props.loading === true;
const showLoader = loading === true;
const isDisabled = props.disabled || showLoader;
return (