From d68bd974624d6b6006bfeaeba7be8f078dd73a63 Mon Sep 17 00:00:00 2001 From: Matt Aitken Date: Fri, 1 Dec 2023 15:50:25 +0000 Subject: [PATCH] The Invoice and Manage card details links are working --- .../app/presenters/BillingPresenter.server.ts | 14 ++++++++++++++ .../_app.orgs.$organizationSlug.billing/route.tsx | 13 +++++++++---- apps/webapp/package.json | 2 +- pnpm-lock.yaml | 8 ++++---- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/apps/webapp/app/presenters/BillingPresenter.server.ts b/apps/webapp/app/presenters/BillingPresenter.server.ts index c1d3f53f5..4818facfd 100644 --- a/apps/webapp/app/presenters/BillingPresenter.server.ts +++ b/apps/webapp/app/presenters/BillingPresenter.server.ts @@ -1,6 +1,8 @@ import { BillingClient } from "@trigger.dev/billing"; import { PrismaClient, prisma } from "~/db.server"; +import { env } from "~/env.server"; import { logger } from "~/services/logger.server"; +import { organizationBillingPath } from "~/utils/pathBuilder"; export class BillingPresenter { #billingClient: BillingClient | undefined; @@ -68,4 +70,16 @@ export class BillingPresenter { return undefined; } } + + async customerPortalUrl(orgId: string, orgSlug: string) { + if (!this.#billingClient) return undefined; + try { + return this.#billingClient.createPortalSession(orgId, { + returnUrl: `${env.APP_ORIGIN}${organizationBillingPath({ slug: orgSlug })}`, + }); + } catch (e) { + logger.error("Error getting customer portal Url", { orgId, error: e }); + return undefined; + } + } } diff --git a/apps/webapp/app/routes/_app.orgs.$organizationSlug.billing/route.tsx b/apps/webapp/app/routes/_app.orgs.$organizationSlug.billing/route.tsx index 016746e50..0b003998f 100644 --- a/apps/webapp/app/routes/_app.orgs.$organizationSlug.billing/route.tsx +++ b/apps/webapp/app/routes/_app.orgs.$organizationSlug.billing/route.tsx @@ -25,6 +25,8 @@ import { useCurrentPlan } from "../_app.orgs.$organizationSlug/route"; import { useFeatures } from "~/hooks/useFeatures"; import { DateTime } from "~/components/primitives/DateTime"; import { formatDuration, formatDurationMilliseconds } from "~/utils"; +import { featuresForRequest } from "~/features.server"; +import { BillingPresenter } from "~/presenters/BillingPresenter.server"; export async function loader({ params, request }: LoaderFunctionArgs) { const userId = await requireUserId(request); @@ -37,9 +39,12 @@ export async function loader({ params, request }: LoaderFunctionArgs) { throw new Response(null, { status: 404 }); } - //todo generate a Stripe customer portal link, if managed cloud + const { isManagedCloud } = featuresForRequest(request); + const billingPresenter = new BillingPresenter(isManagedCloud); + const portal = await billingPresenter.customerPortalUrl(data.id, organizationSlug); + const stripePortalLink = portal?.success ? portal?.customerPortalUrl : undefined; - return typedjson({ ...data, stripePortalLink: undefined }); + return typedjson({ ...data, stripePortalLink }); } export const handle: Handle = { @@ -62,10 +67,10 @@ export default function Page() { <> {stripePortalLink && ( <> - + Invoices - + Manage card details diff --git a/apps/webapp/package.json b/apps/webapp/package.json index b2068a64a..e461849d2 100644 --- a/apps/webapp/package.json +++ b/apps/webapp/package.json @@ -65,7 +65,7 @@ "@tabler/icons-react": "^2.39.0", "@tailwindcss/container-queries": "^0.1.1", "@team-plain/typescript-sdk": "^3.5.0", - "@trigger.dev/billing": "^1.0.5", + "@trigger.dev/billing": "^1.0.7", "@trigger.dev/companyicons": "^1.5.32", "@trigger.dev/core": "workspace:*", "@trigger.dev/core-backend": "workspace:*", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 299681080..e8a19aca5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -130,7 +130,7 @@ importers: '@tailwindcss/typography': ^0.5.9 '@team-plain/typescript-sdk': ^3.5.0 '@total-typescript/ts-reset': ^0.4.2 - '@trigger.dev/billing': ^1.0.5 + '@trigger.dev/billing': ^1.0.7 '@trigger.dev/companyicons': ^1.5.32 '@trigger.dev/core': workspace:* '@trigger.dev/core-backend': workspace:* @@ -268,7 +268,7 @@ importers: '@tabler/icons-react': 2.40.0_react@18.2.0 '@tailwindcss/container-queries': 0.1.1_tailwindcss@3.3.2 '@team-plain/typescript-sdk': 3.5.0 - '@trigger.dev/billing': 1.0.5 + '@trigger.dev/billing': 1.0.7 '@trigger.dev/companyicons': 1.5.32_biqbaboplfbrettd7655fr4n2y '@trigger.dev/core': link:../../packages/core '@trigger.dev/core-backend': link:../../packages/core-backend @@ -14333,8 +14333,8 @@ packages: resolution: {integrity: sha512-vqd7ZUDSrXFVT1n8b2kc3LnklncDQFPvR58yUS1kEP23/nHPAO9l1lMjUfnPrXYYk4Hj54rrLKMW5ipwk7k09A==} dev: true - /@trigger.dev/billing/1.0.5: - resolution: {integrity: sha512-mx5yr73OeJc7FXw//RNEXA9nZKkR15fK1hPFxlZjrJtYZX9znr7KrFd9ny0zL8bhZGWDqQwXtRYUdKsVVEqSow==} + /@trigger.dev/billing/1.0.7: + resolution: {integrity: sha512-ys1yQjIuJZ7chGS3wsVLzjsHif4bN5c2u/GG4PYGOECjIFXEifZsmIqAFWIEIh4Kxh7uYR3qMh/noTREv4SUxA==} dependencies: zod: 3.22.3 dev: false