-
Notifications
You must be signed in to change notification settings - Fork 505
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(billing): a user can add payment while upgrading their plan
- Loading branch information
Showing
6 changed files
with
17,655 additions
and
14,890 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,17 +3,20 @@ import { Code } from "@/components/ui/code"; | |
import { getTenantId } from "@/lib/auth"; | ||
import { db, eq, schema } from "@/lib/db"; | ||
import { stripeEnv } from "@/lib/env"; | ||
import { PostHogClient } from "@/lib/posthog"; | ||
import { currentUser } from "@clerk/nextjs"; | ||
import { redirect } from "next/navigation"; | ||
import Stripe from "stripe"; | ||
|
||
type Props = { | ||
searchParams: { | ||
session_id: string; | ||
new_plan: "free" | "pro" | undefined; | ||
}; | ||
}; | ||
|
||
export default async function StripeSuccess(props: Props) { | ||
const { session_id, new_plan } = props.searchParams; | ||
const tenantId = getTenantId(); | ||
if (!tenantId) { | ||
return redirect("/auth/sign-in"); | ||
|
@@ -44,13 +47,13 @@ export default async function StripeSuccess(props: Props) { | |
typescript: true, | ||
}); | ||
|
||
const session = await stripe.checkout.sessions.retrieve(props.searchParams.session_id); | ||
const session = await stripe.checkout.sessions.retrieve(session_id); | ||
if (!session) { | ||
return ( | ||
<EmptyPlaceholder> | ||
<EmptyPlaceholder.Title>Stripe session not found</EmptyPlaceholder.Title> | ||
<EmptyPlaceholder.Description> | ||
The Stripe session <Code>{props.searchParams.session_id}</Code> you are trying to access | ||
The Stripe session <Code>{session_id}</Code> you are trying to access | ||
does not exist. Please contact [email protected]. | ||
</EmptyPlaceholder.Description> | ||
</EmptyPlaceholder> | ||
|
@@ -69,14 +72,25 @@ export default async function StripeSuccess(props: Props) { | |
); | ||
} | ||
|
||
const isChangingPlan = new_plan && new_plan !== ws.plan; | ||
|
||
await db | ||
.update(schema.workspaces) | ||
.set({ | ||
stripeCustomerId: customer.id, | ||
stripeSubscriptionId: session.subscription as string, | ||
trialEnds: null, | ||
...(isChangingPlan ? {plan: new_plan} :{}), | ||
}) | ||
.where(eq(schema.workspaces.id, ws.id)); | ||
|
||
if (isChangingPlan) { | ||
PostHogClient.capture({ | ||
distinctId: tenantId, | ||
event: 'plan_changed', | ||
properties: { plan: new_plan, workspace: ws.id } | ||
}); | ||
} | ||
|
||
return redirect("/settings/billing"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { PostHog } from 'posthog-node' | ||
|
||
class PostHogClientWrapper { | ||
private static instance: PostHog | null = null; | ||
|
||
private constructor() {} | ||
|
||
public static getInstance(): PostHog { | ||
if (!PostHogClientWrapper.instance) { | ||
if (!process.env.NEXT_PUBLIC_POSTHOG_KEY || !process.env.NEXT_PUBLIC_POSTHOG_HOST) { | ||
console.warn('PostHog key is missing. Analytics data will not be sent.'); | ||
// Return a mock client when the key is not present | ||
PostHogClientWrapper.instance = { | ||
capture: () => {}, | ||
// Add other methods from PostHog, implementing them as no-ops | ||
} as unknown as PostHog; | ||
} else { | ||
PostHogClientWrapper.instance = new PostHog(process.env.NEXT_PUBLIC_POSTHOG_KEY, { | ||
host: process.env.NEXT_PUBLIC_POSTHOG_HOST, | ||
flushAt: 1, | ||
flushInterval: 0 | ||
}); | ||
} | ||
} | ||
return PostHogClientWrapper.instance; | ||
} | ||
} | ||
|
||
export const PostHogClient = PostHogClientWrapper.getInstance(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.